2011-08-04 3 views
3

google 앱 엔진에서 내 웹 사이트에 python 대신 go를 사용하려고합니다. 하지만 로컬에서 테스트 할 때 스크립트로이 오류가 계속 발생합니다. 내가 잘못 어떤 도움을 채널을 사용하고 있어야합니다 그래서go와 함께 Google App Engine에서 로컬 파일 읽기

channel <- buffer[0:dat] 

을 주석 경우

나는 꽤 혼란 스러워요
panic: runtime error: invalid memory address or nil pointer dereference 

그러나 오류없이 실행됩니다?

편집 :

이 날이 하나를 얻을 수 있도록 케빈 발라드로 작업 코드, 많은 감사입니다.

package defp 

import (
    "fmt" 
    "http" 
    "os" 
) 

func getContent(filename string, channel chan []byte) { 
    file, err := os.OpenFile(filename, os.O_RDONLY, 0666) 
    defer file.Close() 
    if err == nil { 
     fmt.Printf("FILE FOUND : " + filename + " \n") 
     buffer := make([]byte, 16) 
     dat, err := file.Read(buffer) 
     for err == nil { 
      fmt.Printf("herp") 
      channel <- buffer[0:dat] 
      buffer = make([]byte, 16) 
      dat, err = file.Read(buffer) 
     } 
     close(channel) 
     fmt.Printf("DONE READING\n") 
    } else { 
     fmt.Printf("FILE NOT FOUND : " + filename + " \n") 
    } 
} 
func writeContent(w http.ResponseWriter, channel chan []byte) { 
    fmt.Printf("ATTEMPTING TO WRITE CONTENT\n") 
    go func() { 
     for bytes := range channel { 
      w.Write(bytes) 
      fmt.Printf("BYTES RECEIVED\n") 
     } 
    }() 
    fmt.Printf("FINISHED WRITING\n") 
} 
func load(w http.ResponseWriter, path string) { 
    fmt.Printf("ATTEMPTING LOAD " + path + "\n") 
    channel := make(chan []byte, 50) 
    writeContent(w, channel) 
    getContent(path, channel) 
} 
func handle(w http.ResponseWriter, r *http.Request) { 
    fmt.Printf("HANDLING REQUEST FOR " + r.URL.Path[1:] + "\n") 
    load(w, r.URL.Path[1:]) 
} 
func init() { 
    http.HandleFunc("/", handle) 
} 
+1

패닉이 당신에게 역 추적을 제공해야합니다. 실제로 어떤 선이 당황하고 있습니까? –

+1

로컬에서 코드를 실행 해 보았는데 패닉이 발생하지 않았습니다. 물론, 실제로 작동하지는 않았지만, 그 이유는 a) 처리기 내에서 동 기적으로 대신 goroutine에 응답을 쓰려고하기 때문입니다 (단지 'writeContent'전에 'go'를 제거하십시오). b) 여러분은 바이트를 글쎄, 바이트로 쓰는 대신 개별 바이트를 숫자로 쓰고 있습니다 ('writeContent'를'w.Write (bytes) '로 바꾸기). 물론, 다른 채널로 보내고있는 버퍼를 재사용하기 때문에 스레드 문제가 발생할 수도 있습니다. –

+0

fmt.Fprint를 w.Write (bytes)로 변경하셨습니까? (도움 btw 주셔서 감사합니다) – seveibar

답변

5

프로그램이 가끔 패닉 이유는 프로그램이 load 기능을 종료 한 후 가끔 w http.ResponseWriter에 쓰기 작업을 수행하는 것입니다. http 패키지는 프로그램이 처리기 기능을 종료하면 http.ResponseWriter을 자동으로 닫습니다. 함수 writeContent에서 프로그램은 닫힌 http.ResponseWriter에 쓰기를 시도합니다.

BTW : io.Copy 기능을 사용하면 프로그램 소스 코드를 훨씬 더 작게 만들 수 있습니다.

은 항상 당신이 핸들러 함수를 종료하기 전에 프로그램이 HTTP 요청 에 대한 응답으로 수행 할 모든 작업이 완료되어 있는지 것을 확인, 예측 가능한 행동을 얻으려면. 예 :

func writeContent(w http.ResponseWriter, channel chan []byte) { 
    fmt.Printf("ATTEMPTING TO WRITE CONTENT\n") 
    for bytes := range channel { 
      w.Write(bytes) 
      fmt.Printf("BYTES RECEIVED\n") 
    } 
    fmt.Printf("FINISHED WRITING\n") 
} 

func load(w http.ResponseWriter, path string) { 
    fmt.Printf("ATTEMPTING LOAD " + path + "\n") 
    channel := make(chan []byte) 
    workDone := make(chan byte) 
    go func() { 
      writeContent(w, channel) 
      workDone <- 1 //Send an arbitrary value 
    }() 
    go func() { 
      getContent(path, channel) 
      workDone <- 2 //Send an arbitrary value 
    }() 
    <-workDone 
    <-workDone 
} 

func handle(w http.ResponseWriter, r *http.Request) { 
    fmt.Printf("HANDLING REQUEST FOR " + r.URL.Path[1:] + "\n") 
    load(w, r.URL.Path[1:]) 
} 
관련 문제