479

文字列を印刷せずにGoで文字列をフォーマットする簡単な方法はありますか?

できます:

bar := "bar"
fmt.Printf("foo: %s", bar)

しかし、さらに操作できるように、フォーマットされた文字列を印刷するのではなく返す必要があります。

私は次のようなこともできます:

s := "foo: " + bar

しかし、フォーマット文字列が複雑な場合、これは読みにくくなり、1つまたは多くの部分が文字列ではなく、最初に変換する必要がある場合は面倒になります。

i := 25
s := "foo: " + strconv.Itoa(i)

これを行うためのより簡単な方法はありますか?

4

9 に答える 9

603

Sprintfはあなたが探しているものです。

fmt.Sprintf("foo: %s", bar)

また、「A Tour of Go」の一部としてエラーの例で使用されていることも確認できます。

return fmt.Sprintf("at %v, %s", e.When, e.What)
于 2012-06-20T16:43:59.803 に答える
231

1. シンプルな文字列

「単純な」文字列 (通常は 1 行に収まるもの) の場合、最も単純な解決策は、fmt.Sprintf()and friends ( fmt.Sprint(), fmt.Sprintln()) を使用することです。Sこれらはスターターレターのない関数に似ていますが、これらのSxxx()バリアントは結果をstring標準出力に出力する代わりに a として返します。

例えば:

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]"

stringsのみを連結する場合は、 (結合する文字列の間に配置する)strings.Join()カスタム セパレータを指定できる場所を使用することもできます。string

Go Playgroundでこれらを試してみてください。

2. 複雑な文字列 (ドキュメント)

作成しようとしている文字列がより複雑な場合 (複数行の電子メール メッセージなど)、fmt.Sprintf()読みにくく効率が悪くなります (特にこれを何度も行う必要がある場合)。

このために、標準ライブラリはパッケージtext/templatehtml/template. これらのパッケージは、テキスト出力を生成するためのデータ駆動型テンプレートを実装します。html/templateコードインジェクションに対して安全な HTML 出力を生成するためのものです。パッケージと同じインターフェイスを提供し、出力が HTML の場合は常にtext/template代わりに使用する必要があります。text/template

パッケージを使用するには、template基本的に、静的テキストを含む可能性のある値の形式で静的テンプレートを提供する必要がありstringます (この場合、ファイル名のみを提供する場合はファイルに由来する可能性があります)。エンジンはテンプレートを処理し、出力を生成します。

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

于 2015-07-31T09:06:01.600 に答える
0

fmt.SprintF関数は文字列を返し、文字列をフォーマットするのとまったく同じ方法でフォーマットできますfmt.PrintF

于 2018-06-20T06:47:31.903 に答える