Go語言如早期的js和python一樣,沒有顯式的類型別,但可透過結構體與函式顯式繫結,隱式地組合實現物件導向程式設計思維。
struct型別
- struct型別初始化
- 按照順序提供初始化值
- 透過
field:value
的方式初始化,這樣可以任意順序 - 透過 new 函式分配一個指標,此處P的型別為 *person
- struct 的匿名欄位(嵌入欄位)
- 匿名欄位能夠實現欄位的繼承
- 所有的內建型別和自定義型別都可以作為匿名欄位
- 同名欄位,外層的優先訪問,可過載
-
匿名結構體
- 空結構值
struct{}{}
, 通常用在通道結束符訊號,不佔記憶體 -
struct{}{name:string}
類似如其它語言中的匿名類一樣type Skills []string type Human struct { name string age int weight int } type Student struct { Human // 匿名欄位,那麼預設 Student 就包含了 Human 的所有欄位 Skills // 匿名欄位,自定義的型別 string slice int // 內建型別作為匿名欄位 speciality string } func main() { // 我們初始化一個學生 mark := Student{Human{"Mark", 25, 120}, "Computer Science"} }
- 空結構值
物件導向
-
方法 帶有接收者的函式
func (r ReceiverType) funcName(parameters) (results) // 自定義型別,類似於別名 type typeName typeLiteral type ages int type months map[string]int
-
可以在任何的自定義型別中定義任意多的 method
-
指標作為receiver
- go 知道是否呼叫指標的 method 還是非指標的 method,會自轉
- 如果一個 method 的 receiver 是 *T, 你可以在一個 T 型別的例項變數 V 上面呼叫method,而不需要 &V 去呼叫這個 method
-
方法繼承 vs 重寫
- Go使用的是內嵌式組合繼承,注意區別於其它語言,Go的‘子類’並非是‘父類’型別
interface型別
- interface 是一組 method 簽名的組合
- 空interface
- interface{} 儲存任意型別的數值 (類C void*)
- interface 函式引數
- interface 變數儲存的型別
- Comma-ok 斷言
- value,ok = element(T)
- element 為interface變數,T斷言的型別
- element.(type) 語法不能在switch外的任何邏輯裡面使用
- Comma-ok 斷言
-
嵌入interface
-
相同的邏輯引入到interface內
type Interface interface { sort.Interface // 嵌入欄位 sort.Interface Push(x interface{}) // a Push method to push elements into the heap Pop() interface{} // a Pop elements that pops elements from the heap }
-
反射
-
結構休欄位型別
type StructField struct { Name string // 欄位名 PkgPath string // 欄位路徑 Type Type // 欄位反射型別物件 Tag StructTag // 欄位的結構體標籤 Offset uintptr // 欄位在結構體中的相對偏移 Index []int // Type.FieldByIndex中的返回的索引值 Anonymous bool // 是否為匿名欄位 }
-
反射某一型別的值(這些值都實現了空interface)
-
轉化為reflect物件(reflect.Type 或 reflect.Value)
t := reflect.TypeOf(i) // 得到型別的後設資料,透過t我們能獲取型別定義裡面的所有元素 v := reflect.ValueOf(i) // 得到實際的值,透過 v 我們獲取儲存在裡面的值,還可以去改變值
-
將reflect轉化為相應的值
tag := t.Elem().Field(0).Tag // 獲取定義在 struct 裡面的標籤 name := v.Elem().Field(0).String() // 獲取儲存在第一個欄位裡面的值
-
反射的欄位必須是可修改(可定址,即非匯出欄位不能被修改)
var x float64 = 3.4 v := reflect.ValueOf(x) fmt.Println("type:", v.Type()) fmt.Println("kind is float64:", v.Kind() == reflect.Float64) fmt.Println("value:", v.Float()) //修改相應的值 p := reflect.ValueOf(&x) v := p.Elem() v.SetFloat(7.1)
-
本作品採用《CC 協議》,轉載必須註明作者和本文連結