文字列を印刷せずにGoで文字列をフォーマットする簡単な方法はありますか?
できます:
bar := "bar"
fmt.Printf("foo: %s", bar)
しかし、私はそれをさらに操作することができるように印刷されるのではなくフォーマットされた文字列が返されることを望みます。
私はまたのような何かをすることができます:
s := "foo: " + bar
しかし、フォーマット文字列が複雑な場合は読みにくくなり、1つまたは複数の部分が文字列ではなく、最初に変換する必要がある場合は面倒です。
i := 25
s := "foo: " + strconv.Itoa(i)
もっと簡単な方法はありますか?
"単純な"文字列(通常は一行に収まるもの)の場合、最も簡単な解決策は fmt.Sprintf()
と友達( fmt.Sprint()
、 fmt.Sprintln()
です。 )これらは開始S
文字を除いた関数に似ていますが、これらのSxxx()
の変種は標準出力にそれらを出力する代わりにstring
として結果を返します。
例えば:
s := fmt.Sprintf("Hi, my name is %s and I'm %d years old.", "Bob", 23)
変数s
は次の値で初期化されます。
Hi, my name is Bob and I'm 23 years old.
ヒント:さまざまなタイプの値を連結するだけの場合は、Sprintf()
が正確に行うように、自動的にSprint()
(フォーマット文字列が必要)を使用する必要はありません。この例を参照してください。
i := 23
s := fmt.Sprint("[age:", i, "]") // s will be "[age:23]"
string
sのみを連結する場合は、 strings.Join()
を使用することもできます。ここでは、(結合する文字列の間に配置される)カスタム区切り文字string
を指定できます。
これらを Go Playground で試してください。
作成しようとしている文字列がもっと複雑な場合(複数行の電子メールメッセージなど)、fmt.Sprintf()
は読みにくく効率が悪くなります(特にこれを何度も行わなければならない場合)。
このため、標準ライブラリは text/template
と html/template
のパッケージを提供しています。これらのパッケージは、テキスト出力を生成するためのデータ駆動型テンプレートを実装しています。 html/template
はコードインジェクションに対して安全なHTML出力を生成するためのものです。これはパッケージtext/template
と同じインターフェースを提供し、出力がHTMLの場合はいつでもtext/template
の代わりに使用されるべきです。
template
パッケージを使用するには、基本的に静的テキストを含むことができるstring
値(ファイル名のみを指定することができます)の形式で静的テンプレートを提供する必要があります。処理および実行されるアクションエンジンがテンプレートを処理して出力を生成したとき。
静的テンプレートに含まれている/置き換えられているパラメータ、および出力生成プロセスを制御できるパラメータを指定できます。そのようなパラメータの典型的な形式は、ネストすることができるstruct
sとmap
の値です。
例:
たとえば、次のような電子メールメッセージを生成したいとしましょう。
Hi [name]!
Your account is ready, your user name is: [user-name]
You have the following roles assigned:
[role#1], [role#2], ... [role#n]
このようなメール本文を生成するには、次の静的テンプレートを使用できます。
const emailTmpl = `Hi {{.Name}}!
Your account is ready, your user name is: {{.UserName}}
You have the following roles assigned:
{{range $i, $r := .Roles}}{{if ne $i 0}}, {{end}}{{.}}{{end}}
`
それを実行するためにこのようなデータを提供します。
data := map[string]interface{}{
"Name": "Bob",
"UserName": "bob92",
"Roles": []string{"dbteam", "uiteam", "tester"},
}
通常、テンプレートの出力は io.Writer
に書き込まれるので、結果をstring
にしたい場合は、 bytes.Buffer
(io.Writer
を実装する)を作成して書き込みます。 )テンプレートを実行し、その結果をstring
として取得します。
t := template.Must(template.New("email").Parse(emailTmpl))
buf := &bytes.Buffer{}
if err := t.Execute(buf, data); err != nil {
panic(err)
}
s := buf.String()
これは予想される出力になります。
Hi Bob!
Your account is ready, your user name is: bob92
You have the following roles assigned:
dbteam, uiteam, tester
囲碁プレイグラウンド で試してみてください。
Go 1.10以降、bytes.Buffer
のより新しく、より速く、より特殊化された代替手段が利用可能です。 strings.Builder
。使い方はよく似ています。
builder := &strings.Builder{}
if err := t.Execute(builder, data); err != nil {
panic(err)
}
s := builder.String()
これを Go Playground で試してみてください。
注:ターゲットとしてos.Stdout
を指定した場合は、テンプレートの実行結果も表示されます(これはio.Writer
も実装しています)。
t := template.Must(template.New("email").Parse(emailTmpl))
if err := t.Execute(os.Stdout, data); err != nil {
panic(err)
}
これは結果を直接os.Stdout
に書き込みます。これを Go Playground で試してみてください。
あなたの場合、あなたはフォーマット文字列のためにSprintf()を使う必要があります。
func Sprintf(format string, a ...interface{}) string
Sprintfはフォーマット指定子に従ってフォーマットし、結果の文字列を返します。
s := fmt.Sprintf("Good Morning, This is %s and I'm living here from last %d years ", "John", 20)
あなたの出力は次のようになります。
おはようございます、これはジョンです。私はここ20年間、ここに住んでいます。
fmt.SprintF関数は文字列を返すので、fmtと同じ方法で文字列をフォーマットできます。 PrintF