在Google App Engine中使用Go语言读取本地文件

huangapple go评论74阅读模式
英文:

Reading a local file in Google App Engine with Go

问题

我正在尝试在Google App Engine上使用Go而不是Python来构建我的网站。但是当我在本地测试我的脚本时,我一直遇到这个错误。

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

我很困惑,但是如果我注释掉以下代码,它将可以正常运行。

channel <- buffer[0:dat]

所以我可能在使用通道时出错了,有人可以帮忙吗?

编辑:

这是可工作的代码,非常感谢Kevin Ballard帮助我解决了这个问题。

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)
}
英文:

I'm trying to use go instead of python for my website on google app engine. But I keep getting this error with my script when I test locally.

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

I'm pretty confused, however it will run without error if I comment out

channel &lt;- buffer[0:dat]

So I must be using channels incorrectly, Any help?

Edit:

This is the working code, many thanks to Kevin Ballard for helping me get this one.

package defp

import (
    &quot;fmt&quot;
    &quot;http&quot;
    &quot;os&quot;
)

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

答案1

得分: 5

你的程序有时会发生恐慌的原因是,在程序退出load函数后,有时会写入w http.ResponseWriter。http包在程序退出处理程序函数时会自动关闭http.ResponseWriter。在writeContent函数中,程序有时会尝试向已关闭的http.ResponseWriter写入。

顺便说一下:如果使用io.Copy函数,可以使程序源代码更小。

为了始终获得可预测的行为,请确保您希望程序在HTTP请求响应中执行的所有工作都在退出处理程序函数之前完成。例如:

func writeContent(w http.ResponseWriter, channel chan []byte) {
    fmt.Printf("尝试写入内容\n")
    for bytes := range channel {
            w.Write(bytes)
            fmt.Printf("接收到字节\n")
    }
    fmt.Printf("写入完成\n")
}

func load(w http.ResponseWriter, path string) {
    fmt.Printf("尝试加载 " + path + "\n")
    channel := make(chan []byte)
    workDone := make(chan byte)
    go func() {
            writeContent(w, channel)
            workDone <- 1 //发送任意值
    }()
    go func() {
            getContent(path, channel)
            workDone <- 2 //发送任意值
    }()
    <-workDone
    <-workDone
}

func handle(w http.ResponseWriter, r *http.Request) {
    fmt.Printf("处理请求 " + r.URL.Path[1:] + "\n")
    load(w, r.URL.Path[1:])
}
英文:

The reason why your program sometimes panics is that it is sometimes writing to <code>w http.ResponseWriter</code> after the program exits the <code>load</code> function. The <code>http</code> package automatically closes the <code>http.ResponseWriter</code> when the program exits the handler function. In function <code>writeContent</code>, the program will sometimes attempt to write to a closed <code>http.ResponseWriter</code>.

BTW: You can make the program source code much smaller if you use the <code>io.Copy</code> function.

To always get predictable behavior, make sure that all work that you want the program to perform in response to a HTTP request is done before you exit the handler function. For example:

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

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

func handle(w http.ResponseWriter, r *http.Request) {
    fmt.Printf(&quot;HANDLING REQUEST FOR &quot; + r.URL.Path[1:] + &quot;\n&quot;)
    load(w, r.URL.Path[1:])
}

huangapple
  • 本文由 发表于 2011年8月5日 07:41:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/6949899.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定