You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用go:embed嵌入配置文件供viper正常加载应用属性

问题原因

你当前代码不生效的核心原因是:viper.AddConfigPath("./configs")默认读取的是操作系统本地文件系统的路径,完全没有用到你通过//go:embed嵌入的embed.FS资源,所以运行时只会去二进制同级的磁盘目录找configs文件夹,自然读不到嵌入到二进制内部的配置文件。

正确解决方案

首先确认前置条件:

  • 你的//go:embed指令写在Go源文件的顶层作用域(不能写在函数内部)
  • embed路径是相对于当前Go源文件的正确相对路径,不包含..等跨目录特殊写法、不以/开头
  • 使用的viper版本 ≥ v1.10.0(低版本没有嵌入FS支持,用后面的通用写法即可)

写法1:使用viper原生的FS支持(推荐)

直接替换原来的配置加载逻辑,通过viper.AddConfigFS传入你嵌入的文件系统,注意路径要对应embed.FS内部的路径规则:

package main

import (
	"embed"
	"github.com/spf13/viper"
)

//go:embed configs/*.conf
var resources embed.FS

func LoadConfig() error {
	// 传入嵌入的文件系统,后续配置路径都基于该FS查找
	viper.AddConfigFS(resources)
	// 注意:这里写embed.FS内的目录路径,不要加./前缀
	viper.AddConfigPath("configs")
	// 配置文件名不需要带后缀
	viper.SetConfigName("app_dev")
	// 显式指定配置格式,避免.conf后缀无法被viper自动识别
	viper.SetConfigType("properties")

	if err := viper.ReadInConfig(); err != nil {
		return err
	}
	return nil
}

写法2:直接读取嵌入文件(通用,无viper版本要求)

如果你的viper版本较低,或者不需要多配置文件自动查找能力,可以直接打开嵌入的配置文件,交给viper解析,完全不会有路径匹配问题:

func LoadConfig() error {
	// 直接打开嵌入的目标配置文件,路径写embed内的完整相对路径
	confFile, err := resources.Open("configs/app_dev.conf")
	if err != nil {
		return err
	}
	defer confFile.Close()

	viper.SetConfigType("properties")
	// 直接从打开的文件句柄读取配置
	if err := viper.ReadConfig(confFile); err != nil {
		return err
	}
	return nil
}
常见踩坑点
  • 不要保留原来的viper.AddConfigPath("./configs")代码:调用AddConfigFS后,后续传入的AddConfigPath是相对于嵌入FS的路径,写本地磁盘路径会导致查找失败
  • 如果你的配置文件不是properties格式(比如是yaml、toml),把SetConfigType的参数改成对应的格式(yaml/toml)即可
  • 编译后直接运行二进制即可,不需要在二进制同级放置configs文件夹,所有匹配configs/*.conf的文件已经被打包进二进制内部
  • 如果写embed指令的Go源文件和configs目录不在同一层级,要调整embed的相对路径,比如源文件在cmd/server/main.go,configs在项目根,那embed路径要写成//go:embed ../../configs/*.conf

内容的提问来源于stack exchange,提问作者Rocky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 21:27:25