2014-11-04 3 views
2

간단한 웹 크롤러를 만들려고 시도하는 것이 처음입니다. 계속 "공황 : 런타임 오류 : 유효하지 않은 메모리 주소 또는 nil 포인터 참조 해제"가 발생하고 문제를 해결하는 방법을 모릅니다. 나는 "advancedFetcher"함수와 "basicFetcher"함수를 가지고 있는데, 둘 중 하나에서 같은 오류가 발생한다. This answer은 각 오류 (내가 생각하기에있는)를 확인하지만 여전히 오류가 발생한다고 제안합니다. 감사!런타임 오류 : 잘못된 메모리 주소 또는 nil 포인터 참조 취소

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") 
} 

수정 # 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

패닉이 발생하기 전에 프로그램이 오류를 인쇄합니까? 메모리가 작동하면'http.Get'가 에러를 반환하면'resp.Body'는'nil'으로 에러를 일으킬 것입니다. –

+0

@JimmySawczuk : 편집 # 1과 같은 의미입니까? 그렇다면 여전히 동일한 오류가 발생합니다. –

+2

어떤 라인이 공포를 던지고 있습니까? –

답변

3

당황하기 전에 오류를 인쇄하는 프로그램인가? 메모리가있는 경우 http.Get이 오류를 반환하면 resp.Body == nil이 표시되어 nilresp.Body.Close()을 호출 할 수 없으므로 오류가 발생할 수 있습니다.

twotwotwo suggests으로 문제가 발생하기 전에 정상적으로 종료 할 수 있도록 (결과, 오류) 쌍을 반환하도록 함수를 작성해야합니다.

+0

와 newx를 돕기위한 thx! –

관련 문제