2011-08-04 83 views
3

我正嘗試在Google應用引擎上使用go而不是python作爲我的網站。但是當我在本地測試時,我一直在用腳本收到這個錯誤。使用Go在Google App Engine中讀取本地文件

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

我很困惑,但它將運行沒有錯誤,如果我註釋掉

channel <- buffer[0:dat] 

所以我必須使用正確的通道,任何幫助嗎?

編輯:

這是工作的代碼,非常感謝凱文·巴拉德幫助我獲得這一個。

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(字節)? (感謝幫助btw) – seveibar

回答

5

之所以你的程序有時恐慌的是,它有時寫w http.ResponseWriter程序退出load功能之後。當程序退出處理函數時,http程序包會自動關閉http.ResponseWriter。在函數writeContent中,程序有時會嘗試寫入已關閉的http.ResponseWriter

順便說一句:如果你使用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:]) 
} 
相關問題