Go在赋值时无法推断类型:“:=的左侧没有名称”。

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

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 &mdash; 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

huangapple
  • 本文由 发表于 2014年1月25日 09:11:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/21345274.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定