這是一個建立於
的文章,其中的資訊可能已經有所發展或是發生改變。
結構體定義的一般方式如下:
type identifier struct { field1 type1 field2 type2 ... }
type T struct {a, b int} 也是合法的文法,它更適用於簡單的結構體。
var t *T t = new(T)
變數 t 是一個指向 T的指標,此時結構體欄位的值是它們所屬類型的零值,使用 new 函數給一個新的結構體變數分配記憶體,它返回指向已指派記憶體的指標。
無論變數是一個結構體類型還是一個結構體類型指標,都使用同樣的 選取器符(selector-notation) 來引用結構體的欄位,即:
type myStruct struct { i int } var v myStruct // v是結構體類型變數var p *myStruct // p是指向一個結構體類型變數的指標v.i p.i
struct執行個體:
package main import ( "fmt" "strings" ) type Person struct { firstName string lastName string } func upPerson(p *Person) { p.firstName = strings.ToUpper(p.firstName) p.lastName = strings.ToUpper(p.lastName) } func main() { // 1-struct as a value type: var pers1 Person pers1.firstName = "Chris" pers1.lastName = "Woodward" upPerson(&pers1) fmt.Printf("The name of the person is %s %s\n", pers1.firstName, pers1.lastName) // 2—struct as a pointer: pers2 := new(Person) pers2.firstName = "Chris" pers2.lastName = "Woodward" (*pers2).lastName = "Woodward" // 這是合法的 upPerson(pers2) fmt.Printf("The name of the person is %s %s\n", pers2.firstName, pers2.lastName) // 3—struct as a literal: pers3 := &Person{"Chris", "Woodward"} upPerson(pers3) fmt.Printf("The name of the person is %s %s\n", pers3.firstName, pers3.lastName) }
程式輸出:
The name of the person is CHRIS WOODWARD The name of the person is CHRIS WOODWARD The name of the person is CHRIS WOODWARD
使用反射訪問struct的tag標籤:
package main import ( "fmt" "reflect" ) type Person struct { firstName string `An important answer` lastName string `The name of the thing` } func main() { tt := Person{"first", "last"} for i := 0; i < 2; i++ { refTag(tt, i) } }
程式輸出:
Tag:An important answer Name:firstName Tag:The name of the thing Name:lastName
在值和指標上調用方法:
可以有串連到類型的方法,也可以有串連到類型指標的方法。
但是這沒關係:對於類型 T,如果在 *T 上存在方法 Meth(),並且 t 是這個類型的變數,那麼 t.Meth() 會被自動轉換為(&t).Meth()。
指標方法和值方法都可以在指標或非指標上被調用,收者類型是 *TwoInts 的方法 AddThem(),它能在類型 TwoInts 的值上被調用,這是自動間接發生的。
因此 two2.AddThem 可以替代 (&two2).AddThem()。
再說一句,go中有方法繼承與覆蓋,不過必須是匿名欄位o