Go語言的型別系統概覽
本文將介紹go語言中的各種型別和go型別系統中的各種概念。 不知道這些概念,將很難理解go語言。
概念:基本型別
go語言中的內建型別已經在《內建基本型別和基本值》中介紹過了。為了本文的完整性,在此再次列出內建的基本型別
- 內建字串型別: string.
- 內建布林型別: bool.
-
內建數字型別:int,int8,uint8,int16,uint16,int32,uint32,int64,uint64,uint,,uintprt,
float32,float64, complex64,complex128.
除了字串型別,Go101文章系統將不會解釋其他基本型別。
概念: 組合型別
Go 支援下面的組合型別:
- 指標型別
- 結構體型別
- 函式型別
- 容器型別:陣列,切片,map
- channel :用來在goroutine之間同步資料
- interface: 在反射和多型中扮演重要角色。
複合型別可以表示為它們各自的型別文字。以下是各種複合型別的一些文字表示示例。
// Assume T is an arbitrary type and Tkey is // a type supporting comparison (== and !=). *T// a pointer type [5]T// an array type []T// a slice type map[Tkey]T // a map type // a struct type struct { name string ageint } // a function type func(int) (bool, string) // an interface type interface { Method0(string) int Method1() (int, bool) } // some channel types chan T chan<- T <-chan T
事實:各種型別
上述基本和複合型別中的每一種對應於一種類型。除了這些型別之外,unsafe包中引入的unsafe 指標型別也屬於一種型別。
到目前為止(go1.12)go有26種類型。
語法:型別定義
在go語言中,我們可以通過下面的方式定義新的型別。在語法上type
是個關鍵詞。
type NewTypeName SourceType type ( NewTypeName1 SourceType1 NewTypeName2 SourceType2 )
新的型別名字必須是個識別符號。
上例中的第二種型別宣告包括兩種型別規範。如果型別宣告包含多個型別規範,則型別規範必須包含在一對()中。
注意:
- 新定義的型別和他對應的原來的型別在型別定義上屬於兩個完全不同的型別
- 在兩個type定義上定義的型別總是不同的型別
- 新定義的型別和源型別將會共用相同的底層型別,他們的值可以相互轉換。
- 可以在函式內定義型別
一些型別定義的例子:
// The following new defined and source types are all basic types. type ( MyInt int Ageint Textstring ) // The following new defined and source types are all composite types. type IntPtr *int type Book struct{author, title string; pages int} type Convert func(in0 int, in1 bool)(out0 int, out1 string) type StringArray [5]string type StringSlice []string func f() { // The names of the three defined types // can be only used within the function. type PersonAge map[string]int type MessageQueue chan string type Reader interface{Read([]byte) int} }
語法:類型別名宣告
type ( Name = string Age = int ) type table = map[string]int type Table = map[Name]Age
概念: 定義的型別和非定義的型別
一個定義的型別是一個在型別定義或者類型別名中定義的。
所有的基本型別都是定義的。非定義型別一定是組合型別。
在下面的例子中,別名型別C和型別文字[]string 都是非定義型別,但是型別A和B都是定義型別
type A []string type B = A type C = []string
概念:命名型別和匿名型別
在go語言中:
- 如果一個型別有一個名字,那這個名字一定是識別符號,而且不是空識別符號。這個型別就被稱為命名型別。 所有基本型別都是命名型別,當一個型別宣告是識別符號非空的話它也是命名型別。
概念: 標的型別
在go語言中,每個型別都有一個標的型別。規則是:
unsafe.Pointer
例如:
// The underlying types of the following ones are both int. type ( MyInt int AgeMyInt ) // The following new types have different underlying types. type ( IntSlice = []int// underlying type is []int MyIntSlice []MyInt // underlying type is []MyInt AgeSlice[]Age// underlying type is []Age ) // The underlying types of Ages and AgeSlice are both []Age. type Ages AgeSlice
給出一個宣告的型別,如何追蹤它的標的型別呢?規則是,當遇到一個內建基本型別,unsafe.Pointer
或者匿名型別時,和追蹤將被終止。以上面的型別宣告為例,我們追蹤一下他們的標的型別。
MyInt → int Age → MyInt → int IntSlice → []int MyIntSlice → []MyInt → []int AgeSlice → []Age → []MyInt → []int Ages → AgeSlice → []Age → []MyInt → []int
在go語言中:
- 標的型別為bool的型別是布林型別
- 標的型別為內建的整型的成為整型
- 標的型別為float32,float64的為浮點型別
- 標的型別為complex64,complex128的為複數型別
- 整數,浮點數和複數也被成為數字型別
- 標的型別為string的型別被稱為字串型別
概念: 值
一個型別的例項被成為這種型別的一個值。
每種型別都有一個0值
概念: 值部件
每個值部件佔領一段連續的記憶體,間接標的部件被他的直接部件通過指標引用。
在執行時,很多值都是存在記憶體中的。在go中,每個這種值都有一個直接的部件。然而有些有一個或者多個間接部件。