-- 名稱
有25個關鍵字,以前不常見的:chan,go,fallthrough
還有一些內置的預聲明的常量、類型和函數
常量:
true,false,iota,nil
類型:
int,8/16/32/64, uiint,8/16/32/64/ uintptr
float32,float64,complex128,complex64
bool,byte,rune,string,error
函數:make,len,cap,new,append,copy,close,delete,complex,real,imag,panic,recover
如果一個實體聲明在函數內部,就只能在函數內部可見。
如果聲明在函數外部,在包的所有源文件中可見。實體第一個字母大寫,表明其對其它包可見,否則不可見。
包名稱本身由小寫字母組成。
-- 聲明
包級別的類型,變量,常量,函數的聲明,不區分順序。
局部變量的聲明和初始化在函數執行期間進行,包級別的初始化在main開始之前進行。
-- 變量
var name type = expr,type和expr可以省略一個,但不能同時省略。
默認初始化爲零值:
- 數字類型:0
- 布爾類型:false
- 字符串:""
- 接口和引用類型(slice, 指針,map,通道,函數):nil
短變量聲明,只用在函數內部,用來聲明和初始化局部變量。
name := expr
:= 表示聲明,而 = 表示賦值。
:= 左側必須有一個新變量,如果一些變量在同一個詞法塊中已經聲明,那麼就等同於賦值,外層的聲明將被忽略。
例如:下面,i,k是聲明和初始化局部新變量,j是賦值。
func ShortVar()
{
var i = 0
if i==0 {
var j = 0
i, j, k := 0, 0, 0
}
}
-- 指針
變量是存儲值的地方,指針的值是一個變量的地址。不是所有值都有地址,但每個變量都有。
函數返回局部變量的地址是非常安全的。變量的生命週期由其引用決定,不由其作用域決定。
返回局部變量的引用,表明局部變量從函數中逃逸,對於逃逸的變量,需要在堆上分配空間,否則,在棧上分配空間。
-- new(T)
創建一個未命名的T類型變量,返回其指針。
-- 多重賦值
在實際更新左側的變量前,右側所有的表達式被推演/計算。
對於返回多個變量的函數或者表達式,左側變量個數需要一致,可以將不需要的使用空標識符。
_, err = io.Copy(dst, src),忽略字節數
一般布爾型用名稱ok,error類型err
賦值的類型,必須精確匹配,nil可以被賦值給任何接口類型和引用類型。
-- 類型聲明
type name underlying-type
T(x),將變量x轉換爲T類型的變量,不改變值,只改變類型。任何情況下,運行時的轉換都不會失敗。-- 什麼意思?
不同命名類型的值不能直接比較。
-- 包
包類似於其它語言的模塊,用於封裝。包由若干個.go文件組成。go工具在調用編譯器前將go文件排序。
包中的標識符,如果以大寫字母開頭,表明可以在其它包中訪問。
包的初始化,按照包級別變量聲明的順序進行,依賴優先,比如:
var a = b + c // 最後把a初始化爲3
var b = f() // 調用f(),b初始化爲2
var c = 1 // 首先c初始化爲1
func f() int { return c+1 }
任何文件可以包含任意數量的init()函數,它不能被調用或者引用,按照它們聲明的順序執行。
func init() { /* ... */ }
在包級別,聲明的順序和作用域沒有關係。所以,一個聲明可以引用它自己或者它後面的其它聲明。
再次強調,:=只能在func內起作用,必須有新變量,且如果同級別詞法塊中沒有的變量就會作爲新變量。即使外層有,會被屏蔽。比如
var cwd string
func init() {
cwd, err := os.Getwd() // 由於包級別的cwd不在這個詞法塊中,因此這裏新聲明瞭一個cwd,使得外面的不可訪問。
if err != nil {
}
}