构建 Golang Web 应用的两种方法
对前后端分离的 web 项目,golang 后端可以以两种方式提供前端静态文件的访问:
- 使用 
http.FileServer提供静态文件服务 - 使用 
go-bindata-assetfs将前端静态文件打包成二进制数据,和后端构建到一起 
一、http.FileServer 提供静态文件服务
文件目录:
go-web-prj/
        static/
                index.html
        main.go
index.html :
<!doctype html>
<html>
  <body>
    <p>Hello World!</p>
  </body>
</html>
main.go
package main
import (
    "log"
    "net/http"
)
func main() {
    // Create a fileServer handler that serves our static files.
    fileServer := http.FileServer(http.Dir("static/"))
    http.HandleFunc(
        "/",
        func(w http.ResponseWriter, r *http.Request) {
            fileServer.ServeHTTP(w, r)
        },
    )
    log.Fatal(http.ListenAndServe(":8080", nil))
}
此时使用 go run  或  go build 将后端代码运行、构建,便可以在浏览器打开 [localhost:8080](http://localhost:8080) 访问。
不过,这种打包形式有一个缺点,就是必须保证 static/  目录的路径正确,如果修改或者不存在了,前端文件就不可以正常渲染。
使用 go-bindata-assetfs 打包前端静态文件可以解决这个问题。
二、使用 go-bindata-assetfs 打包前端文件
使用前先安装:
$ go get github.com/go-bindata/go-bindata/...
$ go get github.com/elazarl/go-bindata-assetfs/...
将前端文件打包:
$ go-bindata-assetfs static/...
生成 bindata_assetfs.go 文件
修改 main.go 代码:
package main
import (
    "log"
    "net/http"
)
func main() {
    // Create a fileServer handler that serves our static files.
    http.Handle("/", http.FileServer(assetFS()))
    log.Fatal(http.ListenAndServe(":8080", nil))
}
使用 go mod 方便接下来构建:
go mod init go-web-prj
构建:
go build main.go bin bindata_assetfs.go
然后运行生成的 main 文件,即可在浏览器打开 [localhost:8080](http://localhost:8080) 访问。
此时 static/ 文件已打包进二进制文件,所以当前的 static/ 修改甚至删除,都不影响网站的正常使用。
使用 Docker 部署
如果是打包好的二进制文件,使用 docker 部署十分简单, Dockerfille :
FROM scratch
ADD main /
CMD ["/main"]
然后构建:
dk build -t go-web-prj .
运行:
dk run -p 8080:8080 web-test
如果出现:
standard_init_linux.go:211: exec user process caused "exec format error"
之类的错误,那是因为二进制文件编译环境出错,对于 linux 的 docker 环境,通常要设置环境变量:
env GOOS=linux GOARCH=arm64
更多的 go 编译环境参考:Golang GOOS and GOARCH