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

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

Why isn't the compiler warning about incorrect formatters?

问题

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

package main

import "fmt"

func main() {
    s := "hello"
    fmt.Printf("1 %w", s)
    fmt.Printf("2 %s", s)
}

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

相反,我得到的输出是:

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:

package main

import "fmt"

func main() {
	s := "hello"
	fmt.Printf("1 %w", s)
	fmt.Printf("2 %s", s)
}

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 %!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:

package main

import "fmt"

func main() {
    s := "hello"
    fmt.Printf("1 %w\n", s)
    fmt.Printf("2 %s\n", s)
}

linter:

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

运行时:

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

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:

package main

import "fmt"

func main() {
	s := "hello"
	fmt.Printf("1 %w\n", s)
	fmt.Printf("2 %s\n", s)
}

linter:

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

runtime:

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

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:

确定