2011-08-04 5 views
3

J'essaie d'utiliser go au lieu de python pour mon site Web sur google app engine. Mais je continue d'obtenir cette erreur avec mon script lorsque je teste en local.Lire un fichier local dans Google App Engine avec Go

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

Je suis assez confus, mais il fonctionnera sans erreur si je commente sur

channel <- buffer[0:dat] 

donc je dois être en utilisant des canaux de manière incorrecte, toute aide?

Edit:

Ceci est le code de travail, un grand merci à Kevin Ballard pour me avoir aidé celui-ci.

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

La panique devrait vous donner un backtrace. Sur quelle ligne panique-t-on? –

+1

J'ai essayé d'exécuter votre code localement et il n'a pas paniqué. Certes, cela ne fonctionnait pas non plus, mais c'est parce que a) vous essayez d'écrire la réponse dans un goroutine au lieu de la synchroniser dans le gestionnaire (il suffit de se débarrasser du 'go' avant le' writeContent') et b) vous écrivez des octets individuels sous forme de nombres au lieu d'écrire les octets comme, bien, octets (changez 'writeContent' pour simplement utiliser' w.Write (bytes) '). Certes, même avec cela, vous aurez des problèmes de thread parce que vous réutilisez le tampon que vous envoyez à l'autre canal. –

+0

Voulez-vous dire change fmt.Fprint à w.Write (bytes)? (Merci pour l'aide btw) – seveibar

Répondre

5

La raison pour laquelle votre programme panique parfois est qu'il est en train d'écrire parfois w http.ResponseWriter après le programme quitte la fonction load. Le package http ferme automatiquement le http.ResponseWriter lorsque le programme quitte la fonction de gestionnaire. Dans la fonction writeContent, le programme essaie parfois d'écrire dans un http.ResponseWriter fermé. BTW: Vous pouvez réduire le code source du programme si vous utilisez la fonction io.Copy.

Pour obtenir toujours un comportement prévisible, assurez-vous que tous les travaux que vous voulez que le programme à exécuter en réponse à une requête HTTP est fait avant de quitter la fonction de gestionnaire. Par exemple:

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:]) 
} 
Questions connexes