golang 結構體嵌入和匿名成員

2022-08-17 14:48:12 字數 2861 閱讀 2561

抄來的,來自go聖經,建議入門閱讀

考慮乙個二維的繪圖程式,提供了乙個各種圖形的庫,例如矩形、橢圓形、星形和輪形等幾 何形狀。這裡是其中兩個的定義

type    circle struct

type wheel

struct

乙個circle代表的圓形型別包含了標準圓心的x和y座標資訊,和乙個radius表示的半徑信 息。乙個wheel輪形除了包含circle型別所有的全部成員外,還增加了spokes表示徑向輻條的 數量。我們可以這樣建立乙個wheel變數:

var

w wheel

w.x = 8

w.y = 8

w.radius = 5

w.spokes = 20

隨著庫中幾何形狀數量的增多,我們一定會注意到它們之間的相似和重複之處,所以我們可 能為了便於維護而將相同的屬性獨立出來:

type point struct

type circle

struct

type wheel

struct

這樣改動之後結構體型別變的清晰了,但是這種修改同時也導致了訪問每個成員變得繁瑣:

var

w wheel

w.circle.center.x = 8

w.circle.center.y = 8

w.circle.radius = 5

w.spokes = 20

go語言有乙個特性讓我們只宣告乙個成員對應的資料型別而不指名成員的名字;這類成員就 叫匿名成員。匿名成員的資料型別必須是命名的型別或指向乙個命名的型別的指標。下面的 **中,circle和wheel各自都有乙個匿名成員。我們可以說point型別被嵌入到了circle結構 體,同時circle型別被嵌入到了wheel結構體。

type circle    struct

type wheel

struct

得益於匿名嵌入的特性,我們可以直接訪問葉子屬性而不需要給出完整的路徑:

var

w wheel

w.x = 8

//equivalent to w.circle.point.x = 8

w.y = 8

//equivalent to w.circle.point.y = 8

w.radius = 5

//equivalent to w.circle.radius = 5

w.spokes = 20

在右邊的注釋中給出的顯式形式訪問這些葉子成員的語法依然有效,因此匿名成員並不是真 的無法訪問了。其中匿名成員circle和point都有自己的名字——就是命名的型別名字——但是 這些名字在點操作符中是可選的。我們在訪問子成員的時候可以忽略任何匿名成員部分。

不幸的是,結構體字面值並沒有簡短表示匿名成員的語法, 因此下面的語句都不能編譯通 過:

w = wheel  //

compile error: unknown fields

w = wheel //

compile error: unknown fields

w = wheel, 5},20

}w =wheel,

radius: 5,

}, spokes:

20, //

note: trailing comma necessary here (and at radius)

}fmt.printf(

"%#v\n

",w)

//output:

//wheel, radius:5}, spokes:20}

w.x = 42

fmt.printf(

"%#v\n

", w)

//output:

//wheel, radius:5}, spokes:20}

需要注意的是printf函式中%v引數包含的#副詞,它表示用和go語言類似的語法列印值。對於 結構體型別來說,將包含每個成員的名字。

因為匿名成員也有乙個隱式的名字,因此不能同時包含兩個型別相同的匿名成員,這會導致 名字衝突。同時,因為成員的名字是由其型別隱式地決定的,所有匿名成員也有可見性的規 則約束。在上面的例子中,point和circle匿名成員都是匯出的。即使它們不匯出(比如改成小 寫字母開頭的point和circle),我們依然可以用簡短形式訪問匿名成員巢狀的成員

w.x = 8

//equivalent to w.circle.point.x = 8

但是在包外部,因為circle和point沒有匯出不能訪問它們的成員,因此簡短的匿名成員訪問語 法也是禁止的。

到目前為止,我們看到匿名成員特性只是對訪問巢狀成員的點運算子提供了簡短的語法糖。 稍後,我們將會看到匿名成員並不要求是結構體型別;其實任何命名的型別都可以作為結構 體的匿名成員。但是為什麼要嵌入乙個沒有任何子成員型別的匿名成員型別呢?

答案是匿名型別的方法集。簡短的點運算子語法可以用於選擇匿名成員巢狀的成員,也可以 用於訪問它們的方法。實際上,外層的結構體不僅僅是獲得了匿名成員型別的所有成員,而 且也獲得了該型別匯出的全部的方法這個機制可以用於將乙個有簡單行為的物件組合成有 複雜行為的物件。組合是go語言中物件導向程式設計的核心。

Golang結構體和指標

golang是一門很特殊的語言,雖然它出生比較晚,但是在很多地方卻和現在的程式語言有所不同。現在的程式語言要麼是函式式的 要麼是物件導向的,而go語言卻有指標 結構體這些概念,並解決了c語言的一些坑。從這個角度上說,golang可以看做c語言的填坑加強版。定義結構體和c語言一樣,使用struct關鍵...

Golang結構體知識

在看docker原始碼時,碰到了這個語句 container.lock 看到上面直接對struct container進行上鎖時,我翻了一下這個結構體,發現沒有定義任何鎖啊,怎麼上鎖的咧。於是我就翻了一下這個結構 體的一些子屬性,發現了state的定義 container container.go ...

Golang 學習 結構體

結構體定義 結構體是一種資料型別。定義型別 地位等價於 int byte bool string.通常放在全域性位置 type person struct 注意 結構體內不能賦初值,不能用 var 修飾。普通變數定義和初始化 普通變數的賦值和使用 使用 索引成員變數。var man person m...