【问题标题】:How to run html on a Go server如何在 Go 服务器上运行 html
【发布时间】:2015-09-20 14:52:44
【问题描述】:

我在 Go 中创建了一个服务器,并尝试在浏览器中运行一个 html 文件。但是浏览器只是像 txt 文件一样打印出代码,而不是呈现 html 格式。我的 index.html 文件保存在 /public 目录中。

我的 go 代码如下所示:

package main

import (
    "net/http"
    "io/ioutil"
)

func main() {
    http.Handle("/", new(MyHandler))

    http.ListenAndServe(":8000", nil)
}

type MyHandler struct {
    http.Handler
}

func (this *MyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    path := "public/" + req.URL.Path
    data, err := ioutil.ReadFile(string(path))

    if err == nil {
        w.Write(data)
    } else {
        w.WriteHeader(404)
        w.Write([]byte("404 - " + http.StatusText(404)))
    }

}

【问题讨论】:

  • 请在此行之后显示您希望data 保持的值; data, err := ioutil.ReadFile(string(path)).
  • 您几乎没有发送任何标头(只有 http 包添加的绝对最小值)。这是不好的。如果您希望您的浏览器处理您作为 HTML 发送的数据,您应该告诉他:将 Content-Type 标头设置为例如“文本/html”。

标签: html go server


【解决方案1】:

从启动和运行 HTML 开始。然后,构建您的 HTTP 错误处理(例如 404)。我建议从一开始就使用text/template,即使您还没有为您的应用程序添加任何活力......但是!

package main

import (
    "io/ioutil"
    "log"
    "net/http"
    "text/template"
)

func main() {
    http.HandleFunc("/", RootHandler)

    if err := http.ListenAndServe(":8080", nil); err != nil {
        log.Fatal(err)
    }
}

func RootHandler(res http.ResponseWriter, req *http.Request) {
    file, _ := ioutil.ReadFile("public/index.html")
    t := template.New("")
    t, _ = t.Parse(string(file))

    t.Execute(res, nil)
}

【讨论】:

    【解决方案2】:

    如果您想推迟使用 text/template 包并直接提供 HTML,只需阅读您的 index.html 文件并将其写入响应编写器(例如,res 在我的示例中用于响应,但是很多人也使用w 作为作家)。

    package main
    
    import (
        "io/ioutil"
        "log"
        "net/http"
    )
    
    func main() {
        http.HandleFunc("/", RootHandler)
    
        if err := http.ListenAndServe(":8080", nil); err != nil {
            log.Fatal(err)
        }
    }
    
    func RootHandler(res http.ResponseWriter, req *http.Request) {
        file, _ := ioutil.ReadFile("public/index.html")
        res.Write(file)
    }
    

    【讨论】:

      【解决方案3】:

      现在您只是读取文件的内容并将其写出。由于 Go 无法告诉 什么 文件是什么类型的文件,所以它无法设置标题。

      谢天谢地,有一个有用的 http.ServeFile 函数 in the net/http package 可以帮助您。

      func (this *MyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
          path := "public/" + req.URL.Path
          http.ServeFile(w, r, filepath.Join("path/to/file", path))
      }
      

      http.ServeFile 尝试根据文件扩展名或前几个字节设置Content-Type(对于 HTML 文件,它应该正确设置)。

      更好的解决方案是将您的路由处理程序设为http.FileServer

      func main() {
          http.Handle("/", http.FileServer(http.Dir("./public"))
      
          http.ListenAndServe(":8000", nil)
      }
      

      查看examples in the Go docs,了解如何以其他方式使用它。

      无耻插件:我编写了一个小型中间件库,它使在 Go 中提供静态文件变得更容易一些,您可能会发现它在其中使用(或阅读代码以获得洞察力):https://github.com/elithrar/station

      【讨论】:

        【解决方案4】:

        在您的主要尝试中使用http.HandleFunc("/", ServeHTTP) 然后编辑ServeHTTP 方法,使其没有接收者,即; func ServeHTTP(w http.ResponseWriter, req *http.Request)

        您尝试使用该对象,Handle 方法也可以正常工作(如果实施正确),但大多数示例使用 HandleFunc,如果您这样做,我敢打赌您的问题会消失。

        唯一会导致您观察到的问题的另一件事是无法读取内容分配给data 的文件,或者对该文件中的数据实际存在一些误解。

        【讨论】:

        • MyHandler 上的ServeHTTP 方法允许它满足http.Handler 并因此与http.Handler 一起工作(它需要接口)——尽管您可能知道这一点。不过,调用处理程序绝对是一种笨拙的方式:回退到写http.HandleFunc("/", MyHandler) 更好。 ServeHTTP 真的应该只用作方法。
        猜你喜欢
        • 1970-01-01
        • 2020-04-28
        • 2018-04-11
        • 1970-01-01
        • 2022-12-18
        • 1970-01-01
        • 2018-04-23
        • 2018-07-21
        • 2016-11-12
        相关资源
        最近更新 更多