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

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

Reading a local file in Google App Engine with Go

问题

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

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

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

  1. channel <- buffer[0:dat]

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

编辑:

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

  1. package defp
  2. import (
  3. "fmt"
  4. "http"
  5. "os"
  6. )
  7. func getContent(filename string, channel chan []byte) {
  8. file, err := os.OpenFile(filename, os.O_RDONLY, 0666)
  9. defer file.Close()
  10. if err == nil {
  11. fmt.Printf("FILE FOUND : " + filename + " \n")
  12. buffer := make([]byte, 16)
  13. dat, err := file.Read(buffer)
  14. for err == nil {
  15. fmt.Printf("herp")
  16. channel <- buffer[0:dat]
  17. buffer = make([]byte, 16)
  18. dat, err = file.Read(buffer)
  19. }
  20. close(channel)
  21. fmt.Printf("DONE READING\n")
  22. } else {
  23. fmt.Printf("FILE NOT FOUND : " + filename + " \n")
  24. }
  25. }
  26. func writeContent(w http.ResponseWriter, channel chan []byte) {
  27. fmt.Printf("ATTEMPTING TO WRITE CONTENT\n")
  28. go func() {
  29. for bytes := range channel {
  30. w.Write(bytes)
  31. fmt.Printf("BYTES RECEIVED\n")
  32. }
  33. }()
  34. fmt.Printf("FINISHED WRITING\n")
  35. }
  36. func load(w http.ResponseWriter, path string) {
  37. fmt.Printf("ATTEMPTING LOAD " + path + "\n")
  38. channel := make(chan []byte, 50)
  39. writeContent(w, channel)
  40. getContent(path, channel)
  41. }
  42. func handle(w http.ResponseWriter, r *http.Request) {
  43. fmt.Printf("HANDLING REQUEST FOR " + r.URL.Path[1:] + "\n")
  44. load(w, r.URL.Path[1:])
  45. }
  46. func init() {
  47. http.HandleFunc("/", handle)
  48. }
英文:

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.

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

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

  1. 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.

  1. package defp
  2. import (
  3. &quot;fmt&quot;
  4. &quot;http&quot;
  5. &quot;os&quot;
  6. )
  7. func getContent(filename string, channel chan []byte) {
  8. file, err := os.OpenFile(filename, os.O_RDONLY, 0666)
  9. defer file.Close()
  10. if err == nil {
  11. fmt.Printf(&quot;FILE FOUND : &quot; + filename + &quot; \n&quot;)
  12. buffer := make([]byte, 16)
  13. dat, err := file.Read(buffer)
  14. for err == nil {
  15. fmt.Printf(&quot;herp&quot;)
  16. channel &lt;- buffer[0:dat]
  17. buffer = make([]byte, 16)
  18. dat, err = file.Read(buffer)
  19. }
  20. close(channel)
  21. fmt.Printf(&quot;DONE READING\n&quot;)
  22. } else {
  23. fmt.Printf(&quot;FILE NOT FOUND : &quot; + filename + &quot; \n&quot;)
  24. }
  25. }
  26. func writeContent(w http.ResponseWriter, channel chan []byte) {
  27. fmt.Printf(&quot;ATTEMPTING TO WRITE CONTENT\n&quot;)
  28. go func() {
  29. for bytes := range channel {
  30. w.Write(bytes)
  31. fmt.Printf(&quot;BYTES RECEIVED\n&quot;)
  32. }
  33. }()
  34. fmt.Printf(&quot;FINISHED WRITING\n&quot;)
  35. }
  36. func load(w http.ResponseWriter, path string) {
  37. fmt.Printf(&quot;ATTEMPTING LOAD &quot; + path + &quot;\n&quot;)
  38. channel := make(chan []byte, 50)
  39. writeContent(w, channel)
  40. getContent(path, channel)
  41. }
  42. func handle(w http.ResponseWriter, r *http.Request) {
  43. fmt.Printf(&quot;HANDLING REQUEST FOR &quot; + r.URL.Path[1:] + &quot;\n&quot;)
  44. load(w, r.URL.Path[1:])
  45. }
  46. func init() {
  47. http.HandleFunc(&quot;/&quot;, handle)
  48. }

答案1

得分: 5

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

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

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

  1. func writeContent(w http.ResponseWriter, channel chan []byte) {
  2. fmt.Printf("尝试写入内容\n")
  3. for bytes := range channel {
  4. w.Write(bytes)
  5. fmt.Printf("接收到字节\n")
  6. }
  7. fmt.Printf("写入完成\n")
  8. }
  9. func load(w http.ResponseWriter, path string) {
  10. fmt.Printf("尝试加载 " + path + "\n")
  11. channel := make(chan []byte)
  12. workDone := make(chan byte)
  13. go func() {
  14. writeContent(w, channel)
  15. workDone <- 1 //发送任意值
  16. }()
  17. go func() {
  18. getContent(path, channel)
  19. workDone <- 2 //发送任意值
  20. }()
  21. <-workDone
  22. <-workDone
  23. }
  24. func handle(w http.ResponseWriter, r *http.Request) {
  25. fmt.Printf("处理请求 " + r.URL.Path[1:] + "\n")
  26. load(w, r.URL.Path[1:])
  27. }
英文:

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:

  1. func writeContent(w http.ResponseWriter, channel chan []byte) {
  2. fmt.Printf(&quot;ATTEMPTING TO WRITE CONTENT\n&quot;)
  3. for bytes := range channel {
  4. w.Write(bytes)
  5. fmt.Printf(&quot;BYTES RECEIVED\n&quot;)
  6. }
  7. fmt.Printf(&quot;FINISHED WRITING\n&quot;)
  8. }
  9. func load(w http.ResponseWriter, path string) {
  10. fmt.Printf(&quot;ATTEMPTING LOAD &quot; + path + &quot;\n&quot;)
  11. channel := make(chan []byte)
  12. workDone := make(chan byte)
  13. go func() {
  14. writeContent(w, channel)
  15. workDone &lt;- 1 //Send an arbitrary value
  16. }()
  17. go func() {
  18. getContent(path, channel)
  19. workDone &lt;- 2 //Send an arbitrary value
  20. }()
  21. &lt;-workDone
  22. &lt;-workDone
  23. }
  24. func handle(w http.ResponseWriter, r *http.Request) {
  25. fmt.Printf(&quot;HANDLING REQUEST FOR &quot; + r.URL.Path[1:] + &quot;\n&quot;)
  26. load(w, r.URL.Path[1:])
  27. }

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:

确定