43

我实际上是在尝试浏览一个包含 html 文件的文件夹。我想将它们嵌入到二进制文件中,并能够根据请求解析它们以用于模板执行目的。(如果我的措辞不正确,请原谅)。

非常感谢任何想法、提示、技巧或更好的方法来实现这一点。

// Template Files
type TempFiles struct {
    Files map[string]string
}

// Loop through view files and load them
func LoadTempFiles() {
    t := new(TempFiles)

    // Load template files
    filepath.Walk("application/views", func(path string, info os.FileInfo, err error) error {
    if !info.IsDir() {
        content, _ := ioutil.ReadFile(path)
        t.Files[path] = string(content)
    }
    return nil
    })
}

func ViewTemp(w http.ResponseWriter, path string) {
    t := new(TempFiles)

    temp, err := template.New().Parse(t.Files[path])
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    } else {
        temp.Execute(w, nil)
    }
}
4

4 回答 4

48

我使用我的大多数 Go 网络应用程序来执行此操作。我使用go-bindata从我想要嵌入的所有文件中自动生成 Go 源代码,然后将它们编译成二进制文件。所有这些都是在构建期间自动完成的。

一个缺点是当前的 go 构建工具不提供挂钩到构建过程的方法,因此我为此使用了 Makefile。调用 makefile 时,它​​会运行go-bindata以生成所有必要文件的源代码,然后通常会执行一些额外的代码生成位和 bobs(特别是创建一个 Go 源文件,其中列出了地图中的所有嵌入文件.. 目录如果你愿意)。然后它继续编译实际程序。

这可能会变得有点混乱,但您只需设置一次。另一个缺点是使用 Makefile 意味着软件与go get命令不兼容。但是由于我的大多数网络应用程序无论如何都不是要共享的,所以到目前为止这还不是问题。

在调试/开发这样的应用程序时,嵌入静态 Web 内容会产生另一个问题:我不能只编辑 HTML 或 CSS 文件并刷新浏览器以查看其效果。我将不得不停止服务器,重建它并在每次编辑时重新启动它。这显然不理想,所以我将 Makefile 拆分为debugandrelease模式。释放模式执行我上面描述的操作。但是,调试模式实际上不会嵌入静态文件。它确实为每个文件生成源文件,但不是让它们包含实际的文件数据,而是包含一个简单地从文件系统加载数据的存根。

就服务器代码而言,生成的代码没有区别。它所做的只是调用一个函数来获取给定静态文件的内容。它不关心该内容是否实际嵌入二进制文件中,或者是否从外部源加载。所以这两种构建模式可以自由互换。

例如,在发布和调试模式下获取静态文件内容的相同生成函数如下所示:

发布方式:

func index_html() []byte {
    return []byte {
        ....
    }
}

调试模式:

func index_html() []byte {
   data, err := ioutil.ReadFile("index.html")
   ...
   return data
}

两种情况下的界​​面是相同的。这允许轻松和无忧的开发和调试。

于 2012-09-18T18:52:16.347 回答
18

另一个需要考虑的工具:另一个最近的好工具来自esc:Embedding Static Assets in Go ( GitHub repo )

一个程序:

  • 可以获取一些目录并以与 http.FileSystem 兼容的方式递归地将所有文件嵌入其中
  • 可以选择禁用以与本地文件系统一起使用以进行本地开发
  • 不会在后续运行中更改输出文件
  • 文件更改时有合理大小的差异
  • 对销售友好

供应商友好意味着当我跑步godep或聚会时,静态嵌入文件不会改变。
这意味着它不能有任何第三方导入(因为它们的导入路径将在 期间被重写goimports,因此与工具本身生成的不同),或所需第三方导入的可指定位置。

它生成漂亮的 gzip 压缩字符串,每个文件一个。
有一个简单的标志来启用本地开发模式,它足够聪明,不会从文件名中去除目录前缀(esc有时需要一个选项)。
输出包括所有需要的代码,并且不依赖于任何第三方库来兼容http.FileSystem.

于 2014-11-20T07:49:18.043 回答
8

我制作了一个包,使调试和生产之间的切换更容易。它还提供了一个 http.FileSystem 实现,可以轻松地为文件提供服务。它有几种将文件添加到二进制文件的方法(生成 go 代码,或附加为 zip)。 https://github.com/GeertJohan/go.rice

于 2014-03-20T17:51:04.410 回答
1

Go 现在已经内置了对此的支持:

package main

import (
   "embed"
   "os"
)

//go:embed *.html
var content embed.FS

func main() {
   b, e := content.ReadFile("index.html")
   if e != nil {
      panic(e)
   }
   os.Stdout.Write(b)
}

https://golang.org/pkg/embed

于 2021-04-01T20:16:47.863 回答