印刷せずにGo文字列をフォーマットしますか?

6月 28, 2021
admin

シンプルな文字列

「シンプルな」文字列 (通常 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 値 (ファイル名のみを提供する場合はファイルから生成されるかもしれません) と、エンジンがテンプレートを処理し、出力を生成する際に実行されるアクションという形式で、静的テンプレートを提供することが必要です。

静的テンプレートに含まれる/置換されるパラメーターを提供し、出力生成プロセスを制御することができます。 そのようなパラメータの典型的な形式は structs と 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.Bufferio.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 で試してみてください。

コメントを残す

メールアドレスが公開されることはありません。