golang爬珍愛網代碼最佳化後,運行報了如下的錯,找了半小時才找到原因,在此記錄一下。
image
代碼是這樣的:
有一個interface類型的Parser:
type Parser interface { Parser(contents []byte, url string) ParserResult Serialize() (funcName string, args interface{})}
有一個struct類型的FuncParser:
type FuncParser struct { parser ParserFunc funcName string}
FuncParser 實現了Parser 介面:
func (f *FuncParser) Parser(contents []byte, url string) ParserResult { return f.Parser(contents, url)}func (f *FuncParser) Serialize() (funcName string, args interface{}) { return f.funcName, nil}
拋開爬蟲代碼整體的複雜度,將代碼簡化到如下這樣:
type ParserFunc func(url string) stringtype FuncParser struct { parser ParserFunc}func (f *FuncParser) Parser(url string) string { return f.Parser(url)}func main() { funcParse := FuncParser{ func(url string) string { return url }, } funcParse.Parser("http://www.zhenai.com/zhenghun")}
同樣運行代碼後同樣會報錯:
runtime: goroutine stack exceeds 1000000000-byte limitfatal error: stack overflowruntime stack:runtime.throw(0x467297, 0xe) D:/Program Files/Go/go103/src/runtime/panic.go:616 +0x88runtime.newstack() D:/Program Files/Go/go103/src/runtime/stack.go:1054 +0x72druntime.morestack() D:/Program Files/Go/go103/src/runtime/asm_amd64.s:480 +0x91
這個樣本就很明顯了,FuncParser的Parser裡形成了遞迴調用(自己調自己),
遞迴調用自身導致棧溢出,導致報錯。應該改成這樣:(小寫parser)
image.png
實際上goland裡已經提示了Recursive Call
image.png
一不小心就會寫出這種代碼,再看如下代碼:
package mainimport ( "fmt")type Str stringfunc (s Str) String() string { return fmt.Sprintf("Str: %s", s)}func main() { var s Str = "hi" fmt.Println(s)}
同樣報錯:
image.png
You are implementing Str.String in terms of itself. return fmt.Sprintf("Str: %s", s) will call s.String(), resulting in infinite recursion. Convert s to string first.
This is working as intended, you are using the %s verb to call Str's String method, which uses fmt.Sprint to call Str's String method, and so on.
正常代碼應該如下:
image.png
實際上,goland裡也會警告該問題的:
image.png
看來平時編寫代碼,警告還是得注意的。
項目代碼見:https://github.com/ll837448792/crawler
最後,csdn資源,收集了海量學習資料,如果你準備入IT坑,勵志成為優秀的程式猿,那麼這些資源很適合你,包括java、go、python、springcloud、elk、嵌入式 、大資料、面試資料、前端等資源。同時我們組建了一個技術交流群,裡面有很多大佬,會不定時分享技術文章,如果你想來一起學習提高,可以關注以下公眾號後回複【2】,擷取。
我是小碗湯,我們一起學習,掃碼關注,精彩內容第一時間推給你
歡迎掃碼關注