当使用http.Get()时出现无效的内存地址或空指针解引用。

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

invalid memory address or nil pointer dereference when use http.Get()

问题

我刚开始学习Go语言,我写了一个小示例,从txt文件中读取图片URL,将URL放入一个数组中,然后将响应保存到文件中。

以下是我的代码:

  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "io"
  6. "io/ioutil"
  7. "net/http"
  8. "os"
  9. )
  10. func main() {
  11. fileName := "meinv.txt"
  12. file, _ := os.Open(fileName)
  13. picUrl := make([]string, 2000)
  14. reader := bufio.NewReader(file)
  15. for {
  16. line, _, err := reader.ReadLine()
  17. if err != io.EOF {
  18. fmt.Printf("文件加载:%s \n", line)
  19. picUrl = append(picUrl, string(line))
  20. } else {
  21. file.Close()
  22. break
  23. }
  24. }
  25. fmt.Printf("文件加载完成,准备下载 \n")
  26. fetchPic(picUrl)
  27. }
  28. func fetchPic(picUrl []string) {
  29. var file string
  30. for key, value := range picUrl {
  31. fmt.Printf("键:%d,行:%s \n\n", key, value)
  32. httpRequest, err := http.Get(string(value))
  33. fmt.Print("加载完成 \n")
  34. httpRequest.Body.Close()
  35. result, readErr := ioutil.ReadAll(httpRequest.Body)
  36. if readErr == nil {
  37. file = "pics/" + string(key) + ".jpg"
  38. ioutil.WriteFile(file, result, 0777)
  39. fmt.Print("写入完成 \n")
  40. }
  41. length := len(string(result))
  42. fmt.Printf("长度:%d", length)
  43. if err == nil {
  44. httpRequest = nil
  45. } else {
  46. fmt.Print("加载失败!!!!!! \n")
  47. }
  48. defer httpRequest.Body.Close()
  49. }
  50. }

运行代码后,我得到了以下错误:

  1. 键:0,行:
  2. 加载完成
  3. panic: runtime error: invalid memory address or nil pointer dereference
  4. [signal 0xb code=0x1 addr=0x40 pc=0x40123f]
  5. goroutine 1 [running]:
  6. runtime.panic(0x5f8300, 0x877688)
  7. /usr/local/go/src/pkg/runtime/panic.c:266 +0xb6
  8. main.fetchPic(0xc21239d000, 0x38be7, 0x4223c)
  9. /home/lyn/www/goOnDev/fetch.go:40 +0x24f
  10. main.main()
  11. /home/lyn/www/goOnDev/fetch.go:28 +0x1b8
  12. exit status 2

meinv.txt中,每行一个URL。有人可以帮忙吗?谢谢。

英文:

I just start to learn Go lang,I wrote a small demo,read picture urls from txt,put urls in an array,then Save the Response into a file.

Here is my code

  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "io"
  6. "io/ioutil"
  7. "net/http"
  8. "os"
  9. )
  10. func main() {
  11. fileName := "meinv.txt"
  12. file, _ := os.Open(fileName)
  13. picUrl := make([]string, 2000)
  14. reader := bufio.NewReader(file)
  15. for {
  16. line, _, err := reader.ReadLine()
  17. if err != io.EOF {
  18. fmt.Printf("file load %s \n", line)
  19. picUrl = append(picUrl, string(line))
  20. } else {
  21. file.Close()
  22. break
  23. }
  24. }
  25. fmt.Printf("file loaded,read to download \n")
  26. fetchPic(picUrl)
  27. }
  28. func fetchPic(picUrl []string) {
  29. var file string
  30. for key, value := range picUrl {
  31. fmt.Printf("key is : %d,this line is %s \n\n", key, value)
  32. httpRequest, err := http.Get(string(value))
  33. fmt.Print("load ok \n")
  34. httpRequest.Body.Close()
  35. result, readErr := ioutil.ReadAll(httpRequest.Body)
  36. if readErr == nil {
  37. file = "pics/" + string(key) + ".jpg"
  38. ioutil.WriteFile(file, result, 0777)
  39. fmt.Print("Write ok \n")
  40. }
  41. len := len(string(result))
  42. fmt.Printf("length is %d", len)
  43. if err == nil {
  44. httpRequest = nil
  45. //result = nil
  46. } else {
  47. fmt.Print("load falt!!!!!!!!! \n")
  48. }
  49. defer httpRequest.Body.Close()
  50. }
  51. }

