Golang:fmt,variadic args和%!(EXTRA type=value)错误

kokeuurv  于 2023-05-11  发布在  Go
关注(0)|答案(5)|浏览(190)

我在标准日志包周围实现了一个 Package 器,以创建具有各种日志级别的日志记录器。
我有以下接口:

type Logger interface {
  Trace(fmt string, args ...interface{})
  Debug(fmt string, args ...interface{})
  Info(fmt string, args ...interface{})
  Warn(fmt string, args ...interface{})
  Error(fmt string, args ...interface{})
  Fatal(fmt string, args ...interface{})
  Panic(fmt string, args ...interface{})
}

在实现中我有这样的东西(不是确切的代码)

func Info(format string, args ...interface{}){
  msg := fmt.Sprintf(format, args...)
  log.Println(msg)
}

现在,假设我这样调用我的库:

logger.Info("Hello %s", "World")

我得到了打印输出:“Hello %!(EXTRA string=WORLD)",而不是预期的“Hello World”。有一个类似的输出,如果我这样做

msg := fmt.Sprintf(format, args)

这将返回“Hello World%!EXTRA []interface{}=[]"。

ldxq2e6h

ldxq2e6h1#

我无法复制这种行为。你确定这不是一个简单的错误,你忘记在这里显示?
https://play.golang.org/p/-jtmll17Xj

package main

import "fmt"

func Info(format string, args ...interface{}){
    msg := fmt.Sprintf(format, args...)
    fmt.Print(msg)
}

func main() {
    Info("Hello %s", "World")
}

打印

Hello World

根据the fmt docs%!(EXTRA string=WORLD)在传递额外参数时被添加到字符串中,这是格式所未预料到的。也许你正在使用格式字符串"Hello World"而不是"Hello %s",或者传递参数两次?

wz8daaqr

wz8daaqr2#

错误是椅子和键盘之间的问题。我混淆了以下接口:

func Print(v ...interface{})
func Printf(format string, v ...interface{})

我的一些代码在没有格式字符串的情况下调用了库。请参阅此处以获取更详细的示例:http://play.golang.org/p/Xx79qujaFp

wfypjpf4

wfypjpf43#

当您的消息没有动词并且varargs是空的但来自其他地方时也会发生:

func CustomPrintf(message string, a ...interface{}) {
    fmt.Printf(message, a) // for no verbs in message you'll get this "EXTRA" suffix
}

这是一般错误的一个特例。你必须先传播a。因此,使用fmt.Printf(message, a...)再次将其设置为varags。

sigwle7e

sigwle7e4#

如果你传递nil参数到你的格式,这可能会发生,例如:

myStr := fmt.Sprintf("check/%s", "hello", nil)

将myStr的值设置为:“检查/你好%!“在这个例子中,额外的参数是第三个值为nil的参数。
因此请确保删除任何额外参数。

qlfbtfca

qlfbtfca5#

此外,发生由于一个简单的(错字?)如果您忘记/错过输入“%”。例如

fmt.Printf("v\n", myvar)

而不是

fmt.Printf("%v\n", myvar)

显然不是一个“语法”错误,所以编译器没有什么可捕捉的。我意识到这和其他一些答案是一样的,但我认为这更清楚(也许?)最常见的原因。

相关问题