【问题标题】:How do you use Go 1.16 embed features in subfolders/packages?您如何在子文件夹/包中使用 Go 1.16 嵌入功能?
【发布时间】:2021-02-19 22:09:07
【问题描述】:

Go 1.16 已经发布,我想使用新的嵌入功能。如果一切都在主包中,我可以让它工作。但目前尚不清楚如何处理从子文件夹/包访问资源。尝试通过 embed.FS 支持来实现。

例如我在处理程序包/文件夹中有一个 main.go 和一个 HTTP 处理程序

如果我将处理程序放在 main 中,它可以工作。如果我把它放在处理程序包中,它就找不到模板。我明白了:

handlers/indexHandler.go:11:12: pattern templates: no matching files found exit status 1

同样,如果我从 / 提供图像,我可以让它从静态文件夹提供图像。但是我不能同时提供来自 / 的处理程序和来自 / 的静态/图像。如果我将图像放在 /static/ 上,它就找不到图像。

我认为这与相对路径有关。但是我无法通过反复试验找到正确的组合......现在依赖这些功能还为时过早吗?

以前我用的是go-rice,我没有遇到这些问题。但我想尽可能多地使用std库。

main.go:

package main

import (...)

//go:embed static
var static embed.FS

func main() {

    fsRoot, _ := fs.Sub(static, "static")
    fsStatic := http.FileServer(http.FS(fsRoot))
    http.Handle("/", fsStatic)
    http.HandleFunc("/index", Index)
    http.ListenAndServe(":8080", nil)
}

handlers/indexHandler.go:

package handlers

import (...)

//go:embed templates
var templates embed.FS

// Index handler
func Index(w http.ResponseWriter, r *http.Request) {

    tmpl := template.New("")
    var err error
    if tmpl, err = tmpl.ParseFS(templates, "simple.gohtml"); err != nil {
        fmt.Println(err)
    }
    if err = tmpl.ExecuteTemplate(w, "simple", nil); err != nil {
        log.Print(err)
    }    
}

结构如下...

.
├── go.mod
├── go.sum
├── handlers
│   └── indexHandler.go
├── main.go
├── static
│   ├── css
│   │   └── layout.css
│   └── images
│       └── logo.png
└── templates
    └── simple.gohtml

【问题讨论】:

  • 请添加您的目录结构的详细信息(您的simple.gohtml 在哪里)。参考您问题的第二部分 - 您可能需要StripPrefix(请参阅the example)。
  • 在进入静态文件夹并从路径中删除静态文件方面取得了一些进展。但仍然不能在同一个/上为 indexHandler 设置处理程序...
  • 抱歉 - 我不清楚您仍然遇到什么问题(可能显示更新的代码)。参考simple./html;除非您还将templates 移动到handlers/templates,否则您将需要使用//go:embed ../templatesembed path 是“相对于包含源文件的包目录”)。
  • 我也是这么想的。除了“..”是不允许的并且会产生错误。所以也许模板需要在包下......
  • 抱歉——您是对的(“模式不得包含‘.’或‘..’或空路径元素,也不能以斜杠开头或结尾”)。

标签: go go-http


【解决方案1】:

我终于明白了……

您可以将模板文件夹保留在主文件夹中并从那里嵌入它们。然后您需要将 FS 变量注入到另一个处理程序包中。弄明白后总是很容易的。

例如

package main

//go:embed templates/*
var templateFs embed.FS

func main() {
    handlers.TemplateFs = templateFs
...
package handlers

var TemplateFs embed.FS

func handlerIndex() {
    ...
    tmpl, err = tmpl.ParseFS(TemplateFs, "templates/layout.gohtml",...
...

【讨论】:

  • 感谢您的解决方案。不能使用相对路径,这很烦人。
  • @Jørgen 这实际上是错误的。事实上,如果您阅读示例 here 下的第二段,它的字面意思是相反的:“模式是相对于包含源文件的包目录进行解释的”。
  • @GoForth 是的,我可能没有使用正确的措辞,但我的意思是使用 ../ 如果你有 cmd/main.go 你不能这样做 ../templates/*不过谢谢你的回复。
【解决方案2】:

目前在 Go 1.17 中,embed 不支持子文件夹/包,请参阅https://github.com/golang/go/issues/41191#issuecomment-686616556

【讨论】:

    猜你喜欢
    • 2021-08-26
    • 2021-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-31
    • 2016-04-21
    • 1970-01-01
    相关资源
    最近更新 更多