go x/tools/cmd/stringer:处理具有类型初始值的未类型化的常量

k5hmc34c  于 4个月前  发布在  Go
关注(0)|答案(8)|浏览(40)

你正在使用的Go版本是什么( go version )?
1.10.2, 1.11beta2(但"stringer"的版本无论如何都是一样的)

这个问题在最新版本的发布中是否会重现?

可能("stringer"实际上并没有被包含进去)

你正在使用什么操作系统和处理器架构( go env )?

linux/amd64

你做了什么?

尝试在一个程序上运行stringer:
https://play.golang.org/p/y0bNVBnOyAi

你期望看到什么?

我期望它能正确地识别出FooA和FooB的类型是Foo,而FooAMask和FooBMask的类型是FooMask。从代码上看,stringer是在寻找声明的类型,而不是从显式类型表达式推断出的类型。

你看到了什么?

$ go generate
stringer: no values defined for type Foo
在运行stringer的代码中,这个修复起来相当困难。你可以进行FooA Foo = iota; FooAMask FoomMask = (1 << iota)操作,但是你不能做以下几行代码,让它们获得相同的类型。你不能在一行中使用逗号声明两种不同类型的两个东西。而且如果你不在同一行上声明它们,FooA和FooAMask可能会失去同步。(嗯,每个列表中的第一个可能是相同的,但如果你有两个二十项的列表,它们最终会失去同步。)

jvidinwx

jvidinwx1#

#11581中,包括来自robpike的类似(最近)讨论:"Stringer不需要支持完整的语言。"

q5iwbnjs

q5iwbnjs2#

是的。其中,有一条评论是:“我很难想出为什么要改写成更简单的(AST方面)X T = iota会有什么问题。”这可能是一个有问题的情况;我没有看到如何在那种形式中声明不同类型的并行事物。

u4vypkhs

u4vypkhs3#

我看不到以这种形式声明不同类型并行事物的方法。
那么,将它们声明在单独的 const 块中怎么样?

ecr0jaav

ecr0jaav5#

经过进一步检查,这可能只是#11581的重复问题,后者已被标记为不会修复。

brccelvz

brccelvz6#

如果它们位于不同的const块中,它们不再是并行的;它们可能会不同步。将声明放在同一条线上可以提供额外的清晰度,并防止错误。
对比:

const (
Foo = iota, FooMask = (1 << iota)
Bar, BarMask
Baz, BazMask
)

const (
Foo = iota,
Baz
Bar
)

const (
FooMask = (1 << iota)
BarMask
BazMask
)

你可能很容易发现这里的不对齐。如果有20个项目,这会变得困难得多。使用第一种形式更容易,因为你只需要验证每行的正确性,而不需要检查它们的顺序。
所以,这与11581类似,但我认为这提供了一个具体的用例,其中将类型放在左侧的重写将无法正常工作,因为确实有一个用例需要以一种明确的并行方式声明两种不同类型的事物。

piwo6bdm

piwo6bdm7#

如果 stringer 再次使用 go/types,这不应该默认生效吗?stringer 不应该关心我们是否声明了类型,或者它是由常量块推断出来的 - go/types 将给我们提供我们要生成的类型的所有用法,对吗?

vx6bjr1n

vx6bjr1n8#

是的,我最初也是这样想的——但是看看之前那个问题的讨论。我认为只要代码和逻辑保持简单,利用go/types进行处理是没有问题的。

相关问题