2015-04-30 61 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看到我的編輯爲一個例子,這可能是不好的 –