等价于Go中的Python string.format? [英] Equivalent of Python string.format in Go?

查看:117
本文介绍了等价于Go中的Python string.format?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Python中,您可以执行以下操作:

In Python, you can do this:

"File {file} had error {error}".format(file=myfile, error=err)

或者这个:

"File %(file)s had error %(error)s" % {"file": myfile, "error": err}

在Go中,最简单的选项是:

In Go, the simplest option is:

fmt.Sprintf("File %s had error %s", myfile, err)

不允许您交换格式字符串中参数的顺序,这对于 I18N . template软件包,它需要以下内容:

which doesn't let you swap the order of the parameters in the format string, which you need to do for I18N. Go does have the template package, which would require something like:

package main

import (
    "bytes"
    "text/template"
    "os"
)

func main() {
    type Params struct {
        File string
        Error string
    }

    var msg bytes.Buffer

    params := &Params{
        File: "abc",
        Error: "def",
    }

    tmpl, _ := template.New("errmsg").Parse("File {{.File}} has error {{.Error}}")
    tmpl.Execute(&msg, params)
    msg.WriteTo(os.Stdout)
}

这似乎是一条很长的路要走的错误消息.有没有更合理的选择,可以让我给出与顺序无关的字符串参数?

which seems like a long way to go for an error message. Is there a more reasonable option that allows me to give string parameters independent of order?

推荐答案

使用strings.Replacer

使用 strings.Replacer ,实现您所希望的格式化程序非常简单,紧凑.

With strings.Replacer

Using strings.Replacer, implementing a formatter of your desire is very easy and compact.

func main() {
    file, err := "/data/test.txt", "file not found"

    log("File {file} had error {error}", "{file}", file, "{error}", err)
}

func log(format string, args ...string) {
    r := strings.NewReplacer(args...)
    fmt.Println(r.Replace(format))
}

输出(在进入游乐场上尝试):

File /data/test.txt had error file not found

通过在log()函数中将括号自动添加到参数名称中,我们可以使使用起来更加愉悦:

We can make it more pleasant to use by adding the brackets to the parameter names automatically in the log() function:

func main() {
    file, err := "/data/test.txt", "file not found"

    log2("File {file} had error {error}", "file", file, "error", err)
}

func log2(format string, args ...string) {
    for i, v := range args {
        if i%2 == 0 {
            args[i] = "{" + v + "}"
        }
    }
    r := strings.NewReplacer(args...)
    fmt.Println(r.Replace(format))
}

输出(在转到操场上尝试):

File /data/test.txt had error file not found

是的,您可以说它仅接受string参数值.这是真实的.如果有更多的改进,那将是不正确的:

Yes, you could say that this only accepts string parameter values. This is true. With a little more improvement, this won't be true:

func main() {
    file, err := "/data/test.txt", 666

    log3("File {file} had error {error}", "file", file, "error", err)
}

func log3(format string, args ...interface{}) {
    args2 := make([]string, len(args))
    for i, v := range args {
        if i%2 == 0 {
            args2[i] = fmt.Sprintf("{%v}", v)
        } else {
            args2[i] = fmt.Sprint(v)
        }
    }
    r := strings.NewReplacer(args2...)
    fmt.Println(r.Replace(format))
}

输出(在进入游乐场上尝试):

File /data/test.txt had error 666

的一种变体,它接受参数作为map[string]interface{}并以string返回结果:

A variant of this to accept params as a map[string]interface{} and return the result as a string:

type P map[string]interface{}

func main() {
    file, err := "/data/test.txt", 666

    s := log33("File {file} had error {error}", P{"file": file, "error": err})
    fmt.Println(s)
}

func log33(format string, p P) string {
    args, i := make([]string, len(p)*2), 0
    for k, v := range p {
        args[i] = "{" + k + "}"
        args[i+1] = fmt.Sprint(v)
        i += 2
    }
    return strings.NewReplacer(args...).Replace(format)
}

去游乐场上尝试.

您的模板解决方案或建议也太冗长了.可以这样紧凑地编写(省略错误检查):

Your template solution or proposal is also way too verbose. It can be written as compact as this (error checks omitted):

type P map[string]interface{}

func main() {
    file, err := "/data/test.txt", 666

    log4("File {{.file}} has error {{.error}}", P{"file": file, "error": err})
}

func log4(format string, p P) {
    t := template.Must(template.New("").Parse(format))
    t.Execute(os.Stdout, p)
}

输出(在游乐场上尝试):

File /data/test.txt has error 666

如果要返回string(而不是将其打印到标准输出),则可以这样做(在

If you want to return the string (instead of printing it to the standard output), you may do it like this (try it on the Go Playground):

func log5(format string, p P) string {
    b := &bytes.Buffer{}
    template.Must(template.New("").Parse(format)).Execute(b, p)
    return b.String()
}

使用显式参数索引

在另一个答案中已经提到了这一点,但是要完成此操作,请知道相同的显式参数索引可以任意使用几次,从而导致同一参数被多次替换.在此问题中阅读有关此内容的更多信息:用相同的变量替换Sprintf中的所有变量

这篇关于等价于Go中的Python string.format?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