编译器为什么没有关于不正确格式化的警告?

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

Why isn't the compiler warning about incorrect formatters?

问题

我原本期望以下代码至少在编译时会引发警告,因为格式化符号与变量的类型不匹配:

  1. package main
  2. import "fmt"
  3. func main() {
  4. s := "hello"
  5. fmt.Printf("1 %w", s)
  6. fmt.Printf("2 %s", s)
  7. }

变量的类型在编译时是已知的,并且字符串格式化符号是以确定性的方式解析的。为什么在这一点上没有引发错误呢?

相反,我得到的输出是:

  1. 1 %!w(string=hello)2 hello

这似乎是一种消息,告诉我们 %w 对于类型 string 是错误的(但只在运行时才会出现)。

英文:

I was expecting the following code to at least raise a warning during compilation because the formatters are not aligned with the types of variables:

  1. package main
  2. import "fmt"
  3. func main() {
  4. s := "hello"
  5. fmt.Printf("1 %w", s)
  6. fmt.Printf("2 %s", s)
  7. }

The types of the variables are known at compile time, and the string formatters are parsed in a deterministic way - is there a reason why the error is not raised at that point?

What I get instead is a code that outputs

  1. 1 %!w(string=hello)2 hello

This seems to be some kind of message telling that %w was wrong for the type string (but only at runtime)

答案1

得分: 3

fmt.Printf的格式字符串参数是在运行时解释的,而不是编译时。

使用静态分析的linter,例如go vet

so.go:

  1. package main
  2. import "fmt"
  3. func main() {
  4. s := "hello"
  5. fmt.Printf("1 %w\n", s)
  6. fmt.Printf("2 %s\n", s)
  7. }

linter:

  1. $ go vet so.go
  2. ./so.go:7:2: fmt.Printf 格式 %w 的参数 s 的类型错误,应为 string
  3. 请参阅 https://pkg.go.dev/fmt#hdr-Printing
  4. $

运行时:

  1. $ go run so.go
  2. 1 %!w(string=hello)
  3. 2 hello
  4. $
英文:

The fmt.Printf format string argument is interpreted at runtime, not compile time.

> func Printf(format string, a ...any) (n int, err error)
>
> Printf formats according to a format specifier and writes to standard output. It returns the number of bytes written and any write error encountered.

Use a static analysis linter, for example, go vet.

> go command - cmd/go - Go Packages
>
> Report likely mistakes in packages
>
> Usage:
>
> go vet [-n] [-x] [-vettool prog] [build flags] [vet flags] [packages]
>
> Vet runs the Go vet command on the packages named by the import paths.
>
> For more about vet and its flags, see 'go doc cmd/vet'.


so.go:

  1. package main
  2. import "fmt"
  3. func main() {
  4. s := "hello"
  5. fmt.Printf("1 %w\n", s)
  6. fmt.Printf("2 %s\n", s)
  7. }

linter:

  1. $ go vet so.go
  2. ./so.go:7:2: fmt.Printf format %w has arg s of wrong type string,
  3. see also https://pkg.go.dev/fmt#hdr-Printing
  4. $

runtime:

  1. $ go run so.go
  2. 1 %!w(string=hello)
  3. 2 hello
  4. $

huangapple
  • 本文由 发表于 2023年1月8日 02:41:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/75042890.html
匿名

发表评论

匿名网友

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

确定