string 在不打印的情况下格式化 Go 字符串?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11123865/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Format a Go string without printing?
提问by Carnegie
Is there a simple way to format a string in Go without printing the string?
有没有一种简单的方法可以在不打印字符串的情况下在 Go 中格式化字符串?
I can do:
我可以:
bar := "bar"
fmt.Printf("foo: %s", bar)
But I want the formatted string returned rather than printed so I can manipulate it further.
但我希望返回格式化的字符串而不是打印,以便我可以进一步操作它。
I could also do something like:
我也可以做类似的事情:
s := "foo: " + bar
But this becomes difficult to read when the format string is complex, and cumbersome when one or many of the parts aren't strings and have to be converted first, like
但是当格式字符串很复杂时,这变得难以阅读,而当一个或多个部分不是字符串并且必须首先转换时,这会变得很麻烦,例如
i := 25
s := "foo: " + strconv.Itoa(i)
Is there a simpler way to do this?
有没有更简单的方法来做到这一点?
回答by Sonia
Sprintfis what you are looking for.
Sprintf正是您要找的。
Example
例子
fmt.Sprintf("foo: %s", bar)
You can also see it in use in the Errors exampleas part of "A Tour of Go."
您还可以在“A Tour of Go”的Errors 示例中看到它的使用情况。
return fmt.Sprintf("at %v, %s", e.When, e.What)
回答by icza
1. Simple strings
1. 简单的字符串
For "simple" strings (typically what fits into a line) the simplest solution is using fmt.Sprintf()
and friends (fmt.Sprint()
, fmt.Sprintln()
). These are analogous to the functions without the starter S
letter, but these Sxxx()
variants return the result as a string
instead of printing them to the standard output.
对于“简单”字符串(通常适合一行的字符串),最简单的解决方案是使用fmt.Sprintf()
和朋友(fmt.Sprint()
, fmt.Sprintln()
)。这些类似于没有起始S
字母的函数,但这些Sxxx()
变体将结果作为 a 返回string
而不是将它们打印到标准输出。
For example:
例如:
s := fmt.Sprintf("Hi, my name is %s and I'm %d years old.", "Bob", 23)
The variable s
will be initialized with the value:
变量s
将被初始化为以下值:
Hi, my name is Bob and I'm 23 years old.
Tip:If you just want to concatenate values of different types, you may not automatically need to use Sprintf()
(which requires a format string) as Sprint()
does exactly this. See this example:
提示:如果您只想连接不同类型的值,您可能不需要像这样自动使用Sprintf()
(需要格式字符串)Sprint()
。看这个例子:
i := 23
s := fmt.Sprint("[age:", i, "]") // s will be "[age:23]"
For concatenating only string
s, you may also use strings.Join()
where you can specify a custom separator string
(to be placed between the strings to join).
对于仅连接string
s,您还可以使用strings.Join()
where 可以指定自定义分隔符string
(放置在要连接的字符串之间)。
Try these on the Go Playground.
在Go Playground上试试这些。
2. Complex strings (documents)
2. 复杂字符串(文档)
If the string you're trying to create is more complex (e.g. a multi-line email message), fmt.Sprintf()
becomes less readable and less efficient (especially if you have to do this many times).
如果您尝试创建的字符串更复杂(例如多行电子邮件),fmt.Sprintf()
那么可读性和效率就会降低(尤其是在您必须多次这样做的情况下)。
For this the standard library provides the packages text/template
and html/template
. These packages implement data-driven templates for generating textual output. html/template
is for generating HTML output safe against code injection. It provides the same interface as package text/template
and should be used instead of text/template
whenever the output is HTML.
为此,标准库提供了包text/template
和html/template
. 这些包实现了用于生成文本输出的数据驱动模板。html/template
用于生成对代码注入安全的 HTML 输出。它提供与包相同的接口,text/template
并且应该text/template
在输出为 HTML 时使用而不是使用。
Using the template
packages basically requires you to provide a static template in the form of a string
value (which may be originating from a file in which case you only provide the file name) which may contain static text, and actions which are processed and executed when the engine processes the template and generates the output.
使用这些template
包基本上需要您以string
值的形式提供一个静态模板(它可能源自一个文件,在这种情况下您只提供文件名),其中可能包含静态文本,以及在执行以下操作时处理和执行的操作引擎处理模板并生成输出。
You may provide parameters which are included/substituted in the static template and which may control the output generation process. Typical form of such parameters are struct
s and map
values which may be nested.
您可以提供静态模板中包含/替换的参数,这些参数可以控制输出生成过程。这些参数的典型形式是可以嵌套的struct
s 和map
值。
Example:
例子:
For example let's say you want to generate email messages that look like this:
例如,假设您要生成如下所示的电子邮件:
Hi [name]!
Your account is ready, your user name is: [user-name]
You have the following roles assigned:
[role#1], [role#2], ... [role#n]
To generate email message bodies like this, you could use the following static template:
要生成这样的电子邮件正文,您可以使用以下静态模板:
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}}
`
And provide data like this for executing it:
并提供这样的数据来执行它:
data := map[string]interface{}{
"Name": "Bob",
"UserName": "bob92",
"Roles": []string{"dbteam", "uiteam", "tester"},
}
Normally output of templates are written to an io.Writer
, so if you want the result as a string
, create and write to a bytes.Buffer
(which implements io.Writer
). Executing the template and getting the result as string
:
通常模板的输出被写入 a io.Writer
,因此如果您希望结果为 a string
,请创建并写入 a 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()
This will result in the expected output:
这将导致预期的输出:
Hi Bob!
Your account is ready, your user name is: bob92
You have the following roles assigned:
dbteam, uiteam, tester
Try it on the Go Playground.
在Go Playground上试一试。
Also note that since Go 1.10, a newer, faster, more specialized alternative is available to bytes.Buffer
which is: strings.Builder
. Usage is very similar:
另请注意,自 Go 1.10 以来,提供了一种更新、更快、更专业的替代方案bytes.Buffer
:strings.Builder
. 用法非常相似:
builder := &strings.Builder{}
if err := t.Execute(builder, data); err != nil {
panic(err)
}
s := builder.String()
Try this one on the Go Playground.
在Go Playground上试试这个。
Note: you may also display the result of a template execution if you provide os.Stdout
as the target (which also implements io.Writer
):
注意:如果您提供os.Stdout
作为目标(也实现io.Writer
),您还可以显示模板执行的结果:
t := template.Must(template.New("email").Parse(emailTmpl))
if err := t.Execute(os.Stdout, data); err != nil {
panic(err)
}
This will write the result directly to os.Stdout
. Try this on the Go Playground.
这会将结果直接写入os.Stdout
. 在Go Playground上试试这个。
回答by Kabeer Shaikh
In your case, you need to use Sprintf() for format string.
在您的情况下,您需要使用 Sprintf() 作为格式字符串。
func Sprintf(format string, a ...interface{}) string
func Sprintf(format string, a ...interface{}) string
Sprintf formats according to a format specifier and returns the resulting string.
Sprintf 根据格式说明符格式化并返回结果字符串。
s := fmt.Sprintf("Good Morning, This is %s and I'm living here from last %d years ", "John", 20)
s := fmt.Sprintf("Good Morning, This is %s and I'm living here from last %d years ", "John", 20)
Your output will be :
您的输出将是:
Good Morning, This is John and I'm living here from last 20 years.
早安,我是约翰,我在这里住了 20 年。
回答by Mo-Gang
fmt.SprintFfunction returns a string and you can format the string the very same way you would have with fmt.PrintF
fmt.SprintF函数返回一个字符串,您可以像使用fmt.PrintF一样格式化字符串
回答by ahuigo
We can custom A new String type via define new Type
with Format
support.
我们可以自定义一个新的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)
}