第 19 頁
在 Go 語言中,所有的變量都以值得方式傳遞。因為指針變量的值是所指向的內(nèi)存地址,在函數(shù)間傳遞指針變量,是在傳遞這個地址值,所以依舊被看作以值得方式在傳遞。
第 39 頁
可以訪問 http://golang.org/pkg/fmt/ 或者在終端輸入 godoc fmt 來了解更多關(guān)于 fmt 包的細節(jié)。
第 40 頁
使用分布式版本控制系統(tǒng)(Distributed Version Control System,DVCS)來分享代碼,如 GitHub、Launchpad 還有 Bitbucket。Go 語言的工具鏈本身就支持從這些網(wǎng)站及類似網(wǎng)站獲取源代碼。
第 44 頁
go vet 命令會幫開發(fā)人員檢測代碼的常見錯誤。
第 46 頁
Go 語言有兩種方法為開發(fā)者生成文檔。可以在終端上直接使用 go doc 命令來打印文檔。可以使用 godoc 程序來啟動一個 Web 服務器,通過點擊的方式來查看 Go 語言的包的文檔。
go doc tar
godoc -http=:6060(這個命令通知 godoc 在端口 6060 啟動 Web 服務器。如果瀏覽器已經(jīng)打開,導航到 http://localhost:6060 可以看到一個頁面,包含所有 Go 標準庫和你的 GOPATH 下的 Go 源代碼的文檔)
第 53 頁
在 Go 語言里,數(shù)組是一個長度固定的數(shù)據(jù)類型,用于存儲一段具有相同的類型的元素的連續(xù)塊。
因為其占用的內(nèi)存是連續(xù)分配的,由于內(nèi)存連續(xù),CPU 能把正在使用的數(shù)據(jù)緩存更久的時間。而且內(nèi)存連續(xù)很容易計算索引,可以快速迭代數(shù)組里的所有元素。數(shù)組的類型信息可以提供每次訪問一個元素時需要在內(nèi)存中移動的距離。既然數(shù)組的每個元素類型相同,又是連續(xù)分配,就可以以固定速度索引數(shù)組中的任意數(shù)據(jù),速度非常快。
第 56 頁
在 Go 語言里,數(shù)組是一個值。這意味著數(shù)組可以用在賦值操作中。變量名代表整個數(shù)組,因此,同樣類型的數(shù)組可以賦值給另一個數(shù)組,復制之后,兩個數(shù)組的值完全一樣。
數(shù)組變量的類型包括數(shù)組長度和每個元素的類型。只有這兩部分都相同的數(shù)組,才是類型相同的數(shù)組,才能互相賦值。
復制指針數(shù)組,只會復制指針的值,而不會復制指針所指向的值,復制之后,兩個數(shù)組指向同一組字符串。
第 58 - 62 頁
數(shù)組本身只有一個維度,不過可以組合多個數(shù)組創(chuàng)建多維數(shù)組。多維數(shù)組很容易管理具有父子關(guān)系的數(shù)據(jù)或者與坐標系相關(guān)聯(lián)的數(shù)據(jù)。
只要類型一致,就可以將多維數(shù)組互相賦值,多維數(shù)組的類型包括每一維度的長度以及最終存儲在元素中的數(shù)據(jù)的類型。
因為每個數(shù)組都是一個值,所以可以獨立復制某個維度。
根據(jù)內(nèi)存和性能來看,在函數(shù)間傳遞數(shù)組是一個開銷很大的操作。在函數(shù)之間傳遞變量時,總是以值的方式傳遞的。如果這個變量是一個數(shù)組,意味著整個數(shù)組,不管有多長,都會完整復制,并傳遞給函數(shù)。
切片是一種數(shù)據(jù)結(jié)構(gòu),這種數(shù)據(jù)結(jié)構(gòu)便于使用和管理數(shù)據(jù)集合。切片是圍繞動態(tài)數(shù)組的概念構(gòu)建的,可以按需自動增長和縮小。切片的動態(tài)增長是通過內(nèi)置函數(shù)append
來實現(xiàn)的。這個函數(shù)可以快速且高效地增長切片。還可以通過對切片再次切片來縮小一個切片的大小。因為切片的底層內(nèi)存也是在連續(xù)塊中分配的,所有切片還能獲得索引、迭代以及為垃圾回收優(yōu)化的好處。
切片有 3 個字段的數(shù)據(jù)結(jié)構(gòu),這些數(shù)據(jù)結(jié)構(gòu)包含 Go 語言需要操作底層數(shù)組的元數(shù)據(jù)。這 3 個字段分別是指向底層數(shù)組的指針、切片訪問的元素的個數(shù)(即長度)和切片允許增長到的元素個數(shù)(即容量)。
使用內(nèi)置的make
函數(shù)創(chuàng)建切片時,需要傳入一個參數(shù),指定切片的長度.如果只指定長度,那么切片的容量和長度相等。也可以分別制定長度和容量,創(chuàng)建的切片,底層數(shù)組的長度是指定的容量,但是初始化后并不能訪問所有的數(shù)組元素。不允許創(chuàng)建容量小于長度的切片,容量小于長度的切片會在編譯時報錯。
如果在[]
運算符里指定了一個值,那么創(chuàng)建的就是數(shù)組而不是切片。只有不指定值的時候,才會創(chuàng)建切片。
第 64 頁
切片之所以被稱為切片,是因為創(chuàng)建一個新的切片就是把底層數(shù)組切出一部分。
第 66 頁
函數(shù)append
總是會增加新切片的長度,而容量有可能會改變,也可能不會改變,這取決于被操作的切片的可用容量。
第 68 頁
函數(shù)append
會智能地處理底層數(shù)組的容量增長。在切片的容量小于 1000 個元素時,總是會成倍地增加容量。一旦元素個數(shù)超過 1000,容量的增長因子會設(shè)為 1.25,也就是會每次增加 25% 的容量。隨著語言的演化,這種增長算法可能會有所改變。
第 75 頁
在函數(shù)間傳遞切片就是要在函數(shù)間以值的方式傳遞切片。由于切片的尺寸很小,在函數(shù)間復制和傳遞切片成本也很低。
在 64 位架構(gòu)的機器上,一個切片需要 24 字節(jié)的內(nèi)存:指針字段需要 8 字節(jié),長度和容量字段分別需要 8 字節(jié)。由于與切片關(guān)聯(lián)的數(shù)據(jù)包含在底層數(shù)組里,不屬于切片本身,所以將切片復制到任意函數(shù)的時候,對底層數(shù)組大小都不會有影響。復制時只會復制切片本身,不會涉及底層數(shù)組。
第 78 頁
切片、函數(shù)以及包含切片的結(jié)構(gòu)類型這些類型由于具有引用語義,不能作為映射的鍵,使用這些類型會造成編譯錯誤。
第 83 - 84 頁
Go 語言是一種靜態(tài)類型的編程語言,意味著編譯器需要在編譯時知曉程序里每個值的類型。
值的類型給編譯器提供兩部分信息:一,需要分配多少內(nèi)存給這個值(即值的規(guī)模);二,這段內(nèi)存表示什么。對于許多內(nèi)置類型的情況來說,規(guī)模和表示是類型名的一部分。int64
類型的值需要 8 字節(jié)(64 位),表示一個整數(shù)值;float32
類型的值需要 4 字節(jié)(32 位),表示一個 IEEE-754 定義的二進制浮點數(shù);bool
類型的值需要 1 字節(jié)(8 位),表示布爾值 true
和false
。
有些類型的內(nèi)部表示與編譯代碼的機器的體系結(jié)構(gòu)有關(guān)。例如,根據(jù)編譯所在的機器的體系結(jié)構(gòu),一個 int
值的大小可能是 8 字節(jié)(64 位),也可能是 4 字節(jié)(32 位)。還要一些與體系結(jié)構(gòu)相關(guān)的類型,如 Go 語言里的所有引用類型。
使用 var
創(chuàng)建一個變量并初始化其為零值。如果變量被初始化為某個非零值,就配合結(jié)構(gòu)字面量和短變量聲明操作符來創(chuàng)建變量。
一個短變量聲明操作符在一次操作中完成兩件事情:聲明一個變量,并初始化。
第 88 頁
Go 語言里有兩種類型的接收者:值接收者和指針接收者。
第 90 - 92 頁
Go 語言既允許使用值,也允許使用指針來調(diào)用方法,不必嚴格符合接收者的類型。這個支持非常方便開發(fā)者編寫程序。
內(nèi)置類型
分別是數(shù)值類型
、字符串類型
和布爾類型
。這些類型本質(zhì)上是原始的類型。因此,當對這些值進行增加或者刪除的時候,會創(chuàng)建一個新值。基于這個結(jié)論,當把這些類型的值傳遞給方法或者函數(shù)時,應該傳遞一個對應值的副本。
引用類型
有切片
、映射
、通道
、接口
和函數(shù)類型
。當聲明上述類型的變量時,創(chuàng)建的變量被稱為標頭
(header)值。從技術(shù)細節(jié)上說,字符串也是一種引用類型。每個引用類型創(chuàng)建的標頭值是包含一個指向底層數(shù)據(jù)結(jié)構(gòu)的指針。每個引用類型還包含一組獨特的字段,用于管理底層數(shù)據(jù)結(jié)構(gòu)。因為標頭值是為復制而設(shè)計的,所以永遠不需要共享一個引用類型的值。標頭值里包含一個指針,因此通過復制來傳遞一個引用類型的值的副本,本質(zhì)上就是在共享底層數(shù)據(jù)結(jié)構(gòu)。
第 122 頁
Go 語言里的并發(fā)指的是能讓某個函數(shù)獨立于其他函數(shù)運行的能力。當一個函數(shù)創(chuàng)建為 goroutine 時,Go 會將其視為一個獨立的工作單元。這個單元會被調(diào)度到可用的邏輯處理器上執(zhí)行。Go 語言運行時的調(diào)度器是一個復雜的軟件,能管理被創(chuàng)建的所有 goroutine 并為其分配執(zhí)行時間。這個調(diào)度器在操作系統(tǒng)之上,將操作系統(tǒng)的線程與語言運行時的邏輯處理器綁定,并在邏輯處理器上運行 goroutine。調(diào)度器在任何給定的時間,都會全面控制哪個 goroutine 要在哪個邏輯處理器上運行。