从嵌入文件夹调用JS、CSS和IMG资源的Golang实践
从嵌入文件夹调用JS、CSS和IMG资源的Golang实践 借助新的 embed 包,我能够嵌入我的文件,并按如下方式调用我的模板:
// inner/embed.go
package inner
import (
"embed"
)
// Content 是我们的静态 Web 服务器内容。
//go:embed configuration template layout
var Content embed.FS // 以 '.' 或 '_' 开头的文件会被排除
// web/Bayan.go
package web
import (
"fmt"
"hasan/embed/inner"
"html/template"
"log"
"net/http"
"os"
"gopkg.in/yaml.v2"
)
// Config ...
type Config struct {
Server struct {
Port string `yaml:"port"`
Host string `yaml:"host"`
} `yaml:"server"`
Database struct {
Username string `yaml:"user"`
Password string `yaml:"pass"`
} `yaml:"database"`
}
func processError(err error) {
fmt.Println(err)
os.Exit(2)
}
func readFile(cfg *Config, lang string) {
data, err := inner.Content.ReadFile("configuration/bayan-" + lang + ".yml")
if err != nil {
log.Fatal(err)
}
// fmt.Println(string(data))
err = yaml.Unmarshal([]byte(data), &cfg)
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("%+v\n", cfg)
fmt.Printf("%+v\n", cfg.Database.Username)
}
// Bayan ...
func Bayan(w http.ResponseWriter, r *http.Request) {
var cfg Config
var lng string
lang, err := r.Cookie("language")
if err != nil {
lng = "ar"
} else {
lng = lang.Value
}
readFile(&cfg, lng)
var tmpl *template.Template
tmpl, err = template.ParseFS(inner.Content, "layout/layout.html", fmt.Sprint("template/bayan-", lng, ".html"))
if err != nil {
fmt.Println(err)
}
//tmpl, err := template.New("").ParseFiles(fmt.Sprint("template/bayan-en.html"), "base.html")
//tmpl, err := template.ParseFiles(fmt.Sprint(http.FS(inner.Content), "/layout/layout.html"))
// or
//tmpl := template.Must(template.ParseFiles("layout/layout.html"))
//tmpl.Execute(w, "data goes here, this is Hasan")
tmpl.ExecuteTemplate(w, "base", "hi")
if err != nil {
fmt.Println(err)
}
}
// main.go
package main
import (
"fmt"
"hasan/embed/inner"
"hasan/embed/web"
"net/http"
_ "embed"
"github.com/zserge/lorca"
)
func main() {
port := "8090"
go func() {
http.HandleFunc("/bayan", web.Bayan)
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.FS(inner.Content))))
http.ListenAndServe(":"+port, nil)
}()
// Start UI
ui, err := lorca.New("http://localhost:8090/bayan", "", 1200, 800)
if err != nil {
fmt.Println("error:", err)
}
defer ui.Close()
<-ui.Done()
}
我的嵌入文件位于 inner 文件夹中,结构如下:

我的问题是,如何在模板中调用 JavaScript、CSS 和 img 文件。
例如,现在如何替换模板中的 <link href="/styles/fontawesome-free-5.15.2-web/css/all.css" rel="stylesheet">?
更多关于从嵌入文件夹调用JS、CSS和IMG资源的Golang实践的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于从嵌入文件夹调用JS、CSS和IMG资源的Golang实践的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go语言中通过embed包嵌入静态资源后,可以通过http.FileServer提供静态文件服务。以下是具体实现示例:
// main.go中修改静态文件路由配置
func main() {
port := "8090"
go func() {
http.HandleFunc("/bayan", web.Bayan)
// 提供静态文件服务
http.Handle("/styles/", http.StripPrefix("/styles/",
http.FileServer(http.FS(inner.Content))))
http.Handle("/js/", http.StripPrefix("/js/",
http.FileServer(http.FS(inner.Content))))
http.Handle("/img/", http.StripPrefix("/img/",
http.FileServer(http.FS(inner.Content))))
http.ListenAndServe(":"+port, nil)
}()
// ... 其余代码不变
}
在模板中直接使用相对路径引用资源:
<!-- layout/layout.html -->
<!DOCTYPE html>
<html>
<head>
<!-- 引用CSS文件 -->
<link href="/styles/fontawesome-free-5.15.2-web/css/all.css" rel="stylesheet">
<link href="/styles/main.css" rel="stylesheet">
</head>
<body>
{{template "content" .}}
<!-- 引用JavaScript文件 -->
<script src="/js/main.js"></script>
<!-- 引用图片 -->
<img src="/img/logo.png" alt="Logo">
</body>
</html>
如果资源文件位于子目录中,需要确保embed指令包含所有相关目录:
// inner/embed.go
package inner
import (
"embed"
)
//go:embed configuration template layout styles js img
var Content embed.FS
对于动态生成的模板路径,可以在模板函数中处理:
// web/Bayan.go中修改模板处理
func Bayan(w http.ResponseWriter, r *http.Request) {
// ... 配置读取代码不变
// 创建带自定义函数的模板
funcMap := template.FuncMap{
"static": func(path string) string {
return "/" + path
},
}
tmpl, err := template.New("").Funcs(funcMap).ParseFS(
inner.Content,
"layout/layout.html",
fmt.Sprintf("template/bayan-%s.html", lng),
)
if err != nil {
fmt.Println(err)
return
}
tmpl.ExecuteTemplate(w, "base", nil)
}
然后在模板中使用自定义函数:
<!-- 在模板中 -->
<link href="{{static "styles/fontawesome-free-5.15.2-web/css/all.css"}}" rel="stylesheet">
如果需要处理版本控制或缓存问题,可以添加时间戳参数:
funcMap := template.FuncMap{
"static": func(path string) string {
// 添加构建时间戳作为查询参数
return "/" + path + "?v=" + buildTimestamp
},
}
确保文件系统结构匹配URL路径。如果资源文件位于styles/fontawesome-free-5.15.2-web/css/目录下,那么对应的URL路径就是/styles/fontawesome-free-5.15.2-web/css/all.css。

