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

String 格式化Go字符串而不打印?,string,go,formatting,string-formatting,String,Go,Formatting,String Formatting,有没有一种简单的方法可以在Go中格式化字符串而不打印字符串 我可以做到: bar := "bar" fmt.Printf("foo: %s", bar) 但是我希望返回格式化的字符串,而不是打印,这样我可以进一步操作它 我也可以这样做: s := "foo: " + bar 但是,当格式字符串很复杂时,这将变得很难读取,当一个或多个部分不是字符串并且必须首先转换时,这将变得很麻烦,如 i := 25 s := "foo: " + strconv.Itoa(i) 有更简单的方法吗?正是您想要

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

我可以做到:

bar := "bar"
fmt.Printf("foo: %s", bar)
但是我希望返回格式化的字符串,而不是打印,这样我可以进一步操作它

我也可以这样做:

s := "foo: " + bar
但是,当格式字符串很复杂时,这将变得很难读取,当一个或多个部分不是字符串并且必须首先转换时,这将变得很麻烦,如

i := 25
s := "foo: " + strconv.Itoa(i)
有更简单的方法吗?

正是您想要的

示例

fmt.Sprintf("foo: %s", bar)
您还可以在中看到它作为“围棋之旅”的一部分使用

1.简单字符串 对于“简单”字符串(通常是适合一行的字符串),最简单的解决方案是使用and friends(,)。这些函数类似于没有starter
S
字母的函数,但是这些
Sxxx()
变量将结果作为
字符串返回,而不是将其打印到标准输出

例如:

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.
提示:如果您只想连接不同类型的值,可能不需要自动使用
Sprint()
(需要格式字符串),因为
Sprint()
正是这样做的。请参见此示例:

i := 23
s := fmt.Sprint("[age:", i, "]") // s will be "[age:23]"
对于仅连接
字符串
s,您还可以在其中指定自定义分隔符
字符串
(放置在要连接的字符串之间)

试穿这些衣服

2.复杂字符串(文档) 如果您试图创建的字符串更复杂(例如多行电子邮件),
fmt.Sprintf()
的可读性和效率会降低(尤其是如果您必须多次这样做)

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

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

您可以提供静态模板中包含/替换的参数,这些参数可以控制输出生成过程。此类参数的典型形式是可以嵌套的
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
)。执行模板并将结果作为
字符串

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 1.10以来,
bytes.Buffer提供了更新、更快、更专业的替代方案,即:。用法非常相似:

builder := &strings.Builder{}
if err := t.Execute(builder, data); err != nil {
    panic(err)
}
s := builder.String()
试一试这个

注意:如果您提供
os.Stdout
作为目标(也实现了
io.Writer
),则还可以显示模板执行的结果:


这将把结果直接写入
os.Stdout
。在上尝试此操作。

在您的情况下,需要使用Sprintf()作为格式字符串

func-Sprintf(格式字符串,一个…接口{})字符串

Sprintf根据格式说明符格式化并返回结果字符串

s:=fmt.Sprintf(“早上好,这里是%s,我在过去的%d年里一直住在这里”,“约翰”,20岁)

您的输出将是:

早上好,我是约翰,过去20年我一直住在这里


fmt.SprintF函数返回一个字符串,您可以使用与fmt.PrintF

相同的方式格式化字符串。我们可以通过
定义新类型
格式
支持自定义新字符串类型

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)
}

我已经从模板中创建了用于字符串格式化的go项目(它允许以C#或Python样式格式化字符串,对于非常简单的情况,这只是第一个版本),您可以在这里找到它

其工作方式如下:


func TestStrFormat(t*testing.t){
strFormatResult,err:=Format(“你好,我是{0},我的年龄是{1},我在等待{2},因为我是{0}!”,
“迈克尔·乌沙科夫(666)”,“34”,“巨大成功”
assert.Nil(t,err)
assert.Equal(t,“你好,我是Michael Ushakov(邪恶领主666),我今年34岁,我在等待“巨大的成功”,因为我是Michael Ushakov(邪恶领主666)!”,strFormatResult)
strFormatResult,err=Format(“我们想知道这些值是否会被替换:{5},{4},{0}”,“一”,“二”,“三”)
assert.Nil(t,err)
Equal(t,“我们想知道这些值是否会被替换:{5},{4},一”,strFormatResult)
strFormatResult,err=Format(“无参数…:{0},{1},{2}”)
assert.Nil(t,err)
等于(t,“无参数…”:{0},{1},{2},strFormatResult)
}
func TestStrFormatComplex(t*testing.t){
strFormatResult,err:=FormatComplex(“你好{user}你在这里做什么{app}?”,映射[string]字符串{“user”:“vpupkin”,“app”:“mn_控制台”})
assert.Nil(t,err)
assert.Equal(t,“你好,vpupkin,你在这里做什么?”,strFormatResult)
}

我来到这一页是为了寻找一种格式化错误字符串的方法。所以如果有人需要
t := template.Must(template.New("email").Parse(emailTmpl))
if err := t.Execute(os.Stdout, data); err != nil {
    panic(err)
}
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)
}
package main

import "fmt"

func main() {
    
    address := "NYC"

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

}
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)

}