2015-04-30 38 views
-1

我正在研究一个示例程序来回答这里的另一个问题,并发现自己有些困惑,因为下面的代码不会编译;复合文字和嵌入式字段

https://play.golang.org/p/wxBGcgfs1o

package main 

import "fmt" 

type A struct { 
    FName string 
    LName string 
} 

type B struct { 
    A 
} 

func (a *A) Print() { 
    fmt.Println(a.GetName()) 
} 

func (a *A) GetName() string { 
    return a.FName 
} 

func (b *B) GetName() string { 
    return b.LName 
} 

func main() { 
    a := &A{FName:"evan", LName:"mcdonnal"} 
    b := &B{FName:"evan", LName:"mcdonnal"} 

    a.Print() 
    b.Print() 
} 

的错误是;

/tmp/sandbox596198095/main.go:28: unknown B field 'FName' in struct literal 
/tmp/sandbox596198095/main.go:28: unknown B field 'LName' in struct literal 

是否可以在静态初始化程序中设置嵌入类型的字段值?怎么样?对我来说,这似乎是一个编译器错误;如果我没有在我面前的来源,并熟悉类型我会打我的头撞墙说:“明确F名存在B编译器说什么!?!?!”。

快速,以抢占典型的答案我知道最接近的工作语法是这个b := &B{A{FName:"evan", LName:"mcdonnal"}},但是在我看来,这种语法在概念上与嵌入相矛盾,所以如果它是唯一的选择,我会感到失望。如果这是唯一的方法,它是Go编译器的一个简短的介绍,还是实际上存在一个理论上的限制,它会阻止编译器解释我的非工作示例中的语法?

+0

可能重复[获取错误:结构体文字中的未知字段](https://stackoverflow.com/questions/33098460/getting-error-unknown-field-in-struct-literal) –

回答

4

这不是编译器错误而是一个设计决定。语言规范只是指出:

Promoted fields act like ordinary fields of a struct except that they cannot be used as field names in composite literals of the struct.

我想这背后的原因是为了避免含糊不清。在使用选择器时,有几条规则可以解决名称冲突,为了允许您提出的建议,它们必须很复杂。最重要的是,如果您在嵌入类型的结构字面值中使用嵌入式结构的现有实例,则可能会产生歧义。

编辑:在此处,这种做法可能会适得其反的例子:

认为你要嵌入,你有一个嵌入B中的情况下,和A的实例:

type A { 
    X int 
} 

type B { 
    A 
} 

这是很简单的要做

b := B{ X: 1 } 

并推断应该做什么。 但是如果我们已经有一个A的实例呢?这是没有意义的:

a := A { X: 1 } 

b := B { X: 2, A: a, } 

是你第一次分配2 A的零实例,然后在它分配的初始化实例?它是相同的:

b := B { A: a, X: 2 } ? 

它打破了初始化顺序与字段名称的复合文字无关的假设。

+1

Apt引用来自spec: )。但我不会按照你的猜测来判断原因。我没有看到支持'b:= B {FName:“x”,“LName:”y“}'比它支持'b:= B {}; b.FName =”x“ b.LName =“y”'。 –

+0

是的,这句话清楚地表明我的代码不会被编译,虽然我同意@DaveC ......如果这是一个有意识的设计决定,那是错误的.Dave的评论指出我的设计的主要问题。在一行中,我无条件地访问该字段,另一方面编译器声称它不存在于该结构中。这基本上是一个矛盾。 – evanmcdonnal

+0

@DaveC看到我的编辑为一个例子,这可能是不好的 –