格式化Go字符串而不打印?

Car*_*gie 346 string formatting string-formatting go

是否有一种简单的方法来在Go中格式化字符串而不打印字符串?

我可以:

bar := "bar"
fmt.Printf("foo: %s", bar)
Run Code Online (Sandbox Code Playgroud)

但我希望返回格式化的字符串而不是打印,以便我可以进一步操作它.

我也可以这样做:

s := "foo: " + bar
Run Code Online (Sandbox Code Playgroud)

但是当格式字符串很复杂时很难读取,当一个或多个部分不是字符串并且必须先转换时很麻烦,就像

i := 25
s := "foo: " + strconv.Itoa(i)
Run Code Online (Sandbox Code Playgroud)

我是Go的新手 - 我的背景是Ruby,这很简单.有更简单的方法吗?

Son*_*nia 430

Sprintf正是您的目标.

fmt.Sprintf("foo: %s", bar)
Run Code Online (Sandbox Code Playgroud)

你也可以在Errors示例中看到它作为"A Tour of Go"的一部分使用.

return fmt.Sprintf("at %v, %s", e.When, e.What)
Run Code Online (Sandbox Code Playgroud)

  • 这封信很重要,它被称为动词,基本上它让Sprintf知道变量是什么类型,这样如果它接收65并且动词是%d它将打印数字65但是如果动词是%c它将打印字符'一个'.请参阅:https://golang.org/pkg/fmt/#hdr-Printing (15认同)
  • 在问题之后发信吗?可能是%y和%q?或%y和%y (6认同)
  • 为什么叫Sprintf?S 代表字符串,f 代表格式?如果函数不输出到屏幕,则 print 是函数名称的一部分,这很奇怪。这让我困惑了一段时间... (6认同)

icz*_*cza 180

1.简单的字符串

对于"简单"字符串(通常适用于一行),最简单的解决方案是使用fmt.Sprintf()和朋友(fmt.Sprint(),fmt.Sprintln()).这些类似于没有起始S字母的函数,但这些Sxxx()变量将结果作为a string而不是将它们打印到标准输出.

例如:

s := fmt.Sprintf("Hi, my name is %s and I'm %d years old.", "Bob", 23)
Run Code Online (Sandbox Code Playgroud)

该变量s将使用以下值初始化:

Hi, my name is Bob and I'm 23 years old.
Run Code Online (Sandbox Code Playgroud)

提示:如果您只想连接不同类型的值,则可能不会自动使用Sprintf()(这需要格式字符串),Sprint()就像这样.看这个例子:

i := 23
s := fmt.Sprint("[age:", i, "]") // s will be "[age:23]"
Run Code Online (Sandbox Code Playgroud)

对于仅连接strings,您还可以使用strings.Join()指定自定义分隔符的位置string(放置在要连接的字符串之间).

Go Playground尝试这些.

2.复杂的字符串(文件)

如果您尝试创建的字符串更复杂(例如,多行电子邮件消息),fmt.Sprintf()则可读性降低且效率降低(特别是如果您必须多次执行此操作).

为此,标准库提供包text/templatehtml/template.这些包实现了数据驱动的模板,用于生成文本输出.html/template用于生成HTML输出,以防止代码注入.它提供与包相同的接口text/template,应该使用它而不是text/template输出是HTML时.

使用这些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]
Run Code Online (Sandbox Code Playgroud)

要生成这样的电子邮件正文,您可以使用以下静态模板:

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}}
`
Run Code Online (Sandbox Code Playgroud)

并提供这样的数据来执行它:

data := map[string]interface{}{
    "Name":     "Bob",
    "UserName": "bob92",
    "Roles":    []string{"dbteam", "uiteam", "tester"},
}
Run Code Online (Sandbox Code Playgroud)

通常将模板的输出写入a io.Writer,因此如果要将结果作为a 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()
Run Code Online (Sandbox Code Playgroud)

这将产生预期的输出:

Hi Bob!

Your account is ready, your user name is: bob92

You have the following roles assigned:
dbteam, uiteam, tester
Run Code Online (Sandbox Code Playgroud)

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()
Run Code Online (Sandbox Code Playgroud)

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)
}
Run Code Online (Sandbox Code Playgroud)

这将直接将结果写入os.Stdout.在Go Playground尝试这个.


Ran*_*oon 7

尝试使用Sprintf(); 它不会打印输出,而是将其保存以供将来使用。看一下这个。

package main

import "fmt"

func main() {
    
    address := "NYC"

    fmt.Sprintf("I live in %v", address)

}
Run Code Online (Sandbox Code Playgroud)

当您运行此代码时,它不会输出任何内容。但是,一旦将 分配Sprintf()给单独的变量,它就可以用于将来的目的。

package main

import "fmt"

func main() {
    
    address := "NYC"

    fmt.Sprintf("I live in %v", address)

    var city = fmt.Sprintf("lives in %v", address)
    fmt.Println("Michael",city)

}
Run Code Online (Sandbox Code Playgroud)


Mo-*_*ang 5

fmt.Sprintf函数返回一个字符串,您可以按照与使用相同的方式格式化该字符串fmt.Printf