run it ,and I got

  1. key is : 0,this line is
  2. load ok
  3. panic: runtime error: invalid memory address or nil pointer dereference
  4. [signal 0xb code=0x1 addr=0x40 pc=0x40123f]
  5. goroutine 1 [running]:
  6. runtime.panic(0x5f8300, 0x877688)
  7. /usr/local/go/src/pkg/runtime/panic.c:266 +0xb6
  8. main.fetchPic(0xc21239d000, 0x38be7, 0x4223c)
  9. /home/lyn/www/goOnDev/fetch.go:40 +0x24f
  10. main.main()
  11. /home/lyn/www/goOnDev/fetch.go:28 +0x1b8
  12. exit status 2

meinv.txt ,one line per url
Anyone help?THKS

答案1

得分: 6

在执行httpRequest, err := http.Get(string(value))之后,你正在从httpRequest.Body中无条件地读取,而没有检查err:如果http.Get失败,你将无法从httpRequest.Body中读取有效数据。

经验法则:立即检查每一个错误。

英文:

You are reading unconditional from httpRequest.Body after doing httpRequest, err := http.Get(string(value)) without checking err: If http.Get fails you won't have a valid httpRequest.Body to read from.

Rule of thumb: Check each and every error immediately.

答案2

得分: 2

这对我来说似乎工作得很好

  1. func main() {
  2. randomURLs := []string{"http://i.imgur.com/I7Rak2y.jpg", "http://i.imgur.com/XuM8GCN.jpg"}
  3. fetchPic(randomURLs)
  4. }
  5. func fetchPic(picUrl []string) {
  6. var file string
  7. for key, value := range picUrl {
  8. fmt.Printf("key is : %d,this line is %s \n\n", key, value)
  9. httpRequest, err := http.Get(string(value))
  10. fmt.Print("load ok \n")
  11. defer httpRequest.Body.Close()
  12. result, readErr := ioutil.ReadAll(httpRequest.Body)
  13. if readErr == nil {
  14. file = "pics/" + string(key) + ".jpg"
  15. ioutil.WriteFile(file, result, 0777)
  16. fmt.Print("Write ok \n")
  17. }
  18. len := len(string(result))
  19. fmt.Printf("length is %d", len)
  20. if err == nil {
  21. httpRequest = nil
  22. //result = nil
  23. } else {
  24. fmt.Print("load falt!!!!!!!!! \n")
  25. }
  26. }
  27. }

上述代码输出以下结果:

  1. 正在运行...
  2. key is : 0,this line is http://i.imgur.com/I7Rak2y.jpg
  3. load ok
  4. Write ok
  5. length is 445661key is : 1,this line is http://i.imgur.com/XuM8GCN.jpg
  6. load ok
  7. Write ok
  8. length is 746031
  9. 成功:进程以代码 0 退出。
英文:

This seems to be working fine for me

  1. func main() {
  2. randomURLs := []string{"http://i.imgur.com/I7Rak2y.jpg", "http://i.imgur.com/XuM8GCN.jpg"}
  3. fetchPic(randomURLs)
  4. }
  5. func fetchPic(picUrl []string) {
  6. var file string
  7. for key, value := range picUrl {
  8. fmt.Printf("key is : %d,this line is %s \n\n", key, value)
  9. httpRequest, err := http.Get(string(value))
  10. fmt.Print("load ok \n")
  11. defer httpRequest.Body.Close()
  12. result, readErr := ioutil.ReadAll(httpRequest.Body)
  13. if readErr == nil {
  14. file = "pics/" + string(key) + ".jpg"
  15. ioutil.WriteFile(file, result, 0777)
  16. fmt.Print("Write ok \n")
  17. }
  18. len := len(string(result))
  19. fmt.Printf("length is %d", len)
  20. if err == nil {
  21. httpRequest = nil
  22. //result = nil
  23. } else {
  24. fmt.Print("load falt!!!!!!!!! \n")
  25. }
  26. }
  27. }

