Answers:
Sprintf是您想要的。
例
fmt.Sprintf("foo: %s", bar)
您还可以在“ 错误”示例中看到它在使用中,作为“ A Tour of Go”的一部分。
return fmt.Sprintf("at %v, %s", e.When, e.What)
对于“简单”字符串(通常适合一行),最简单的解决方案是使用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]"
对于仅连接string
s,您还可以strings.Join()
在可以指定自定义分隔符的位置string
(放置在要连接的字符串之间)使用。
在Go Playground上尝试一下。
如果您要创建的字符串比较复杂(例如,多行电子邮件),fmt.Sprintf()
那么可读性和效率就会降低(尤其是您必须多次执行此操作时)。
为此,标准库提供了软件包text/template
和html/template
。这些软件包实现了数据驱动的模板以生成文本输出。html/template
用于生成可防止代码注入的HTML输出。它提供了与包相同的接口,text/template
并且应text/template
在输出为HTML时代替其使用。
使用template
软件包基本上需要您提供一个string
值形式的静态模板(该值可能源自文件,在这种情况下,您仅提供文件名),其中可能包含静态文本,以及在操作时执行和执行的操作。引擎处理模板并生成输出。
您可以提供静态模板中包含/替换的参数,这些参数可以控制输出生成过程。这种参数的典型形式是struct
s和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上尝试一下。
在您的情况下,您需要使用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)
您的输出将是:
早上好,我是约翰,过去二十年来我一直住在这里。
我们可以自定义一个新的String类型通过define new Type
与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)
}