首页 文章

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

提问于
浏览
266

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

我可以:

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

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

我也可以这样做:

s := "foo: " + bar

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

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

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

4 回答

  • 143

    fmt.SprintF 函数返回一个字符串,您可以使用与 fmt.PrintF 相同的方式格式化字符串

  • 331

    Sprintf

    Here also是在教程中使用它,"A Tour of Go."

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

    1.简单的字符串

    对于"simple"字符串(通常适用于一行),最简单的解决方案是使用fmt.Sprintf()和朋友(fmt.Sprint()fmt.Sprintln()) . 这些类似于没有starter 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.
    

    Tip: 如果您只想连接不同类型的值,则可能不会自动使用 Sprintf() (需要格式字符串),因为 Sprint() 正是如此 . 看这个例子:

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

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

    Go Playground上试试这些 .

    2.复杂字符串(文档)

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

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

    使用 template 软件包基本上要求您提供一个静态模板,其形式为 string 值(可能源自文件,在这种情况下,您只提供文件名)可能包含静态文本,以及处理和执行的操作当引擎处理模板并生成输出时 .

    您可以提供在静态模板中包含/替换的参数,这些参数可以控制输出生成过程 . 这些参数的典型形式是 structmap 值,它们可以嵌套 .

    Example:

    例如,假设您要生成如下所示的电子邮件:

    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 ne $i 0}}, {{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 .

  • -1

    在您的情况下,您需要使用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)

    你的输出将是:

    早上好,这是John和我在过去的20年里住在这里 .

相关问题