Goroutines 破坏了程序

问题是:有一个网络服务器。我认为在页面加载中使用 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

}


慕慕森
浏览 181回答 2
2回答

呼如林

之所以出现这种情况的原因是因为你的HandlerFunc其称之为“loadPage”与请求同步调用。当您在 go 例程中调用它时,处理程序实际上是立即返回,从而立即发送响应。这就是为什么你会得到一个空白页。您可以在server.go 中看到这一点(第 1096 行):serverHandler{c.server}.ServeHTTP(w, w.req)if c.hijacked() {&nbsp; &nbsp; return}w.finishRequest()该ServeHTTP函数调用您的处理程序,并在返回后立即调用“finishRequest”。因此,只要您的 Handler 函数想要满足请求,它就必须阻塞。使用 go 例程实际上不会使您的页面更快。正如 Philip 建议的那样,将单个 go 例程与通道同步,在这种情况下也无济于事,因为这与根本没有 go 例程相同。您的问题的根源实际上是ioutil.ReadFile,它在发送之前将整个文件缓冲到内存中。如果要流式传输文件,则需要使用os.Open. 您可以使用io.Copy将文件内容流式传输到浏览器,浏览器将使用分块编码。这看起来像这样:f, err := os.Open(path)if err != nil {&nbsp; &nbsp; http.Error(w, "Not Found", http.StatusNotFound)&nbsp; &nbsp; return}n, err := io.Copy(w, f)if n == 0 && err != nil {&nbsp; &nbsp; http.Error(w, "Error", http.StatusInternalServerError)&nbsp; &nbsp; return}如果由于某种原因您需要在多个 go 例程中工作,请查看sync.WaitGroup. 渠道也可以工作。如果您只想提供一个文件,则还有其他为此进行了优化的选项,例如FileServer或ServeFile。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go