Golang中fmt工具的-w -s参数是否存在bug?
Golang中fmt工具的-w -s参数是否存在bug? 大家好,
我在使用 go fmt -w -s 时遇到了一个奇怪的输出。有人遇到过这种情况吗?在多行代码之前的行在结构体列表中没有正确对齐。在我的例子中,inID 字段一直偏离列对齐位置。
这是一个有效的错误吗?
你使用的 Go 版本是什么(go version)?
$ go version
go version go1.12.1 linux/amd64
这个问题在最新版本中是否仍然存在?
尚未探索刚发布的 1.12.3 版本
你使用的操作系统和处理器架构是什么(go env)?
`go env` 输出
$ go env
GOARCH="amd64"
GOBIN="/home/u0/bin"
GOCACHE="/home/u0/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/u0"
GOPROXY=""
GORACE=""
GOROOT="/usr/local/go"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/u0/Documents/gosandbox/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build565099213=/tmp/go-build -gno-record-gcc-switches"
你做了什么?
当对源代码应用 $ gofmt -w -s . 时,多行代码之前的行被格式化为奇怪的样子,没有对齐到正确的列。这种情况在所有紧接在多行代码之前的行中都非常一致。
这发生在我处理一个大型结构体列表进行表驱动测试时。执行没有问题。
你期望看到什么?
{
inID: 0,
inAction: (AsymmetricEncryptAction |
AsymmetricDecryptAction),
inBadRand: false,
outError: false,
outPublicKey: true,
outPrivateKey: true,
}, {
inID: 1,
inAction: AsymmetricEncryptAction,
inBadRand: false,
outError: false,
outPublicKey: true,
outPrivateKey: true,
}, {
inID: 2,
inAction: AsymmetricDecryptAction,
inBadRand: false,
outError: false,
outPublicKey: true,
outPrivateKey: true,
}, {
inID: 3,
inAction: SignAction | VerifyAction,
inBadRand: false,
outError: false,
outPublicKey: true,
outPrivateKey: true,
你实际看到了什么?
{
inID: 0,
inAction: (AsymmetricEncryptAction |
AsymmetricDecryptAction),
inBadRand: false,
outError: false,
outPublicKey: true,
outPrivateKey: true,
}, {
inID: 1,
inAction: AsymmetricEncryptAction,
inBadRand: false,
outError: false,
outPublicKey: true,
outPrivateKey: true,
}, {
inID: 2,
inAction: AsymmetricDecryptAction,
inBadRand: false,
outError: false,
outPublicKey: true,
outPrivateKey: true,
}, {
inID: 3,
inAction: SignAction | VerifyAction,
inBadRand: false,
outError: false,
outPublicKey: true,
outPrivateKey: true,
更多关于Golang中fmt工具的-w -s参数是否存在bug?的实战教程也可以访问 https://www.itying.com/category-94-b0.html
已在Github上作为错误提出(https://github.com/golang/go/issues/31431)。这确实是一个需要调查的问题。
更多关于Golang中fmt工具的-w -s参数是否存在bug?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
这不是 gofmt 工具的 bug,而是其设计行为。gofmt 在处理多行表达式时会采用不同的对齐策略,特别是当某个字段的值跨越多行时。
在你的例子中,第一个结构体的 inAction 字段使用了多行表达式:
inAction: (AsymmetricEncryptAction |
AsymmetricDecryptAction),
由于这个多行表达式的存在,gofmt 会重新计算对齐方式,导致同一结构体中的 inID 字段不再与其他结构体中的对应字段对齐。
这是一个示例来演示这个行为:
// 多行表达式前的字段不会与其他结构体对齐
{
id: 1,
action: (ValueA |
ValueB),
flag: true,
}, {
id: 2, // 这里会保持对齐
action: ValueC,
flag: false,
}
gofmt 的这种行为是故意的,目的是在多行表达式存在时提供更清晰的视觉分组。当检测到多行表达式时,它会优先保证当前结构体内部的可读性,而不是跨结构体的列对齐。
你可以通过将多行表达式重构为单行来避免这个问题:
{
inID: 0,
inAction: AsymmetricEncryptAction | AsymmetricDecryptAction,
inBadRand: false,
outError: false,
outPublicKey: true,
outPrivateKey: true,
}
或者使用变量来存储复杂的表达式:
action := AsymmetricEncryptAction | AsymmetricDecryptAction
// ...
{
inID: 0,
inAction: action,
// ...
}
这种行为在 Go 1.12 及后续版本中都是一致的,不是特定版本的 bug。