The previous code output the following result:

  1. Running...
  2. key is : 0,this line is http://i.imgur.com/I7Rak2y.jpg
  3. load ok
  4. Write ok
  5. length is 445661key is : 1,this line is http://i.imgur.com/XuM8GCN.jpg
  6. load ok
  7. Write ok
  8. length is 746031
  9. Success: process exited with code 0.

答案3

得分: 0

我输入了这段代码并进行了测试,没有遇到任何问题。

  1. package main
  2. import (
  3. "os"
  4. "fmt"
  5. "bufio"
  6. "net/http"
  7. "io/ioutil"
  8. )
  9. func read_file(path string) ([]string, error) {
  10. file, err := os.Open(path)
  11. if err != nil {
  12. return nil, err
  13. }
  14. defer file.Close()
  15. var lines []string
  16. reader := bufio.NewScanner(file)
  17. for reader.Scan() {
  18. lines = append(lines, reader.Text())
  19. }
  20. return lines, reader.Err()
  21. }
  22. func main(){
  23. lines, err := read_file("./file.txt")
  24. if err != nil {
  25. fmt.Println(err)
  26. return
  27. }
  28. for key, value := range lines {
  29. fmt.Printf("key is : %d,this line is %s \n\n", key, value)
  30. httpRequest, err := http.Get(value)
  31. if err != nil {
  32. fmt.Println(err)
  33. return
  34. }
  35. defer httpRequest.Body.Close()
  36. result, readErr := ioutil.ReadAll(httpRequest.Body)
  37. if readErr != nil {
  38. fmt.Println(err)
  39. return
  40. }
  41. ioutil.WriteFile("./" + fmt.Sprintf("%d", key) + ".jpg", result, 0777)
  42. }
  43. }

答案

  1. key is : 0,this line is http://samsam.iteye.com/images/login_icon.png
  2. key is : 1,this line is http://www.iteye.com/images/logo-small.gif

Shell

  1. >>ls
  2. 0.jpg 1.jpg file.txt test.go
英文:

I type this code and test, I do not get any problem.

  1. package main
  2. import (
  3. "os"
  4. "fmt"
  5. "bufio"
  6. "net/http"
  7. "io/ioutil"
  8. )
  9. func read_file(path string) ([]string, error) {
  10. file, err := os.Open(path)
  11. if err != nil {
  12. return nil, err
  13. }
  14. defer file.Close()
  15. var lines []string
  16. reader := bufio.NewScanner(file)
  17. for reader.Scan() {
  18. lines = append(lines, reader.Text())
  19. }
  20. return lines, reader.Err()
  21. }
  22. func main(){
  23. lines, err := read_file("./file.txt")
  24. if err != nil {
  25. fmt.Println(err)
  26. return
  27. }
  28. for key, value := range lines {
  29. fmt.Printf("key is : %d,this line is %s \n\n", key, value)
  30. httpRequest, err := http.Get(value)
  31. if err != nil {
  32. fmt.Println(err)
  33. return
  34. }
  35. defer httpRequest.Body.Close()
  36. result, readErr := ioutil.ReadAll(httpRequest.Body)
  37. if readErr != nil {
  38. fmt.Println(err)
  39. return
  40. }
  41. ioutil.WriteFile("./" + fmt.Sprintf("%d", key) + ".jpg", result, 0777)
  42. }
  43. }

Answer

  1. key is : 0,this line is http://samsam.iteye.com/images/login_icon.png
  2. key is : 1,this line is http://www.iteye.com/images/logo-small.gif

Shell

  1. >>ls
  2. 0.jpg 1.jpg file.txt test.go

huangapple
  • 本文由 发表于 2014年1月10日 20:11:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/21044079.html
匿名

发表评论

匿名网友

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

确定