前言 我们平时读取配置文件大多都是json, ini, conf, yaml ...
这一些文件,各有各的方便之处。现在我这里浅浅的记录一下go
语言读取 yaml
文件。
这个文章只讲 读取 文件 的demo
首先我这里会说到两种方案,和网上的基本其它教程一样的:
gopkg.in/yaml.v3
github.com/spf13/viper
现在我们简单说一下我这里的目录结构
1 2 3 4 $GOPATH/src/YamlTest |____________config.yaml 目标文件 |____________yamlV3.go 第一种方式 |____________vipeRead.go 第二种方式
这个测试的配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 name: Heartfilia age: 666 next: test1: 111 test2: 222 test3: 333 more: - - 666 - 777 - 888 - - 000 - 111 - 222
yaml.v3 这个包是谷歌官方推荐的,很快,不一定方便。
安装
1 go get -u gopkg.in/yaml.v3
用这个包,我们得已知目录结构,然后创建映射关系。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 package mainimport ( "fmt" "gopkg.in/yaml.v3" "os" ) type Next struct { Test1 int `json:"test1"` Test2 int `json:"test2"` Test3 int `json:"test3"` } type Config struct { Name string `json:"name"` Age int `json:"age"` Next Next `json:"next"` More [][]int `json:"more"` } func main () { dataBytes, _ := os.ReadFile("config.yaml" ) config := Config{} yaml.Unmarshal(dataBytes, &config) name := config.Name more := config.More[0 ][1 ] fmt.Println(name, " : " , more) }
因为这个后面读取内容和普通的变量属性操作没有任何差别,这里不再赘述。
viper
安装
1 go get -u "github.com/spf13/viper"
这个在读取一般文件的时候非常方便,然后可以读取各种类型的配置文件,如果不配置后面的一个文件格式 的属性,那么就会按照优先级依次读取。
优先级如下:
1 json > toml > yaml > yml > properties > props > hcl > tfvars > dotenv > env > ini
也就是如果如果配置文件格式那里不写格式,同一个目录下有 config.json
和config.yaml
那么会优先读取json
格式的。
代码
这个包整体模板都差不多的,我这里先写一个基础格式 然后细说后面的一些操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package mainimport ( "fmt" viper2 "github.com/spf13/viper" "strings" ) func Get (filePath, searchKey string ) interface {} { basePathArray := strings.Split(filePath, "\\" ) fileName := basePathArray[len (basePathArray)-1 ] index := strings.Index(fileName, "." ) fileNameString := fileName[:index] key := fileName[index+1 :] viper := viper2.New() viper.SetConfigName(fileNameString) viper.SetConfigType(key) viper.AddConfigPath("$GOPATH/src/YamlTest" ) viper.AddConfigPath("." ) if err := viper.ReadInConfig(); err != nil { panic (err.Error()) } return viper.Get(searchKey) }
然后基本的键值对提取数据很简单,按照我这模板只需要如下写都可以
1 2 3 4 5 6 7 8 func main () { result := Get("C:\\code\\mine\\GoCode\\src\\SqlTest\\YamlTest\\config.yaml" , "next.test1" ) fmt.Println(result) result = Get("config.yaml" , "next.test1" ) fmt.Println(result) result = Get("config.yaml" , "name" ) fmt.Println(result) }
到目前来都很简单,这也是大多数配置文件这样子写的,但是我这例子里面有一个嵌套的二维数组,我这里尝试提取 more[0][1]
的数据。这里才是我这里要讲的核心点。
这里我们先尝试获取more
的数据查看一下类型及结果
1 2 3 4 5 6 7 func main () { result := Get("config.yaml" , "more" ) fmt.Printf("%T %v\n" , result, result) }
所以可以说获取到了是一个 接口的集合值,我们现在需要对它进行遍历一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 func main () { result := Get("config.yaml" , "more" ) switch reflect.TypeOf(result).Kind() { case reflect.Slice, reflect.Array: s := reflect.ValueOf(result) for i := 0 ; i < s.Len(); i++ { key := s.Index(i).Interface() s1 := reflect.ValueOf(key) fmt.Printf("%T %v\n" , s1, s1) } } }
可以看到我们运行了一次后 里面还有一层 但是是 reflect.Value
类型的,我们最终其实是想要里面的数据 比如我们设置成 int
类型的 所以我们这里最好得创建一个变量来接收这个结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 func main () { result := Get("config.yaml" , "more" ) var res [2 ][3 ]int switch reflect.TypeOf(result).Kind() { case reflect.Slice, reflect.Array: s := reflect.ValueOf(result) for i := 0 ; i < s.Len(); i++ { key := s.Index(i).Interface() s1 := reflect.ValueOf(key) for i1 := 0 ; i1 < s1.Len(); i1++ { val := s1.Index(i1).Interface().(int ) res[i][i1] = val } } } fmt.Println(res) fmt.Println(res[0 ][1 ]) }
每一个 reflect.Value
属性的值都会有Interface()
的方法,然后就可以转换成想要的结果 我们这里数组默认是int
。我们要是后面不跟着.(int)
,那么这个val是不可以给res赋值过去的,因为它会说 我们这个Interface()
返回的结果类型是Any
,不是int
。 虽然我们单个取值查看类型Interface()
返回的就是int
,但是我们如果要给其它res
使用,这里就得指定一下,它返回的就是int
。所以才不会有什么问题的。
1 2 3 4 5 6 7 8 val := s1.Index(i1).Interface() res[i][i1] = val Cannot use 'val' (type any) as the type int var val any = s1.Index(i1).Interface()
所以我们这里一定要转换一下 然后就可以提取想要的结果了
总结 效率来说yaml.v3
运行效率很高,启动没有那么快,操作便捷性一般。github
viper
这个只要不搞我上面比较复杂的那种数组读取之类的,还是很简单的,也可以赋值给已经创建好了的结构体,也可以上手即用,运行效率比yaml.v3
慢一丢丢,但是好用啊,比如我这里只是读取 操作,这个东西写起来也很方便,但是我这里就不用了,因为一般的配置文件都是我们外面写好的,就不赘述了,写的自己去查官网啥的。 github