這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
func main() {x := 1defer func(a int) { fmt.Println("a=", a) }(x)defer func() { fmt.Println("x=", x) }()x++}
結果: x=2 a=1
說明: defer 調用所需參數在 defer 語句執行時就被已計算好了 (拷貝傳遞),閉包內則是引用,defer執行順序FIFO
數組和slice
數組是實值型別 slice是參考型別,
數組的建立 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)
每個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
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 literalfmt.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 {D1x int}func main() {d := Data{D1{10}, 20}d.x = 200d.D1.x = 100fmt.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) // 雖然接⼝口內的複製品未受到影響