如何忽略fmt.Sprintf的额外字段

Pat*_*ick 4 go

我有一个Golang程序,它从命令行读取一个字符串参数并将其传递给fmt.Sprintf函数.假设tmp_str是命令行中的目标字符串.

package main

import "fmt"

func main() {
    tmp_str := "hello %s"
    str := fmt.Sprintf(tmp_str, "world")
    fmt.Println(str)
}
Run Code Online (Sandbox Code Playgroud)

在某些情况下,程序将传递一个完整的字符串,如"Hello Friends",而不是字符串模板..程序将发生恐慌并返回:

你好朋友%!(EXTRA string = world)

那么,如何忽略fmt.Sprintf的额外字段?

Ste*_*ein 9

在这种特殊情况下,您可以要求命令行用户始终提供 %s 动词,并解释他们可以将字符串截断为零长度:

Hello Friends%.0s
Run Code Online (Sandbox Code Playgroud)

甚至更短:

Hello Friends%.s
Run Code Online (Sandbox Code Playgroud)

输出很简单:

大家好


Den*_*ret 7

是的,您可以通过将传递给您的参数切换到可变参数Sprintf函数来实现:

func TruncatingSprintf(str string, args ...interface{}) (string, error) {
    n := strings.Count(str, "%s")
    if n > len(args) {
        return "", errors.New("Unexpected string:" + str)
    }
    return fmt.Sprintf(str, args[:n]...), nil
}

func main() {
    tmp_str := "hello %s %s %s"         // don't hesitate to add many %s here
    str, err := TruncatingSprintf(tmp_str, "world") // or many arguments here
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(str)
}
Run Code Online (Sandbox Code Playgroud)

示范1

演示2(即使有比参数多%s的输出,也会输出不同的版本)

但是你通常不使用动态格式化的字符串,这是不安全的,如果你想接受任何字符串,你也应该调整这个代码不要窒息%%s.如果你冒险这么远,那么你应该看一下模板(这会让你使用命名字符串,因此丢失的字符串不一定是最后一个).

  • @ william.taylor.09好主意.我接受了你的错误处理并将其添加到答案中,以便没有人会错过它.但请注意,可以考虑使用%s而不是参数*OK*(只有一些"MISSING") (2认同)