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

2 回复

更多关于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。

回到顶部