Goroutines打破了程序

Arcticcu

问题是这样的:有一个Web服务器。我认为在页面加载中使用goroutines将是有益的,所以我继续进行:将loadPage函数作为goroutine。但是,这样做时,服务器只会停止运行而不会出现错误。它打印一张空白的白页。问题必须出在函数本身上—某种程度上与goroutine冲突。

这些是相关的功能:

func loadPage(w http.ResponseWriter, path string) {
   s := GetFileContent(path)
   w.Header().Add("Content-Type", getHeader(path))
   w.Header().Add("Content-Length", GetContentLength(path))
   fmt.Fprint(w, s)
}
func GetFileContent(path string) string {
   cont, err := ioutil.ReadFile(path)
   e(err)
   aob := len(cont)
   s := string(cont[:aob])
   return s
}


func GetFileContent(path string) string {
   cont, err := ioutil.ReadFile(path)
   e(err)
   aob := len(cont)
   s := string(cont[:aob])
   return s
}

func getHeader(path string) string {
   images := []string{".jpg", ".jpeg", ".gif", ".png"}
   readable := []string{".htm", ".html", ".php", ".asp", ".js", ".css"}
   if ArrayContainsSuffix(images, path) {
      return "image/jpeg"
   }
   if ArrayContainsSuffix(readable, path) {
      return "text/html"
   }
   return "file/downloadable"
}


func ArrayContainsSuffix(arr []string, c string) bool {
   length := len(arr)
   for i := 0; i < length; i++ {
      s := arr[i]
      if strings.HasSuffix(c, s) {
         return true
      }
   }
return false
}
路加

之所以出现这种情况的原因是因为你的HandlerFunc其称之为“loadPage”与请求同步调用。当您在go例程中调用它时,Handler实际上会立即返回,从而导致立即发送响应。这就是为什么您会得到空白页的原因。

您可以在server.go(第1096行)中看到以下内容

serverHandler{c.server}.ServeHTTP(w, w.req)
if c.hijacked() {
    return
}
w.finishRequest()

ServeHTTP函数调用您的处理程序,并在返回时立即调用“ finishRequest”。因此,您的Handler函数必须阻塞,只要它想满足请求即可。

使用go例程实际上不会使您的页面更快。正如Philip所建议的,将单个go例程与一个通道同步,在这种情况下也无济于事,因为这与完全没有go例程相同。

问题的根源实际上是ioutil.ReadFile,它将在发送之前将整个文件缓冲到内存中。

如果要流式传输文件,则需要使用os.Open您可以使用io.Copy将文件内容流式传输到浏览器,该浏览器将使用分块编码。

看起来像这样:

f, err := os.Open(path)
if err != nil {
    http.Error(w, "Not Found", http.StatusNotFound)
    return
}
n, err := io.Copy(w, f)
if n == 0 && err != nil {
    http.Error(w, "Error", http.StatusInternalServerError)
    return
}

如果由于某种原因您需要在多个go例程中进行工作,请查看sync.WaitGroup频道也可以。

如果您只想提供文件,则还有其他为此目的而优化的选项,例如FileServerServeFile

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章