程式結構
基礎部分僅僅列舉和其他語言不一樣的地方(C語言為例)。
宣告
Go語言有四個主要宣告:var、const、type、func,類似於C語言中的變數,常量,結構體和函式。
package main //表明檔案屬於哪個包 import "fmt" const boilingF = 212.0 //包級別宣告,類似於全域性變數 func main() { var f = bologna //區域性變數 var c = (f-32)*5/9 fmt.Printf("boiling point = %gF or %gC\n",f,c) }
變數使用
定義
通用形式:var name type = expression,type和expression可省略一個。型別省略,由expression決定;表示式省略初始值對應零值。Go語言不存在未初始化的變數。
var b,f,s=true,2.3,"four" //多型別宣告
短變數形式:name:=expression,型別由expression決定,僅僅初始化一個新的變數才能用,同樣可以宣告多個變數如: i,j:=0,1 僅僅對可讀性有幫助的時候才用這種形式。
指標使用
指標的概念和訪問符號和C語言一樣,只是定義時候不一樣而已。
定義:*type
指標型別的零值是nil。
new函式
用法:new(T),建立一個T型別變數,初始化,並返回其地址。
go語言裡new不是一個關鍵字,可以重定義為另外的其他型別。如果使用new作為自定義變數名字,那麼這個變數作用域內new函式就不能用了。
變數生命週期
生命週期概念不在介紹,我們知道變數生命週期可以根據它所分配的空間來定。但是go語言編譯器選擇使用堆或棧上的空間不是基於使用var或new關鍵字的。看個例子:
var global *int func f(){ var x int x = 1 global = &x }
func g(){
y:=new(int)
*y=1
}
按照C語言習慣,區域性變數使用的是棧空間,但這裡x一定使用堆空間,因為它在f函式返回之後還可以通過global訪問,這種情況我們稱x從f逃逸。g函式返回後,y就不可訪問了,可被回收,即便使用new,編譯器也會在棧上分配*y。
垃圾回收對於寫出正確程式有巨大幫助,但是變數的生命週期是寫出高效程式所必須的。記住它在效能優化時候是有好處的,因為每一次變數逃逸都需要一次額外的記憶體分配過程。
賦值
go語言支援多重賦值。在實際更新變數前,右邊所有的表示式被推演(即被計算出來),當變數同時出現在賦值符兩側時候特別有用。
交換兩個變數的值 x,y=y,x
但是獨立語句更易讀。
因為go語言函式支援多返回值,所以可以將不需要的值賦給空識別符號 _,err = x.(T)
型別宣告
用法:type name underlying-type
相當於C++的typedef關鍵字。
包和檔案
包的作用和其他語言中的庫或模組作用類似,用於支援模組化、封裝、編譯隔離和重用。gopl.io/ch1/helloworld包檔案儲存在目錄$GOPATH/src/gopl.io/ch1/helloworld中。
每一個包給他的宣告提供獨立的名稱空間。
包讓我們可以通過控制變數在包外面的可見性或匯出情況來隱藏資訊;管理識別符號是否對外可見規則:匯出識別符號以大寫字母開頭。
匯出的包級別的宣告在同一個包的所有檔案中可見,因為包級別的常量名字以大寫字母開頭,可以使用packag.name來訪問。
package宣告前面緊挨著文件註釋對整個包進行描述。
匯入
go語言中每一個包通過import來匯入。語言的規範沒有定義從哪來以及含義,這依賴於工具來解釋。匯入宣告可以給匯入的包一個短名字,用來在整個檔案中引用包的名字。
如果匯入一個沒有被引用的包,就會觸發錯誤!!
包的初始化從初始化包級別變數開始,在依賴已解析完畢的情況下,根據依賴的順序進行。
var a = b+c //最後初始化a var b = f() //然後初始化b var c = 1 //首先初始化 func f() int { return c+1 }
如果包由多個檔案組成,初始化按照編譯器收到的檔案順序進行:go工具會在呼叫編譯器前將.go檔案進行排序。