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

时间:2016-01-27 16:45:16

标签: go

我有一个Golang程序,它从命令行读取字符串参数并将其传递给fmt.Sprintf函数。让我们说tmp_str是来自命令行的目标字符串。

AFTER

在某些情况下,程序会传递一个完整的字符串,例如" Hello Friends",而不是字符串模板..程序会惊慌失措并返回:

  

Hello Friends%!(EXTRA string = world)

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

5 个答案:

答案 0 :(得分: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)
}

Demonstration 1

Demonstration 2(即使%s多于参数,也会输出不同的版本)

但是你通常不使用动态格式化字符串,这不安全,如果你想接受任何字符串,你也应该调整这段代码,使%%s上没有阻塞。 。如果你冒险这么远,那么你应该看看templates(这会让你使用命名字符串,因此丢失的字符串不一定是最后一个)。

答案 1 :(得分:4)

我同意Volker's answer,但您可以检查输入字符串:

package main

import (
    "fmt"
    "strings"
)

func main() {
    tmp_str := "hello %s"

    res := tmp_str
    if strings.Count(tmp_str, "%s") == 1 {
        res = fmt.Sprintf(tmp_str, "world")
    }
    fmt.Println(res)
}

答案 2 :(得分:2)

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

Hello Friends%.0s

甚至更短:

Hello Friends%.s

输出很简单:

  

你好朋友

答案 3 :(得分:0)

我使用这个(可能可以扩展)

Sprintf("Hello"+"%[2]s", "World", "")
Sprintf("Hello %s"+"%[2]s", "World", "")

答案 4 :(得分:-4)

你不能这样做。

您必须找到不同的解决方案。