印刷せずにGo文字列をフォーマットしますか?
シンプルな文字列
「シンプルな」文字列 (通常 1 行に収まるもの) に対する最もシンプルなソリューションは、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.
ヒント: 単に異なる型の値を連結したい場合、Sprint()
がまさにこれを行うため、format string を必要とする Sprintf()
は自動的に必要ではないかもしれません。 この例を参照してください。
i := 23s := fmt.Sprint("") // s will be ""
string
だけを連結する場合は、strings.Join()
を使用して、カスタム セパレータ string
(連結する文字列の間に配置される)を指定することもできます。
複雑な文字列 (ドキュメント)
作成しようとしている文字列がより複雑な場合 (例えば複数行の電子メールメッセージ)、fmt.Sprintf()
は読みにくく、効率も悪くなります (特にこれを何度も行う場合)。
このために標準ライブラリは text/template
および html/template
パッケージを提供しています。 これらのパッケージはテキスト出力を生成するためのデータ駆動型テンプレートを実装しています。 html/template
はコードインジェクションに対して安全な HTML 出力を生成するためのものです。
template
パッケージを使用するには、基本的に静的テキストを含む string
値 (ファイル名のみを提供する場合はファイルから生成されるかもしれません) と、エンジンがテンプレートを処理し、出力を生成する際に実行されるアクションという形式で、静的テンプレートを提供することが必要です。
静的テンプレートに含まれる/置換されるパラメーターを提供し、出力生成プロセスを制御することができます。 そのようなパラメータの典型的な形式は struct
s と map
値で、ネストされることがある。
例:
たとえば、次のような電子メール メッセージを生成したいとします:
Hi !Your account is ready, your user name is: You have the following roles assigned:, , ...
このような電子メール メッセージ本文を生成するには、次の静的テンプレートを使用できます。
const emailTmpl = `Hi {{.Name}}!Your account is ready, your user name is: {{.UserName}}You have the following roles assigned:{{range $i, $r := .Roles}}{{if $i}}, {{end}}{{.}}{{end}}`
そして、これを実行するためのデータを以下のように用意します。
data := mapinterface{}{ "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: bob92You have the following roles assigned:dbteam, uiteam, tester
これを Go Playground で試してください。
また、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 で試してみてください。
。