好的,所以我有这段代码
func registerDomain(domainName string, n int) bool {
//building the request here
resp, errr := client.Do(r)
if errr != nil {
if n == 1 {
return false
}
registerDomain(domainName, n-1)
}
bodyBytes, err2 := ioutil.ReadAll(resp.Body)
if err2 == nil {
resp.Body.Close()
//handle bodyBytes
//if the response is how it should be return true, if it's not call the function again with n-1
} else { //if there is an error reading the response
resp.Body.Close()
if n == 1 {
return false
}
registerDomain(domainName, n-1)
}
return false //it should never reach this line
}
解释:
我用一个参数 n(比如说 5)调用该函数,该参数表示如果出现问题,该函数将重试的次数。每次出现问题时,我都会使用 n-1 进行递归调用,因此当它达到 n=1 时,它会放弃并返回 false。这段代码在实践中运行良好,它完成了它应该做的事情,有时当响应不正确时,它会递归地调用自己,并且它会在第二次(或第三次、第四次......)时间运行。当问题在 n=1 之前没有解决时,它返回 false。
问题:
这是一段大代码的一部分,它应该运行大约 17 个小时,当它尝试从正文中读取时,它有时会在这一行上出现恐慌:
bodyBytes, err2 := ioutil.ReadAll(resp.Body)
它说恐慌:运行时错误:无效的内存地址或零指针取消引用。现在我知道这可能意味着它正在尝试从不存在的 resp.Body 中读取,但Go 文档明确指出当 err 为 nil 时,resp 始终包含非 nil resp.Body。
因此,在我看来,这可能与递归调用有关。对我来说唯一有意义的是这种情况:假设 errr 不是 nil (这意味着 resp.Body 不存在),所以它进入 if errr != nil 并且因为 n!= 1,它会再次调用自己,n=4。假设这次一切正常,第二个函数对第一个函数返回 true,但第一个函数继续执行并尝试从不存在的 resp.Body 中读取。这会引起恐慌,我们在这里......
所以,我需要的是一个确切地知道递归函数是如何工作的人,如果不是这样,我可以在阅读它之前以某种方式检查 resp.Body 的存在,或者有帮助的东西。
不管怎么说,多谢拉!:)
更新:你很好,我的代码不再恐慌,我也没有。非常感谢!(我不确定这是否是更新的地方)