今天試着按照上一篇博客的設計本身實現本身的crawler, 踩了一路坑。有些找到了答案,有些沒有。我先將這些坑記錄下來,而後divide and conquer。html
code snippetc++
1 package util 2 3 import ( 4 "math" 5 "sync" 6 ) 7 8 type IdGenerator interface { 9 NextId() (uint64, error) 10 } 11 12 type myIdGenerator struct { 13 rwmutex sync.RWMutex 14 seed uint64 15 } 16 17 func NewIdGenerator() (*IdGenerator, error) { 18 return new(myIdGenerator), nil 19 } 20 21 //???RWMutex - two steps: write after read. 22 func (this *myIdGenerator) NextId() (uint64, error) { 23 this.rwmutex.Lock() 24 defer this.rwmutex.Unlock() 25 26 //read 27 if this.seed == math.MaxUint64 { 28 return 0, error.New("util.id.NextId(): id overflow") 29 } 30 31 orig := seed 32 33 //write 34 seed++ 35 return orig, nil 36 }
坑一:struct -> interfacegolang
crawler\util\id.go:18: cannot use new(myIdGenerator) (type *myIdGenerator) as type *IdGenerator in return argument:
*IdGenerator is pointer to interface, not interfaceide
solution: http://jordanorelli.com/post/32665860244/how-to-use-interfaces-in-gopost
坑二:RWMutex read lock and write lock性能
原本計劃,用讀鎖保護 seed 的讀取,以後用寫鎖保護seed 的修改。可是這個讀取和寫應該在一個transaction中,也就是說在本身讀取到seed 和寫seed之間,seed 不能被其餘實體修改。ui
若是在讀鎖Lock時候,寫鎖重入(假定支持鎖升級重入),那麼就會出現一種經典的死鎖現象。A, B 都申請到了讀鎖,如今A準備升級到寫鎖,A等待B釋放讀鎖,B也要升級而等待A釋放讀鎖。this
本例中,資源鎖定的範圍並不大,一致用寫鎖對性能影響並不十分嚴重。可是若是讀寫臨界區都比較大,那麼怎麼解決呢?spa
坑三:interface 究竟是 struct 仍是 pointer? 這個應該與第一個坑屬於同一個問題的不一樣表象。設計
1 package base 2 3 import ( 4 "net/http" 5 ) 6 7 type Response struct { 8 resp *http.Response 9 depth uint 10 } 11 12 ... 13 14 func (this *Response) Valid() bool { 15 if this.resp != nil && this.resp.Body != nil { 16 return true 17 } 18 19 return false 20 }
注意這行代碼,
this.resp != nil && this.resp.Body
從定義中咱們知道this.resp的類型是一個指針,因此其零值是一個指針。可是咱們怎麼知道 this.resp.Body表示什麼,它是一個接口,其定義以下:
1 // Body represents the response body. 2 // 3 // The http Client and Transport guarantee that Body is always 4 // non-nil, even on responses without a body or responses with 5 // a zero-lengthed body. 6 // 7 // The Body is automatically dechunked if the server replied 8 // with a "chunked" Transfer-Encoding. 9 Body io.ReadCloser
是否是接口的實際類型都是指針,其零值都是nil?
若是接口能夠表示struct, 那麼編譯器如何判斷 obj == nil 類型是否匹配?難道編譯器知道interface 對應的真實類型, 用它的真實類型來判斷的嗎?
坑四 const in golang
golang 中的 const 比 c/c++中的 const 限定更加嚴格。
golang: const a = expr; <---- golang 中右邊必須是 編譯期能夠肯定的常量。
而在 c\c++ 中, const b = expr 右邊 能夠是 運行期才能肯定的值。
若是我要在程序中使用 一個運行期肯定的值,同時想限制在後繼操做中不能修改此值,在 golang 中如何實現?貌似不能實現。-> 十分苦惱