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


381

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

できます:

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

しかし、私はそれをさらに操作できるように、印刷するのではなく、フォーマットされた文字列を返したいのです。

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

s := "foo: " + bar

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

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

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

回答:


465

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

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

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

return fmt.Sprintf("at %v, %s", e.When, e.What)

6
%の後の文字は重要ですか?%yと%qでしたか?または%yおよび%y
Filip Bartuzi 2017年

17
文字は重要です。動詞と呼ばれます。基本的に、変数が65を受け取り、動詞が%dの場合、数値65を出力しますが、動詞が%cの場合、文字を出力します。 「A」。参照:golang.org/pkg/fmt/#hdr-Printing
redsalt

2
なぜSprintfと呼ばれるのですか?文字列のS、フォーマットのf?関数が画面に出力されない場合、printが関数名の一部であることは奇妙です。これはしばらく私を困惑させました...
jcollum

194

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.

ヒント:異なるタイプの値を連結するだけの場合Sprintf()は、これとSprint()まったく同じように、自動的に使用する必要はありません(フォーマット文字列が必要です)。この例を見てください:

i := 23
s := fmt.Sprint("[age:", i, "]") // s will be "[age:23]"

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

Go Playgroundでお試しください。

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

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

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

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

静的テンプレートに含まれる/置換されるパラメーターを指定して、出力生成プロセスを制御できます。そのようなパラメーターの典型的な形式は、ネストされているstructsとmapvalueです。

例:

たとえば、次のような電子メールメッセージを生成するとします。

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でお試しください。

またゴー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で試してみてください。


2

あなたのケースでは、フォーマット文字列に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年前からここに住んでいます。


0

fmt.SprintFの関数は、文字列を返すと、あなたがしなければならない非常に同じように文字列の書式を設定できfmt.PrintF


0

サポートによりdefine new Type、新しいAの文字列型をカスタムできますFormat

package main

import (
    "fmt"
    "text/template"
    "strings"
)

type String string
func (s String) Format(data map[string]interface{}) (out string, err error) {
    t := template.Must(template.New("").Parse(string(s)))
    builder := &strings.Builder{}
    if err = t.Execute(builder, data); err != nil {
        return
    }
    out = builder.String()
    return
}


func main() {
    const tmpl = `Hi {{.Name}}!  {{range $i, $r := .Roles}}{{if $i}}, {{end}}{{.}}{{end}}`
    data := map[string]interface{}{
        "Name":     "Bob",
        "Roles":    []string{"dbteam", "uiteam", "tester"},
    }

    s ,_:= String(tmpl).Format(data)
    fmt.Println(s)
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.