技巧
golang可以在函數定義的時候確定其返回值具體為
func foo(arg int)(res int){}
go env GOPATH
可以用來去查看當前的GOPATHgolang
查找問題, 可以根據Gogland
和ack
工具一起結合查找golang
中的init
函數用來初始化一些變量, 它總是會被運行, 只要導入了這個包, 初始化就會在run main之前被運行
golang
中的接口類型, 以接口類型傳入參數, 如果該接口類型, 實現了方法則okproto.String()
是一個helper方法, 分配一個新的空間, 并返回一個指向它的指針golang
中首字母大寫表示public
, 首字母小寫則表示protect
或者private
golang
中defer
語句的執行順序為逆序golang
中有時候為了診斷方便, 可以使用printStack
即runtime.Stack(buf[:], false)
io.Writer
是golang中接口類型的一種典型的運用, Fprintf=>(Printf, SPrintf)Stringer
接口通常用于對于printf
或者println
等一些列的函數數輸出golang
中的數組array
為定長數組, 如兩個數組相比較必須是comparable
即長度和類型必須一致golang
語言定義變量或者結構體在編譯期就已經復制, 在運行期賦值, 需要重新定義一個函數golang
中flag
庫需要使用flag.parse()
來傳遞參數buffer channel
在channel
中的元素個數小于channel size
時為非阻塞的, 達到channel size
之后則阻塞當前線程直到元素被取出.0 buff channel
即為sync channel
. 生產者和消費者都會被阻塞.golang
中對比并行程序設計有: 設置返回channel, 以經典的生產者消費者模式進行處理.timer
主要是用來設置定時任務,tickers
主要是用來設置周期任務.使用
sync.Mutex
通過對全局變量的Lock
和UnLock
實現atomic加鎖和解鎖對于
Atomic inc
也可以使用sync/atomic
庫實現.CAS
:Compare And Swap
比較并交換, 在golang中是以共享內存方式實現的一種同步機制.Share memory by communicating; don't communicate by sharing memory.
golang中更好的一種方式是通過sync包以及channel來實現同步機制.
time.Sleep
vstime.After
time.After
通常于select
搭配使用, 可以設置超時機制time.Sleep
可讀性更強, 暫停當前Goroutine, 直到達到時間.timer
通過AfterFunc
或NewTimer
來創建, 使用Reset
來重置, timer. 使用Stop
來停止timer
, 停止timer
之后, 相應的goroutine
會被阻塞.timer
使用時, 如果使用了timer.Stop()
, 則timer, 會被GC所回收, 但是timer對應的channel
不會關閉, 則channel
將會被永遠的阻塞.timer.Stop
對應的timer
被GC所回收,timer.C
被阻塞, 如果再使用timer.Reset
,則重新給timer對應的時間賦值并放入timer.C
中timer
使用的正確姿勢是, 使用timer.Reset
, 而不是使用timer.Stop
. 如果使用指針并且使用對應的timer.Channel
. 重置timer
時, 應當使用Reset
而不是重新Stop
+NewTimer
來重置, 這樣會導致內存泄漏, 阻塞goroutine
deadlock
死鎖: 多個線程占有一部分資源, 去請求另一部分資源時阻塞. 這些線程等等其他的線程釋放資源. (已請求到鎖)livelock
:活鎖, 不斷請求鎖, 但是無法請求到資源. (未加鎖)select
與channel
搭配使用, 如果要實現類似listener
的模式, 則需要在外層加for {select ...}
.通常使用
select
實現函數超時機制.HTTP keep-alive
是保持TCP
連接open
, 即復用TCP連接的一種手段. 例如: 通過HTTP keep-alive
就可以實現不用每次都去重新建立HTTP
連接, 這樣就不會重新去請求靜態資源css
,html
等.TCP keep-alive
是TCP協議定時地發送空的ack
包來確認彼此的狀態.TCP keep-alive
和HTTP keep-alive
是兩個不同的技術, 不存在誰依賴誰的關系.TCP keep-alive
用來檢測對端是否存在, 而HTTP keep-alive
用來協商以復用連接.context
上下文類型,帶有deadline,取消信號,還有其他與請求相關的request-scoped的值context
遵循的幾個原則:不要將
Context
放入結構體,使用Context
應該作為第一個參數傳入,并命名為ctx,func DoSomething(ctx context.Context, arg Arg) error {//use ctx}
即使函數允許,不要傳入
nil
的Context.如果不知道用哪種Context,使用context.TODO()
使用context的
Value
相關的方法只應該用于在程序和接口中傳遞和請求相關元數據,不要用它傳遞可選參數相同的Context可以傳遞給不同的
goroutine
, Context并發安全sync.Map
go1.9支持的線程安全的map,通過cas實現reflect: go語言反射機制。reflact反射是一種機制,這種機制可以實現自我類型的檢查和描述
init
函數在main函數之前執行,通常用作初始化sync.Once
保證程序僅僅執行一次actionpanic
類似于拋出異常,即停止當前正確的程序流程, panic之后會執行defer函數recover類似于恢復異常,即panic會一直向上拋出阻礙正常流程,直到recover則恢復
具體的某個golang對象初始化時候,通常的一種寫法是通過
OptionFunc
來初始化一些可選參數// +build
:是golang的build tag
例如// +build linux,386 darwin,!cgo
等價于(linux AND 386) OR (darwin AND (NOT cgo))go build -tags="linux 386"
進行編譯, 并根據Build Constraints
的條件進行編譯golang make初始化并分配內存
golang
%#v
與%+v
為打印變量并打印其變量名value receiver
和pointer receiver
value receiver
是并發安全的, 且不改變value本身的值, copy by valuepointer receiver
不是并發安全的,且可以改變pointer本身的值golang elastic 使用Scorll可以滾動的獲取所有請求的結果
dep 為官網golang包管理工具
dep init
: 效率較低,初始化golang項目的獨立環境,利用gps分析出當前代碼包中的依賴關系,并將其約束寫入項目中的,Gopkg.toml
文件中。將所有依賴的包最新的version/branch/revision信息寫入Gopkg.lock
,創建vendor目錄,并以Gopkg.lock為輸入,將其中包下載到vendor目錄下面。dep status
: 查看當前項目下的status的狀態dep ensure
: 確保當前項目的vendor處于一個正確的狀態gorilla/mux
: golang 非常受歡迎的URL router dispatchergoconvey
: golang 帶UI的單元測試框架,可以很好的顯示單元覆蓋度ACL: access control list 訪問控制列表,是路由器和交換機接口的指令,用于控制端口進出的數據包,ACL提供了網絡安全訪問的基本手段。
map[string]*person{}
與map[string]person{}
的區別在于指針和實例,實例為重新copy構造,改變內容之后,不改變map本身的內容, 末尾的{}為初始化map
OLAP
:Online Analytical Processing
: 在線數據處理關注于數據分析,OLTP: Online Transaction Processing
在線事務處理,類似于增刪查改,專注于查詢的速度一致性hash,為了解決彈性集群動態擴容的問題,通常的做法是構造
0~2^32-1
個hash環狀空間,對于具體的某個key找到對應服務器上節點時,只需要順序在環上轉動找到第一個命中的節點即可。當出現負載不均的情況時,可以考慮使用引入虛擬節點達到負載均衡的效果。GC
: Garbage collection 垃圾回收機制,常見的垃圾回收算法有: 引用計數,標記清除Mark-Sweep
法,三色標記法,分代收集法。引用計數:最基礎的垃圾回收算法,例如C++中的
std:shared_ptr
標記清除:分為兩個步驟:1. Mark: 從程序的根節點開始,遍歷所有的對象,對可達的節點進行標記。2. Sweep: 將所有未標記的節點對象作為垃圾進行回收清除操作。有一個問題是會有
STW(Stop The World)
的問題,算法進行標記時會暫停整個應用程序。當程序中的對象特別多時,遍歷整個對象樹會消耗很多的時間。go1.3三色標記:是
Mark-Sweep
的一個改進,支持并發,即可以實現on-the-fly
即在程序執行的同時進行垃圾回收 go1.6. 步驟如下:
1. 首先創建三個集合:白、灰、黑。
2. 將所有對象放入白色集合中。
3. 然后從根節點開始遍歷所有對象(注意這里**并不遞歸遍歷**),把遍歷到的對象從白色集合放入灰色集合。
4. 之后遍歷灰色集合,將灰色對象引用的對象從白色集合放入灰色集合,之后將此灰色對象放入黑色集合
5. 重復 4 直到灰色中無任何對象
6. 通過write-barrier檢測對象有變化,重復以上操作
7. 集所有白色對象(垃圾)
分代收集:也是
Mark-Sweep
的一個改進。該算法基于一個經驗:絕大多數的對象生命周期都很短,按照對象生命周期的長短來分代。
一般分代GC,分為3代,新生代(Young Generation),年老代(Tenured Generation),永久代(Permanent Generation)
原理如下:
1. 新對象放入第 0 代
2. 當內存用量超過一個較小的閾值時,觸發 0 代收集
3. 第 0 代幸存的對象(未被收集)放入第 1 代
4. 只有當內存用量超過一個較高的閾值時,才會觸發 1 代收集,2 代同理
因為 0 代中的對象十分少,所以每次收集時遍歷都會非??欤ū?nbsp;1 代收集快幾個數量級)。只有內存消耗過于