2011-08-04 12 views
3

googleアプリケーションエンジンのウェブサイトでpythonの代わりにgoを使用しようとしています。しかし、私はローカルでテストするときに私のスクリプトでこのエラーが発生し続けます。goでGoogle App Engineでローカルファイルを読む

panic: runtime error: invalid memory address or nil pointer dereference 

私は

channel <- buffer[0:dat] 

をコメントアウトした場合しかし、それはエラーなしで実行されます、かなり混乱しているので、私は、間違って任意のヘルプをチャネルを使用する必要がありますか?

編集:

これは、作業コードで、私はこの1つを得るための助けケビンバラードに多くの感謝。

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)ハンドラ内で同期的にではなく、(writeContentの前に 'go'を取り除いて)応答をgoroutineに書き込もうとしているため、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:]) 
}