go version go1.11 windows/amd64html
本文爲閱讀Go語言中文官網的規則說明書(https://golang.google.cn/ref/spec)而作的筆記,完整的介紹Go語言的 類型(Types)。golang
官文的 類型 的 目錄結構 以下(12項):編程
Types
-Method sets
-Boolean types
-Numeric types
-String types
-Array types
-Slice types
-Struct types
-Pointer types
-Function types
-Interface types
-Map types
-Channel typeswindows
其中一些類型本身是熟悉的,但Go語言中特有的類型就不那麼清楚了,好比,Channel types,第一次見到這種類型,也是重難點;Method sets的概念也是第一次見,好像和Interface types有些關係,需dig清楚;而Interface types也能夠Java中的概念不同;數組
其它的,Slice types在Python有所耳聞,但在Go裏面是一個專門的類型;Struct、Pointer types的概念在C/C++中見到過,沒想到這裏又出現了。架構
審查後發現,總共12項,其中6項須要花精時弄清楚才行。併發
下面分別介紹(添加了一個type (...),出如今官文Types一節的開始位置,也是重難點):app
-type (...)編程語言
這部分還不是很清楚,官文強翻(譯)以下:ide
Go預約義了一些類型名稱,其它類型則須要type關鍵字來聲明。組合類型——好比,數組、結構體、指針、函數、接口、分片、映射和通道類型等——可使用類型常量構建。
每個類型 T 都有一個 底層類型:...(後面內容仍是看官文吧!)
官文給的示例:
type ( A1 = string A2 = A1 ) type ( B1 string B2 B1 B3 []B1 B4 B3 )
上面的string、A一、A二、B一、B2的 底層類型 是 string,[]B一、B三、B4的底層類型是[]B1(我覺得是 []string)。
下面是本身的測試,結果代表,上面的語句就是 定義類型別名 使用的嘛!
package main import ( "reflect" "fmt" ) type ( A1 = string A2 = A1 ) type ( B1 string B2 B1 B3 []B1 B4 B3 ) func main() { var str1 A1 = "1234" var str2 A2 = "abcd" fmt.Println("----測試1----") fmt.Println(str1) fmt.Println(str2) fmt.Println() fmt.Println(typeof(str1)) fmt.Println(typeof(str2)) fmt.Println() fmt.Println(typeof2(str1)) fmt.Println(typeof2(str2)) fmt.Println("----測試2----") var str3 B1 = "haha" var str4 B2 = "heihei" var strs1 B3 strs1 = append(strs1, "dad", "mom") var strs2 B4 strs2 = append(strs2, "tom", "jerry") fmt.Println(str3) fmt.Println(str4) fmt.Println(strs1) fmt.Println(strs2) fmt.Println() fmt.Println(typeof(str3)) fmt.Println(typeof(str4)) fmt.Println(typeof(strs1)) fmt.Println(typeof(strs2)) fmt.Println() fmt.Println(typeof2(str3)) fmt.Println(typeof2(str4)) fmt.Println(typeof2(strs1)) fmt.Println(typeof2(strs2)) } // https://studygolang.com/articles/10524 func typeof(v interface{}) string { return fmt.Sprintf("%T", v) } func typeof2(v interface{}) string { return reflect.TypeOf(v).String() }
測試結果:
----測試1---- 1234 abcd string string string string ----測試2---- haha heihei [dad mom] [tom jerry] main.B1 main.B2 main.B3 main.B4 main.B1 main.B2 main.B3 main.B4
說明,雖然進行了測試,但是,本身對這個用法仍是不太熟悉,何時會用到了?還須要dig!
-Method sets
方法集。
一個類型能夠擁有一個方法集。一個實現了接口類型的方法集合的類型 也是這個 接口類型(前面學習的經驗)。
官文後面的就不清楚什麼意思了,什麼receiver type T、receiver *T……
在方法集合中,每個方法都是一個 惟一的、非空的 方法名稱。
能夠看下面的示例(來自RUNOOB.COM)(下面的示例包含兩份代碼,簡單的部分被註釋掉了):
package main import ( "fmt" ) //type Phone interface { // call() //} // //type NokiaPhone struct { // //} // //func (nokiaPhone NokiaPhone) call() { // fmt.Println("I am Nokia, I can all you") //} // //type IPhone struct { // //} // //func (iPhone IPhone) call() { // fmt.Println("I am iPhone, I can call you") //} // 給接口增長參數 type Man interface { name() string age() int } type Woman struct { } func (woman Woman) name() string { return "Jin Yawei" } func (woman Woman) age() int { return 23 } type Men struct { } func (men Men) name() string { return "liweibin" } func (men Men) age() int { return 27 } func main() { // var phone Phone // // phone = new(NokiaPhone) // phone.call() // // phone = new(IPhone) // phone.call() // 給接口增長參數 var man Man man = new(Woman) fmt.Println(man.name(), man.age()) man = new(Men) fmt.Println(man.name(), man.age()) }
運行結果:
Jin Yawei 23 liweibin 27
說明&思考,關於方法集的更多內容,能夠查看struct類型相關文檔。經過 方法集、interface 這兩個概念,Go語言將 數據、使用數據的方法 完全分開了。還須要dig!
-Boolean types
布爾類型,類型名稱爲 bool,兩個字面量:true、false。
-Numeric types
數值類型。
整數 和 浮點數 和 複數,包括:
預約義 的和計算機架構無關的數值類型以下(官文):
uint8 the set of all unsigned 8-bit integers (0 to 255) uint16 the set of all unsigned 16-bit integers (0 to 65535) uint32 the set of all unsigned 32-bit integers (0 to 4294967295) uint64 the set of all unsigned 64-bit integers (0 to 18446744073709551615) int8 the set of all signed 8-bit integers (-128 to 127) int16 the set of all signed 16-bit integers (-32768 to 32767) int32 the set of all signed 32-bit integers (-2147483648 to 2147483647) int64 the set of all signed 64-bit integers (-9223372036854775808 to 9223372036854775807) float32 the set of all IEEE-754 32-bit floating-point numbers float64 the set of all IEEE-754 64-bit floating-point numbers complex64 the set of all complex numbers with float32 real and imaginary parts complex128 the set of all complex numbers with float64 real and imaginary parts byte alias for uint8 rune alias for int32
還有下面幾個 預約義 的數值類型,但它們和計算機架構有關係:
uint either 32 or 64 bits int same size as uint uintptr an unsigned integer large enough to store the uninterpreted bits of a pointer value
官文:爲了不移植問題, 全部的數值類型都是 定義了的類型(defined types?)而且是清楚的,除了其中的byte——uint8的別名、rune——int32的別名。不一樣的數值類型參與同一個計算時,須要顯示轉換,Go語言不存在隱式轉換——這和以前遇到的編程語言不一樣。好比,int32 和 int 是不一樣類型,即使它們在某些架構上有相同的字節數。
-String types
字符串類型。
不可改變。是一個 defined types。
字符串長度獲取:使用內建函數 len。若字符串是常量,那麼,len獲取的值就是編譯時常量(compile-time constant)。
字符串的 字符 (官文是bytes,感受有錯誤)能夠經過下標 0 到 len(s) -1獲取。
注意,獲取一個字符串中字符的地址 是錯誤的,即 &s[i] 是非法的!
-Array types
數組類型。
數組中的元素類型是 相同的,數組元素的個數 即爲 數組的長度,數組的長度不爲負數。
和字符串類型語言獲取數組類型長度 使用內建函數len。
官文中這句不太理解: Array types are always one-dimensional but may be composed to form multi-dimensional types.
翻譯:數組類型都是一維的,但能夠組合成多維類型。
就是說,檢測到的都是數組類型,可是呢,有的是一維的、有的是二維的?
測試數組類型:
var arr1 [2]int var arr2 [2][2]int fmt.Println(typeof(arr1)) fmt.Println(typeof(arr2)) fmt.Println(typeof2(arr1)) fmt.Println(typeof2(arr2)) // https://studygolang.com/articles/10524 func typeof(v interface{}) string { return fmt.Sprintf("%T", v) } func typeof2(v interface{}) string { return reflect.TypeOf(v).String() }
測試結果:
[2]int [2][2]int [2]int [2][2]int
二維數組檢測到就是二維的啊?官文有誤?
-Slice types
切片類型。
參考連接:Go 語言切片(Slice) by RUNOOB.COM,裏面有更清楚的介紹。
切片類型是對 數組 的抽象(an underlying array),一個未初始化的切片類型的值爲 nil。
經過 len函數 獲取切片長度,經過 cap函數 獲取切片容量。
和數組同樣,切片中的數據類型是相同的,一維的切片 能夠 組合成 多維的切片。
-Struct types
結構體類型。
是一系列被稱爲 域 的 命名元素 的 序列,每個域都有一個名稱和類型。
域的名稱能夠顯示或隱式地制定。(疑惑)
在結構體中,非空的域的名稱必須是惟一的,也就是說,域的名稱能夠爲空(下劃線,_)。
官文示例以下:
// An empty struct.
struct {}
// A struct with 6 fields.
struct {
x, y int
u float32
_ float32 // padding
A *[]int
F func()
}
一個聲明瞭類型但沒有指定域名稱的域被叫作 嵌入域(embedded field),……(更多翻譯省略,還有些複雜)。
還有 promoted fields,promoted methods,tag……(不太清楚)。
這個結構體類型還須要dig纔是!
-Pointer types
指針類型。
指的是 全部給定類型的變量的指針的集合,被稱爲指針的基本類型(zzzz)。
未初始化 的指針 是 nil。
取地址 運算符:&;指針變量:*。
-Function types
函數類型。
函數成爲了類型,這就是Go支持函數式編程的接觸吧!
一個函數類型 指的是 具備相同參數、返回值 的函數的集合。
未初始化 的函數 是 nil。
關鍵字 func。
函數的參數的名稱能夠存在,也能夠不存在。
參數 和 返回結果 列表必須加 圓括號,除非有一個沒有命名的結果(zzzz)。
注意,函數的最後一個參數 能夠用 三個點(...)作前綴,這即是此參數爲 可變參數,能夠 擁有 0到多個 元素。
官文的函數類型示例:
func() func(x int) int func(a, _ int, z float32) bool func(a, b int, z float32) (bool) func(prefix string, values ...int) func(a, b int, z float64, opt ...interface{}) (success bool) func(int, int, float64) (float64, *[]int) func(n int) func(p *T)
疑問,同一做用域下函數的名稱(不是簽名)是否能夠相同?但參數、返回類型不一樣?
-Interface types
接口類型。
和Java等面向對象中的接口不是同一個概念。
它是 一個 方法的集合。
未初始化 的接口類型 是 nil。
一個類型,其包含的全部方法 徹底涵蓋了 某接口類型 中定義的方法,那麼,就稱 這個類型實現了這個接口。
接口類型中的方法名稱是惟一的。
接口嵌入:把另外一個接口的類型名稱 放到 當前接口類型的定義中,實現嵌入。嵌入 也須要保證 方法名的 惟一性。
type Locker interface { Lock() Unlock() } type ReadWriter interface { Read(b Buffer) bool Write(b Buffer) bool } type File interface { ReadWriter // same as adding the methods of ReadWriter Locker // same as adding the methods of Locker Close() } type LockedFile interface { Locker File // illegal: Lock, Unlock not unique Lock() // illegal: Lock not unique }
注意:禁止嵌入 自身,禁止出現 環狀嵌入——你嵌入我、我嵌入你。
-Map types
映射類型(鍵值對)。
無序的元素集合,由鍵值對註冊,鍵有惟一性要求,鍵和值得類型是肯定的。
未初始化 的映射類型 是 nil。
鍵類型的要求:==、!= 運算符要實現!所以,鍵類型不能是函數、分片、映射類型。能夠是 接口類型,可是,這些運算符須要爲這些動態鍵值定義,失敗則返回run-time panic。
map[string]int map[*T]struct{ x, y float64 } map[string]interface{}
映射類型有 長度,用 len函數 獲取。
程序運行時能夠 賦值,使用 鍵值 獲取值,使用 delete函數 刪除值。
映射類型 也有 容量的概念,但不是限制值。
注意,nil 映射 和 空映射相等,除非,沒有元素被添加(原文:A nil
map is equivalent to an empty map except that no elements may be added.)(感受本身這翻譯有問題啊,仍是 官文有問題?)。
-Channel types
通道類型。
Go語言中最特別的類型了,用於支持併發等應用,重難點啊!
能熟練使用了,就算是熟悉Go開發了!
官文:
通道提供了實現併發執行函數的機制——經過發送和接受指定元素類型的值。未初始化的通道 是 nil。
可選的 運算符 <- 指明瞭通道的方向:發送、接收。如果沒有給出,這個通道就是 雙向的,又能夠發送 又能夠接收
chan T // can be used to send and receive values of type T chan<- float64 // can only be used to send float64s <-chan int // can only be used to receive ints
下面有個更復雜的用法:通道串聯。leftmost什麼的。直接看示例吧。(本身須要搞清楚)
chan<- chan int // same as chan<- (chan int) chan<- <-chan int // same as chan<- (<-chan int) <-chan <-chan int // same as <-chan (<-chan int) chan (<-chan int)
其它:
創建新的初始化的 通道 可使用 內建函數make,還能夠指定 容量(官文有更詳細的解釋)。
nil 通道不能被用於通訊。
通道可使用內建函數 close 關閉(上午試驗了一個程序,結果發生了一些問題)。
官文後面 又和 goroutine 扯上關係了,不懂啊,暫時就這樣了!
--------翻篇--------
好了,就這樣了,大半個下午就在這片博文中過去了!對於Go語言的類型,本身 熟悉 多少了呢?使用程度又怎樣呢?尤爲是它的一些重難點?
後面會寫 表達式、語句,再結合本文,應該會更好理解吧!
後續,Go開發水平進步了,必定要對這篇文章進行補充!由於目前這篇文章,最多得59分吧,離及格還差那麼一點點啊!