正文

golang爬珍爱网代码优化后,运行报了如下的错,找了半小时才找到原因,在此记录一下。

爬虫遇到了点问题_正则

代码是这样的:

有一个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) string

type 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 limit
fatal error: stack overflow

runtime stack:
runtime.throw(0x467297, 0xe)
D:/Program Files/Go/go103/src/runtime/panic.go:616 +0x88
runtime.newstack()
D:/Program Files/Go/go103/src/runtime/stack.go:1054 +0x72d
runtime.morestack()
D:/Program Files/Go/go103/src/runtime/asm_amd64.s:480 +0x91

这个示例就很明显了,FuncParser的Parser里形成了递归调用(自己调自己),

递归调用自身导致栈溢出,导致报错。应该改成这样:(小写的parser)

爬虫遇到了点问题_正则_02

实际上goland里已经提示了Recursive Call

爬虫遇到了点问题_公众号_03

一不小心就会写出这种代码,再看如下代码:

package main

import (
"fmt"
)

type Str string

func (s Str) String() string {
return fmt.Sprintf("Str: %s", s)
}

func main() {
var s Str = "hi"
fmt.Println(s)
}

同样报错:

爬虫遇到了点问题_珍爱网_04


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.


正常代码应该如下:

爬虫遇到了点问题_爬虫_05

实际上,goland里也会警告该问题的:

爬虫遇到了点问题_公众号_06

看来平时编写代码,警告还是得注意的。

项目代码见:​​https:///ll837448792/crawler​



作者简洁


作者:小碗汤,一位热爱、认真写作的小伙,目前维护原创公众号:『我的小碗汤』,专注于写golang、docker、kubernetes等知识等提升硬实力的文章,期待你的关注。 转载说明:务必注明来源(注明:来源于公众号:我的小碗汤, 作者:小碗汤)