惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

A
About on SuperTechFans
G
Google Developers Blog
L
LangChain Blog
aimingoo的专栏
aimingoo的专栏
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
云风的 BLOG
云风的 BLOG
小众软件
小众软件
月光博客
月光博客
Recent Announcements
Recent Announcements
人人都是产品经理
人人都是产品经理
P
Proofpoint News Feed
博客园 - 聂微东
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
雷峰网
雷峰网
The Cloudflare Blog
博客园_首页
美团技术团队
大猫的无限游戏
大猫的无限游戏
B
Blog
IT之家
IT之家
Jina AI
Jina AI
H
Hackread – Cybersecurity News, Data Breaches, AI and More
C
Check Point Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知

MoonLab

VSCode + OpenOCD 远程调试开发STM32 Clangd + VSCode使用方法 Keil5 编译错误 error: call to undeclared function '__enable_irq' BTSNOOP is FUN! 算法 - 前缀和 2025蓝桥杯赛后总结 三星ZFold 3改造 JavaScript 逆向 Steam 登录二维码 快速求解平方根倒数算法 Protobuf Android设备安装Debian成为BT下载服务器 [双系统] Windows 更新摧毁了我的Linux系统 Reading List Hexo博客自动备份插件 云盘备份支持 通过汇编分析栈、函数调用 esp&ebp Git push 出现 permisson denied error 403 坑:Litepal save方法返回true却没有保存 Android Shizuku源码分析 第二篇 Android Shizuku源码分析 Android 监听第三方Activity的一举一动 Android笔记#1 View的事件分发机制解析 知乎日报的问题 使用Hexo Hello World Ubnutu 无法启动网易云音乐 - 总结 Windows 好软推荐 | 这一定是良心软件 typecho - http转https 如何评价Android P MoonLab MoonLab
Golang embed 使用问题
LingC · 2023-12-27 · via MoonLab

📦 由AI生成的摘要
Golang 使用 embed 包在编译时将外部文件包含到二进制程序中。使用 embed 指令可以将 html、css、js 等静态文件添加到二进制文件中,而无需额外的资源文件。嵌入文件可以使用字符串、[]字节和 FS 来引用。但也有一些限制,如文件层次结构问题和复杂路径问题。例如,如果嵌入文件和被嵌入文件不在同一层次,嵌入模式将无法成功解析。另一个问题是处理复杂路径,即静态文件夹被放置在嵌入文件的子文件夹中。解决办法是使用 io/fs 软件包中的 Sub 方法来处理这些复杂路径。

Golang一般用到embed package的主要场景就是Web server需要携带html css js等静态文件。

使用embed directive可以让外部文件在编译时自动加入到二进制程序中。这样我们如果要分发程序,只需一个二进制文件,不需要外带任何其他资源文件。

而我们在代码中去引用embedded文件有三种方法(类型):string , []byteFS

但实际上,embed还是有一些限制的,本文就详细讲讲这些限制是什么,以及如何曲线救国。

文件层级问题

如果embed directive与被embedded的文件不在同一级(文件系统中)。

比如说

│  main.go
│  
├─server
│      handler.go
│      
└─tepl
        index.html

如果handler.go试图去包含tepl文件夹里的文件:

// handler.go
//go:embed tepl
var s embed.FS

embed pattern将无法被成功解析,因为被引用者的文件层级高于引用者。

除了将被引用者的文件层级降至同一级或更低,还有一种方法就是直接在main.go这样同级的文件中进行处理,然后传递给需要的包中。

// main.go
//go:embed tepl
var tepl embed.FS

func main() {
	handler.injectFS(&tepl)
}

目前来说,没有其他更好的解决方法了。

复杂路径问题

假如我们在tepl中放入一个static文件夹:

│  main.go
│  
└─server
    │  handler.go
    │  
    └─tepl
        │  index.html
        │  
        └─static
                main.css

在handler.go中,我们用http.FileServer来处理对静态文件们的请求:

//go:embed tepl
var tepl embed.FS

func handle() {
	http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.FS(tepl))))
}

很自然地,定义的是/static/的路由,而不是/,因为根路径常常要处理其他事情。

但此时由于 embed 的局限,如果我们要获取mian.css,就需要访问这个路径/static/tepl/static/main.css

解决的方法也很简单,用 io.fs 包中的Sub方法即可:

var tepl embed.FS

func handle() {
	sub, _ := fs.Sub(tepl, "tepl/static")
	http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.FS(sub))))
}

Refs


https://pkg.go.dev/embed