英文:
Go fails to infer type in assignment: "non-name on left side of :="
问题
这段代码正常工作 play.golang.org/p/VuCl-OKMav
<!-- language: lang-go -->
i := 10
next := 11
prev, i := i, next
然而,这段几乎相同的代码会报错 non-name f.Bar on left side of :=
play.golang.org/p/J8NNWPugQG
<!-- language: lang-go -->
type Foo struct {
Bar int
}
f := Foo{10}
next := 11
prev, f.Bar := f.Bar, next
这个结构体有什么特殊之处导致类型推断失败?这是一个 bug 吗?
英文:
This snippet works as expected play.golang.org/p/VuCl-OKMav
<!-- language: lang-go -->
i := 10
next := 11
prev, i := i, next
However this nearly identical snippet gives non-name f.Bar on left side of :=
play.golang.org/p/J8NNWPugQG
<!-- language: lang-go -->
type Foo struct {
Bar int
}
f := Foo{10}
next := 11
prev, f.Bar := f.Bar, next
What's special about the struct that stops type inference? Is this a bug?
答案1
得分: 24
这是一个<strike>开放</strike>的问题。
问题 6842: 规范:使用短声明符号给字段赋值
英文:
It's an <strike>open</strike> issue.
Issue 6842: spec: Assigning to fields with short declaration notation
答案2
得分: 22
这不是一个类型推断问题,只是:=
的左侧必须是一个标识符列表,而f.Bar
不是一个标识符,所以不能声明它,即使使用:=
的稍微宽松一些的规则也不行。请参考《Go编程语言规范》中的“短变量声明”一节(http://golang.org/ref/spec#Short_variable_declarations)。
英文:
It's not really a type inference issue, it's just that the left-hand-side of :=
must be a list of identifiers, and f.Bar
is not an identifier, so it can't be declared — not even with :=
's slightly-more-permissive rules for what it can declare. See "Short variable declarations" in The Go Programming Language Specification.
答案3
得分: 13
根据规范中的短变量声明部分:
与常规变量声明不同,短变量声明可以重新声明变量,前提是它们在同一代码块中最初被声明过...具有相同的类型,并且至少有一个非空变量是新的。
因此,如果你在另一个类型内部声明变量(例如结构体Foo),它将被“provided they were originally declared earlier in the same block”所排除。
因此,答案是将预先声明的变量设置为不使用:=语法的值:
...
var prev int
prev, f.Bar = f.Bar, next
...
英文:
From the spec's Short variable declarations section:
> Unlike regular variable declarations, a short variable declaration may
> redeclare variables provided they were originally declared earlier in
> the same block...with the same type, and at least one of the non-blank
> variables is new.
So if you declare the variable inside another type (struct Foo in the example), it is disqualified by "provided they were originally declared earlier in the same block".
So the answer is to just set the pre-declared variable equal not using the := syntax to the value:
...
var prev int
prev, f.Bar = f.Bar, next
...
答案4
得分: 0
只需删除冒号即可重新分配。以下是修改后的代码:
var prev string
f := Foo{10}
next := 11
prev, f.Bar = f.Bar, next
这样就可以重新分配了。
英文:
it is just that you already assigned f to Foo
f := Foo{100}
in this case f.Bar is 100
so to reassign it just remove the column
var prev string
f := Foo{10}
next := 11
prev, f.Bar = f.Bar, next
this will work
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论