Golang合并yaml文件过程逐步讲解
梦想画家 人气:0当前有趋势使用环境变量代替配置文件,主要是为了方便容器部署,因为文件需要额外文件权限。但环境变量也有缺点,如长度和因数量太多造成的复杂性,另外嵌套也很难实现,此时配置文件则更合适。
本文就介绍Golang读写配置文件,以及合并配置获得最终配置信息。
读配置
首先准备配置文件config.yaml:
name: test image: tom.png environment: os: linux group: admin user: testAdmin limits: cpu: 4 memory: 512M
为了加载配置,需要定义结构体及标签,和json标记类似:
type Spec struct { // Name: name of the function Name string `yaml:"name"` // Image: docker image name of the function Image string `yaml:"image"` Environment map[string]string `yaml:"environment,omitempty"` // Limits for the function Limits *FunctionResources `yaml:"limits,omitempty"` } // FunctionResources Memory and CPU type FunctionResources struct { Memory string ` yaml:"memory"` CPU string ` yaml:"cpu"` }
这里仅用yaml代替json,下面解析也同样使用Unmarshal接口生成对象:
import ( "fmt" "os" "gopkg.in/yaml.v2" ) func ReadYaml() { bytesOut, err := os.ReadFile("config.yaml") if err != nil { panic(err) } spec := Spec{} if err := yaml.Unmarshal(bytesOut, &spec); err != nil { panic(err) } fmt.Printf("Function name: %s\tImage: %s\tEnvs: %d\n", spec.Name, spec.Image, len(spec.Environment)) fmt.Printf("Limists: %s, %s\n", spec.Limits.CPU, spec.Limits.Memory) }
输出结果:
Function name: test Image: tom.png Envs: 3
Limists: 4, 512M
写配置
写文件首先使用接口Marshal把对象序列化为字节数组,然后调用os方法写yaml文件:
func WriteYaml() { spec := Spec{ Image: "docker.io/functions/figlet:latest", Name: "figlet", } bytesOut, err := yaml.Marshal(spec) if err != nil { panic(err) } err = os.WriteFile("figlet.yaml", bytesOut, os.ModePerm) if err != nil { panic(err) } fmt.Printf("Wrote: figlet.yaml. . OK. \n") }
运行程序成功生成figlet.yaml文件并输出:
Wrote: figlet.yaml. . OK.
使用yaml.v2库可以快速实现配置文件相关工作,下面介绍如何合并多个配置信息。
合并配置
如果配置信息包括包括很多字段,则可能需要维护一个示例文件,并允许用户提供新的值进行修改。我们可以使用mergo库实现合并功能,当然其他库也可以实现类似功能,该方法支持内存中任何结构体,不一定为YAML:
import "github.com/imdario/mergo" func MergeYaml() { base := Spec{ Image: "docker.io/functions/figlet:latest", Name: "figlet", Environment: map[string]string{"stage": "develop"}, Limits: &FunctionResources{Memory: "512Mi", CPU: "60Mi"}, } production := Spec{ Environment: map[string]string{"stage": "production"}, Limits: &FunctionResources{Memory: "1Gi", CPU: "100Mi"}, } overrides := []Spec{ base, production, } merged := Spec{} for _, override := range overrides { err := mergo.Merge(&merged, override, mergo.WithOverride) if err != nil { panic(err) } } bytesOut, err := yaml.Marshal(merged) if err != nil { panic(err) } fmt.Printf("Merged content: \n\n%s\n", string(bytesOut)) }
运行测试输出结果:
Merged content:
name: figlet
image: docker.io/functions/figlet:latest
environment:
stage: production
limits:
memory: 1Gi
cpu: 100Mi
我们在Merge方法指定后面覆盖前置配置,读者还可以通过源码查看其他的合并方法。
加载全部内容