Golang: fmt,可变参数和%!(EXTRA type=value)错误

huangapple go评论89阅读模式
英文:

Golang: fmt, variadic args and %!(EXTRA type=value) error

问题

我正在实现一个包装标准日志包的包装器,以创建具有不同日志级别的记录器。

我有以下接口:

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{}=[]"。

英文:

I'm implementing a wrapper around the standard log package to make a logger with various log levels.

I have the following interface:

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

In the implementation I have something like this (not the exact code)

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

Now, assume I call my library like this:

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

I get the printout: "Hello %!(EXTRA string=WORLD)", instead of the expected "Hello World". There a similar output if I do

msg := fmt.Sprintf(format, args)

This returns "Hello World%!EXTRA []interface{}=[]".

答案1

得分: 20

我无法重现这种行为。你确定这不是一个简单的错误,你忘记在这里展示吗?

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

根据 fmt 文档,当你传递额外的参数时,格式化字符串中会添加 %!(EXTRA string=WORLD)。也许你正在使用格式化字符串 "Hello World" 而不是 "Hello %s",或者将参数传递了两次?

英文:

I can't reproduce this behavior. Are you sure it's not a simple error that you forgot to show here?

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

Prints

Hello World

According to the fmt docs, %!(EXTRA string=WORLD) is added to the string when you pass extra parameters, unexpected by the format. Maybe you are using the format string "Hello World" instead of "Hello %s", or passing the argument twice?

答案2

得分: 10

错误出现在椅子和键盘之间。我混淆了以下接口:

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

我的一些代码在调用库时没有提供格式字符串。请参考这里的更详细示例:http://play.golang.org/p/Xx79qujaFp

英文:

The error was between the chair and keyboard. I mixed up the following interfaces:

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

Some of my code was calling the library without a format string.See here for a more detailed example: http://play.golang.org/p/Xx79qujaFp

答案3

得分: 0

当你的消息没有动词并且可变参数为空,但来自其他地方时,也会发生这种情况:

func CustomPrintf(message string, a ...interface{}) {
    fmt.Printf(message, a) // 对于消息中没有动词的情况,你将得到这个“EXTRA”后缀
}

这是一种特殊情况的一般错误。你必须先展开 a。所以使用 fmt.Printf(message, a...) 来再次将其转换为可变参数。

英文:

Happens aswell when your message has no verbs and the varargs are empty but coming from elsewhere:

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

That's a special case of a general error. You've got to spread a first. So use fmt.Printf(message, a...) to make it to varags again.

答案4

得分: 0

这可能是因为你将空参数传递给了格式化函数,例如:

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

这样会将myStr的值设置为:"check/hello%!"
在这个例子中,额外的参数是第三个参数,其值为nil。

所以请确保删除任何多余的参数。

英文:

This can happen if you pass nil params to your format, for instance:

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

will set the value of myStr to: "check/hello%!"
In this example the extra params was the third param with nil value.

so make sure to remove any extra params.

答案5

得分: 0

另外,如果你忘记或者漏掉了输入“%”符号,也会发生这种情况(是个笔误吗?)。
例如:

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

而不是

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

显然这不是一个“语法”错误,所以编译器无法捕捉到。
我意识到这与其他答案中的一些情况相同,但我认为这更清晰,也可能是最常见的原因。

英文:

Also, happens due to a simple (typo?) if you forget/miss putting in the "%".
e.g.

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

instead of

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

obviously not a "syntax" error, so nothing for the compiler to catch.
I realize this nets out to the same as some of the other answers, but I think this is clearer and (maybe?) the most common cause.

huangapple
  • 本文由 发表于 2015年10月29日 03:49:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/33400325.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定