func main() { x := 1 defer func(a int) { fmt.Println("a=", a) }(x) defer func() { fmt.Println("x=", x) }() x++ }
結果: x=2 a=1 golang
說明: defer 調用所需參數在 defer 語句執行時就被已計算好了 (拷貝傳遞),閉包內則是引用,defer執行順序FIFO 數組
數組和slice 閉包
數組是值類型 slice是引用類型, app
數組的建立 arr:=[...]int{1,2,3} arr:=[3]int{} arr:=new([10]int) (注意new返回的是[10]int的指針類) 性能
slice的建立 slice:=[]int{1,2,3} slice:=arr[n:m]( n <= x < m) slice:=make([]int,len,[cap]) (cap default=len) spa
每一個slice指向了一個底層數組,對slice的更新會反映到這個底層數組上,cap=slice在數組的start_index到數組的end_index 指針
reslice slice1:=slice2[n:m] 在slice進行reslice時若是n,m超過了cap 不會引起底層數組的重分配 ,而會panic: runtime error: index out of range code
append(s1,1,2,3) 能夠引起底層數組重分配 增長一個cap 對象
copy(dst,src) len=min(len(dst),len(src)) 繼承
map
d := map[*int]struct{ x, y float64 } { &10: { 1.0, 2.0 } }
struct 和數組同樣 也是 值類型
type s1 struct { s2 struct { a int } } func main() { m := map[int]struct{ a int }{1: {1}}//正確 fmt.Println(m) s := s1{{1}}//異常 missing type in composite literal fmt.Println(s) }匿名struct能夠做爲map的value並且賦值方便,而匿名struct做爲struct的成員則在初始化時 須要帶上struct的名字才行,成員變量 匿名struct 就不方便了。
struct拷貝複製
u := User{ 100, "Tom" } var u2 *User = new(User) *u2 = u
匿名成員 (組合優於繼承)
type D1 struct { x int } type Data struct { D1 x int } func main() { d := Data{D1{10}, 20} d.x = 200 d.D1.x = 100 fmt.Println(d) }
接口類型推斷
if o,ok:=i.(User);ok{ o.xxx } switch o:=i.(type){ case User: xxx case Man: xxx }
將對象賦值給接口變量時,會發發生值拷貝行爲
u := User{ 1, "Tom" } i := Tester(u)//強制轉換 賦值發生的是copy動做 //在golang裏要千萬注意 = 這個賦值動做 都是copy動做,若是copy的對象是個指針的話性能會比較好 u.Id = 100 // 顯式修改的原對象 u.Name = "Jack" fmt.Println(u, i) // 雖然接⼝口內的複製品未受到影響