运行时错误:无效的内存地址或空指针解引用

huangapple go评论79阅读模式
英文:

Runtime error: invalid memory address or nil pointer dereference

问题

我是你的中文翻译助手,以下是你提供的代码的翻译:

package main

import (
	"crypto/tls"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"time"
)

var tr = &http.Transport{
	TLSClientConfig:     &tls.Config{InsecureSkipVerify: true},
	MaxIdleConnsPerHost: 25,
	DisableKeepAlives:   true,
	Proxy:               http.ProxyFromEnvironment,
	Dial: (&net.Dialer{
		Timeout:   10 * time.Second,
		KeepAlive: 10 * time.Second,
	}).Dial,
	TLSHandshakeTimeout: 5 * time.Second,
}
var client = &http.Client{Transport: tr}

func makeGetRequest(uri string) *http.Response {
	req, err := http.NewRequest("GET", uri, nil)
	if err != nil {
		fmt.Println(err)
	}
	req.Header.Add("User-Agent", "Hi it's me again")
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
	}
	return resp
}

func advancedFetcher(uri string, c chan int) {
	fmt.Println("Getting: ", uri)
	resp := makeGetRequest(uri)
	defer resp.Body.Close()
	c <- resp.StatusCode
}

func basicFetcher(uri string, c chan int) {
	fmt.Println("Getting: ", uri)
	resp, err := http.Get(uri)
	if err != nil {
		fmt.Println(err)
	}
	defer resp.Body.Close()
	_, err = ioutil.ReadAll(resp.Body)
	c <- resp.StatusCode
}

func main() {
	c := make(chan int)
	rows := []string{"https://www.google.com", "http://www.fdicconnect.gov"}
	for _, row := range rows {
		//go basicFetcher(row, c)
		go advancedFetcher(row, c)
	}
	for _ = range rows {
		select {
		case result := <-c:
			fmt.Println(result)
		}
	}
	fmt.Println("All Done")
}

这段代码是一个简单的网络爬虫。你遇到了一个"panic: runtime error: invalid memory address or nil pointer dereference"错误,并且不知道如何解决这个问题。你有一个"advancedFetcher"函数和一个"basicFetcher"函数,但无论使用哪个函数都会出现相同的错误。这个答案建议检查每个错误(我认为你已经做到了),但你仍然会遇到错误。谢谢!

英文:

I am new to go and trying to make a simple webcrawler. I keep getting a "panic: runtime error: invalid memory address or nil pointer dereference" and have no idea how to fix the issue. I have an "advancedFetcher" function and a "basicFetcher" function and I get the same error under either one. This answer suggests checking each error (which I have I think) but I am still getting an error. Thanks!

package main
import (
&quot;crypto/tls&quot;
&quot;fmt&quot;
&quot;io/ioutil&quot;
&quot;net&quot;
&quot;net/http&quot;
&quot;time&quot;
)
var tr = &amp;http.Transport{
TLSClientConfig:     &amp;tls.Config{InsecureSkipVerify: true},
MaxIdleConnsPerHost: 25,
DisableKeepAlives:   true,
Proxy:               http.ProxyFromEnvironment,
Dial: (&amp;net.Dialer{
Timeout:   10 * time.Second,
KeepAlive: 10 * time.Second,
}).Dial,
TLSHandshakeTimeout: 5 * time.Second,
}
var client = &amp;http.Client{Transport: tr}
func makeGetRequest(uri string) *http.Response {
req, err := http.NewRequest(&quot;GET&quot;, uri, nil)
if err != nil {
fmt.Println(err)
}
req.Header.Add(&quot;User-Agent&quot;, &quot;Hi it&#39;s me again&quot;)
resp, err := client.Do(req)
if err != nil {
fmt.Println(err)
}
return resp
}
func advancedFetcher(uri string, c chan int) {
fmt.Println(&quot;Getting: &quot;, uri)
resp := makeGetRequest(uri)
defer resp.Body.Close()
c &lt;- resp.StatusCode
}
func basicFetcher(uri string, c chan int) {
fmt.Println(&quot;Getting: &quot;, uri)
resp, err := http.Get(uri)
if err != nil {
fmt.Println(err)
}
defer resp.Body.Close()
_, err = ioutil.ReadAll(resp.Body)
c &lt;- resp.StatusCode
}
func main() {
c := make(chan int)
rows := []string{&quot;https://www.google.com&quot;, &quot;http://www.fdicconnect.gov&quot;}
for _, row := range rows {
//go basicFetcher(row, c)
go advancedFetcher(row, c)
}
for _ = range rows {
select {
case result := &lt;-c:
fmt.Println(result)
}
}
fmt.Println(&quot;All Done&quot;)
}

EDIT #1:

Getting:  https://www.google.com
Getting:  http://www.fdicconnect.gov
200
Get http://www.fdicconnect.gov: dial tcp 167.176.6.86:80: i/o timeout
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x400ff2]
goroutine 21 [running]:
runtime.panic(0x6594c0, 0x7e9b53)
/usr/local/go/src/pkg/runtime/panic.c:279 +0xf5
main.advancedFetcher(0x6c3b70, 0x1a, 0xc208004180)
/home/me/go/src/testfolder/tester/main.go:41 +0x1c2
created by main.main
/home/me/go/src/testfolder/tester/main.go:61 +0x123
goroutine 16 [chan receive]:
main.main()
/home/me/go/src/testfolder/tester/main.go:65 +0x198
goroutine 19 [finalizer wait]:
runtime.park(0x413bd0, 0x7ee660, 0x7ec8c9)
/usr/local/go/src/pkg/runtime/proc.c:1369 +0x89
runtime.parkunlock(0x7ee660, 0x7ec8c9)
/usr/local/go/src/pkg/runtime/proc.c:1385 +0x3b
runfinq()
/usr/local/go/src/pkg/runtime/mgc0.c:2644 +0xcf
runtime.goexit()
/usr/local/go/src/pkg/runtime/proc.c:1445
goroutine 17 [syscall]:
runtime.goexit()
/usr/local/go/src/pkg/runtime/proc.c:1445

答案1

得分: 5

你的程序在恐慌之前是否打印了错误?如果我没记错的话,如果http.Get返回一个错误,那么resp.Body == nil,这会导致你的错误,因为你不能在nil上调用resp.Body.Close()

正如twotwotwo建议的,你应该编写你的函数,使其返回一个(结果,错误)对,这样你就可以在遇到问题之前优雅地终止它。

英文:

Is your program printing an error before panicking? If memory serves, if http.Get returns an error, then resp.Body == nil, which would cause your error because you can't call resp.Body.Close() on nil.

As twotwotwo suggests, you should write your function so that it returns a (result, error) pair so you can terminate it gracefully before running into problems.

huangapple
  • 本文由 发表于 2014年11月4日 09:16:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/26726203.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定