相当于 Go 中的 Python string.format? [英] Equivalent of Python string.format in Go?

查看:25
本文介绍了相当于 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.Go 确实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?

推荐答案

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

输出(在 Go Playground 上试试):

Output (try it on the Go Playground):

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

输出(在 Go Playground 上试试):

Output (try it on the Go Playground):

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

输出(在 Go Playground 上试试):

Output (try it on the Go Playground):

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

Go Playground 上试试.

您的模板解决方案或提案也过于冗长.它可以写成这样紧凑(省略错误检查):

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

输出(在 Go Playground 上试试):

Output (try it on the Go Playground):

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天全站免登陆