如何将cmr10.ttf嵌入Go二进制文件,避免随可执行文件分发?
问题场景与代码
我在个人Go包中编写了如下代码,该代码必须加载cmr10.ttf字体文件,因此该字体文件必须与所有使用此包的可执行文件放置在同一目录下。
import ( "github.com/deadsy/sdfx/sdf" ) func Text(txt string, height, thickness, roundness float32) (sdf.SDF3, error) { f, err := sdf.LoadFont("cmr10.ttf") if err != nil { return nil, err } t := sdf.NewText(txt) s2d, err := sdf.TextSDF2(f, t, float64(height)) if err != nil { return nil, err } // Extrude the 2D SDF to a 3D SDF. return sdf.ExtrudeRounded3D(s2d, float64(thickness), float64(roundness)) }
提问
有没有办法避免将cmr10.ttf字体文件复制到所有使用此包的可执行文件旁?例如将字体文件嵌入编译后的二进制文件中,如果可行,具体该如何操作?还有其他可行方案吗?
解决方案
方案一:用Go 1.16+的embed包嵌入字体到二进制
这是最可靠的方案,直接将字体文件嵌入包的二进制文件,无需额外携带字体文件。
操作步骤:
- 在你的包目录下创建
fonts子目录,将cmr10.ttf放入其中。 - 修改代码引入
embed包,嵌入字体文件并从嵌入的文件系统读取内容:
import ( "embed" "github.com/deadsy/sdfx/sdf" "io/fs" ) //go:embed fonts/cmr10.ttf var fontsFS embed.FS func Text(txt string, height, thickness, roundness float32) (sdf.SDF3, error) { // 从嵌入的文件系统打开字体文件 fontFile, err := fontsFS.Open("fonts/cmr10.ttf") if err != nil { return nil, err } defer fontFile.Close() // 使用sdf库支持从io.Reader加载字体的方法(比如LoadFontReader) f, err := sdf.LoadFontReader(fontFile) if err != nil { return nil, err } t := sdf.NewText(txt) s2d, err := sdf.TextSDF2(f, t, float64(height)) if err != nil { return nil, err } return sdf.ExtrudeRounded3D(s2d, float64(thickness), float64(roundness)) }
注:如果
sdfx库未提供LoadFontReader,可先将嵌入的字体内容读入字节切片,再用bytes.NewReader包装为io.Reader后传入自定义加载逻辑。
方案二:通过模块路径定位包内字体文件
将字体文件放在包的固定子目录,通过可执行文件路径反向定位包内的字体文件,需确保部署时字体文件随包目录一同复制。
示例代码:
import ( "github.com/deadsy/sdfx/sdf" "os" "path/filepath" ) func Text(txt string, height, thickness, roundness float32) (sdf.SDF3, error) { // 获取当前可执行文件路径 exePath, err := os.Executable() if err != nil { return nil, err } exeDir := filepath.Dir(exePath) // 替换为你的模块实际路径,比如"your-module/pkg/fonts" fontPath := filepath.Join(exeDir, "your-module-path", "fonts", "cmr10.ttf") f, err := sdf.LoadFont(fontPath) if err != nil { return nil, err } t := sdf.NewText(txt) s2d, err := sdf.TextSDF2(f, t, float64(height)) if err != nil { return nil, err } return sdf.ExtrudeRounded3D(s2d, float64(thickness), float64(roundness)) }
方案三:使用系统预装字体
若cmr10.ttf是系统可能预装的字体(比如部分Linux发行版的TeX包会包含),可遍历系统字体目录查找:
- Linux:
/usr/share/fonts/、~/.fonts/ - Windows:
C:\Windows\Fonts\ - macOS:
/Library/Fonts/、~/Library/Fonts/
编写函数遍历上述路径查找字体文件,找到后加载即可。此方案无需携带字体文件,但依赖目标系统的字体预装情况,兼容性较差。
内容的提问来源于stack exchange,提问作者Megidd
相关产品推荐
相关产品推荐

