1 channel實現CSP模型
2 記憶體配置:tcmalloc
3 動態庫buildmode功能???
4 缺乏真正意義上的調試器嗎???
5 依賴包管理問題???
6 編譯器將未使用的局部變數定義當作錯誤
7 函數可以返回函數類型func test() func(int) {
return func(x int) {
println("x:", x)
}
}
8 defer定義延遲調用,無論函數是否出錯都確保結束前被調用
9 ok-idiom(A跌目)模式:多傳回值中用一個名為ok的布爾值來標記操作是否成功,因為很多操作預設返回零值,所以需要額外說明
10 結構中的匿名欄位,結構的執行個體可以直接調用匿名欄位的方法和屬性
11 介面使用duck type方式
12 channel和goroutine實現通訊代替共用記憶體的CSP模型
1 電腦中變數是一段或者多段用來儲存資料的記憶體,類型決定變數記憶體的長度和儲存格式,所以我們只能修改變數值不能修改類型
2 記憶體配置發生在運行時,編譯後的機器碼不使用變數名而是直接使用記憶體位址訪問目標資料,所以編碼階段採用易於閱讀的變數名
3 慣例建議以組的方式整理多行變數定義 var {x,y int }
4 簡短聲明一般用於函數多傳回值,以及if for switch等語句中定義局部變數
5 未使用的局部變數會編譯出錯,全域變數不報錯
6 命名建議字母或底線開始,多字母數字和底線組合,局部變數優先短名
7 常量實在預先處理階段展開成指令資料,變數是在運行期分配儲存記憶體.(所以常量無法定址,沒有地址)
8 byte是uint8的別名 rune是int32的別名 別名直接可以相互賦值不需要類型轉換
9 擁有相同的底層結構不代表就屬於別名
10 new為指定類型分配零值記憶體返回指標;make是參考型別專用的建立函數(記憶體配置和屬性初始化)
11 多個type可以組合初始化
12 未命名類型:數組、切片、字典、通道等類型與具體元素類型或長度等屬性相關的類型,可以用type將其改變成命名類型
13 對於未命名類型 struct tag不同也屬於不同類型,欄位順序不同也屬於不同類型。
1 程式=演算法+資料 演算法:解決問題的過程,小到加法指令大到分布式叢集
2 乘冪和絕對值運算在math包的Pow和Abs中
3 自增自減只能作為獨立語句
4 指標是實體會分配記憶體空間,記憶體位址是記憶體中每個位元組單元的唯一編號
5 指標類型指向相同地址或nil則相等,但是不能做加減和類型轉換
6 unsafe.Pointer將指標轉換為uintptr進行加減運算,但可能造成非法訪問
7 指標不能用->,統一使用.
8 複合類型初始化,必須包含類型標籤;左花括弧必須在類型尾部;多成員都好隔開;多行右側必須是逗號或者花括弧
9 switch 無需顯式執行break,但是想順序執行需要顯式執行fallthrough
10 range迭代是複製資料
11 goto只能跳轉到同級代碼,不能跨層級
12 break用於switch for select,終止整個語句塊執行
13 continue只用於for迴圈,終止後續邏輯立即進入下一輪迴圈
1 函數無需前置聲明;不支援命名嵌套定義;不支援同名重載;不支援預設參數;支援不定長參數;支援多傳回值;支援命名傳回值;支援匿名函數和閉包
2 函數類型只支援nil判斷,不支援其他比較操作
3 從函數返回局部變數指標是安全的,編譯器會通過逃逸分析來決定是否在堆上分配記憶體;所以參數盡量減少值拷貝
4 函數建議命名規則:動詞+名稱;避免不必要的縮寫(printError優於printErr);避免使用類型關鍵字;使用習慣用語(init表示初始化,is/has返回布爾值);用反義詞命名行為相反的函數
5 不管是指標、參考型別還是其天涯型別參數,都是值拷貝傳遞,區別在於拷貝的目標對象
6 指標傳遞壞處在於延長該變數的聲明周期,也可能導致他分配到堆上增加效能消耗
7 函數參數在函數內部有效,範圍是整個函數內部
8 變參 func test(a ...int){} test(a[:]...)
9 命名傳回值的問題: 新定義的同名局部變數會引起同名遮蔽:xx is shadowed during return ;此時實名return即可
10 閉包 匿名函數能夠使用內容相關的環境中的資料(最終資料)
11 延遲調用defer 常用於資源釋放 解除鎖定 錯誤處理等 先入後出。 延遲調用開銷很大,效能要求高壓力大的演算法盡量避免使用
12 error是介面類型
13 panic會引發函數中斷執行defer ,在defer中使用recover捕獲panic提交的錯誤對象(recover只能在defer中執行才有效)
14 多個panic僅最後一個被捕獲
15 runtime/debug.PrintStrack()可以列印完整的堆棧資訊
16 不可恢複性、導致系統無法正常工作的錯誤才會使用panic (檔案系統沒許可權操作、服務連接埠被佔用、資料庫未啟動等)
1 字串是不可變位元組(byte)序列,可用len擷取長度,不可用cap; ` 支援跨行;允許位元組數組訪問,單不允許位元組數組取地址
2 用切片指向數組時,底層還是指向該字串
3 range遍曆可以列印出漢字,len遍曆出的漢字是亂碼
4 append可以向[]byte追加 =》var bs []byte bs=append(bs,"abc"...)
5 字串加法運算每次都會重新分配記憶體,構建大字串效能極差;方法1:strings.Join 方法2:bytes.Buffer 小字串拼接使用fmt.Sprintf text/template等
6 utf8.RuneCountInString(s)代替len擷取帶漢字的字串長度
7 長度是數組的類型組成部分,元素類型相同長度不同的數組不是同一類型
8 多維陣列,只第一維支援... [...][10]
9 如果元素支援== !=操作,則數組也支援
10 數組時實值型別
11 切片:不是動態數組或數組指標;內部通過指標引用底層數組,設定相關屬性將資料讀寫操作限定在指定地區內。
12 切片本身是唯讀對象,工作機制類似數組指標的封裝 右半開區間 數組必須addressable
type slice struct{
array unsafe.Pointer
len int
cap int
}
13 切片引用數組時,切片指標會指向數組地址;訪問越界會報錯;append會追加數組,當長度大於cap時會重新分配地址,則切片和數組就相互獨立了
14 切片 var a[]int 為nil,僅代表他為初始化,但依舊分配記憶體;且a[:]依舊是nil
15 如果切片長時間佔用大數組的少量資料,建議切片單獨分配地址,以讓大數組儘早釋放
16 可將字串直接複製到[]byte => b:=make([]byte,3) n:=copy(b,"abcdefhg")=>n=3,b=[97 98 99]
17 字典的key必須支援== != 如數字、字串、指標、數組、結構、介面
18 if v,ok:=m["d"];ok{存在} 使用ok-idiom模式判斷key是否存在
19 delete(m,"d"),刪除不存在的key不報錯
20 map使用range迭代每次順序不定
21 map被設計成 no addressable,所有沒法修改value的成員(如果value是個結構或者數組等) ;改進方法1:先擷取完整value,修改後再賦值回去;方法2:value採用指標類型
因為value是指標,所有可以通過指標修改指標指向的資料。
22 map並行作業,某任務針對map寫操作,其他任務對該map的讀寫刪除都會導致進程崩潰;可用sync.RWMutex實現同步(不要使用defer)
23 map對象本身就是指標封裝,傳參不需要取地址
24 map建立時和slice一樣要預選分配足夠地址,減少擴張時不必要的記憶體配置和重新雜湊操作=>make(map[int]int,1000)
25 對于海量小對象,應該直接用字典儲存索引值資料拷貝而不是指標,這樣減少掃描對象的數量縮短記憶體回收時間。
26 字典不會收縮記憶體,適當替換新對象是有必要的。。。
27 結構推薦命名初始化,以防擴充結構時報錯
28 匿名結構
u:=struct{
name string
}{
name:"xxx",
}
29 只有所有成員都支援==操作時,結構才支援相等操作
30 匿名字典隱式的以類型名為欄位名稱,使用時可以直接飲用匿名欄位的成員,但是初始化時必須當做獨立欄位。(但是隱式欄位是外部類型的話,隱式名稱不包含包名)
31 除介面指標 多級指標外的任何命名類型都可作為匿名型別
32 不能講基礎類型和其指標類型同時匿名,因為他們的匿名名稱相同
33 欄位標籤是對欄位描述的中繼資料,是類型的組成部分;運行期間可用反射擷取標籤資訊,通常作為格式校正和資料庫關係映射等
p1:=p{
name:"xxx",
sex:1,
}
v:=reflect.ValueOf(p1)
t:=v.Type()
for i,n:=0,t.NumField();i<n;i++{
fmt.Printf("%s:%v\n",t.Field(i).Tag,v.Field(i))
}
33 reflect.StructTag提供了更完善的功能
1 前置執行個體接收參數-receiver
2 receiver是基礎類型則會被複製,指標類型則必須能擷取執行個體地址
3 receiver類型選擇:不修改的小對象或固定值用T;參考型別、字串、函數等指標封裝對象用T;修改執行個體狀態用*T;包含Mutex等同步欄位用*T,大對象或不確定情況用*T;;
4 匿名型別的方法也存在同名遮蔽的特性。(可實作類別似覆蓋操作)
5 T的方法集是 receiver T;*T的方法集是receiver T+*T
6 匿名嵌入S,T包含 receiver S;匿名嵌入*S,T包含 receiver S+*S; 匿名嵌入S或*S,*T都包含 receiver S+*S;
7 方法集僅影響介面實現和方法運算式轉換。匿名欄位就是為方法集準備的
1 chan,一次性事件使用chan的close效率更高
向close的chan發資料panic
從已關閉的chan接收資料返回已快取資料或零值
無論手法,nil通道都會阻塞
2 同步問題應該用鎖或原子變數來操作
對效能要求較高時,贏避免使用defer unlock
讀寫並發時,用RWMutex效能更好
對單個資料的讀防寫保護建議使用讀寫鎖
嚴格測試,儘可能開啟資料競爭檢查
3 通道傾向於解決邏輯層次的並發處理架構
4 鎖用來保護局部範圍內的資料安全