本文对 yaml 文件进行解析。
yaml执行 go get github.com/spf13/viper
安装。
golang 有很多库可以解释 yaml 文件。本文选用 viper 进行解析,执行 go get github.com/spf13/viper
安装。
#
进行注释,与shell
一样。# yaml测试样例
# null 或 NULL 为关键字,不能写
# 表示 bool 真假的几个值
result_true:
- y
- Y
- yes
- Yes
- YES
- true
- True
- TRUE
- on
- On
- ON
# 数组的另一种形式
result_false: [n, N, no, No, NO , false, False, FALSE , off, Off, OFF]
# 名称
# 字符串
name: conf file
# 版本
# 如按浮点,2.0会转换成2
# 如按字符串,保留原样
version: 2.0
# 布尔类,转换为1或0
need: true
# 时间
time: 2020-10-03T09:21:13
empty: nul
# 对象
# 加双引号会转义\n,即会换行
my:
name: late \n lee
name1: "late \n lee"
age: 99
# 块
text: |
hello
world!
# 数组
fruit:
- apple
- apple1
- apple2
- apple3
- apple4
- apple5
# 多级数组
multi:
sta:
- 110 210 ddd 99
- 133 135 1 2 1588 1509
- 310-410
- 333-444
# 多层级
loginfo:
log:
dir: log
# 多级对象
mymap:
dir: "mymap"
map_data:
- name: "在线"
attri: "在线电子"
url: "http://abc.com"
- name: "离线"
attri: "离线电子"
url: "http://ccc.com"
# more
该示例基本涵盖了大部分的 yaml 格式。包括:字符串,数值、数组、多级map。
测试代码如下:
package test
import (
"fmt"
"os"
"testing"
"github.com/spf13/viper"
)
var (
cfgFile string
)
type mapUrl_t struct {
Name string `json:"name"`
Attri string `json:"attri"`
Url string `json:"url"`
}
func TestYaml(t *testing.T) {
fmt.Println("test of yaml...")
// 设置配置文件的2种方式
if cfgFile != "" {
// Use config file from the flag.
viper.SetConfigFile(cfgFile)
} else {
viper.AddConfigPath("./")
viper.SetConfigName("config")
viper.SetConfigType("yaml")
}
viper.AutomaticEnv() // read in environment variables that match
// 读取
err := viper.ReadInConfig()
if err != nil {
fmt.Println("'config.yaml' file read error:", err)
os.Exit(0)
}
name := viper.GetString("name") // 读取 字符串
version := viper.GetString("version")
need := viper.GetBool("need") // 读取 布尔
theTime := viper.GetString("time")
empty := viper.GetString("empty")
text := viper.GetString("text")
fmt.Printf("need: %v name: %v\nversion: %v \ntime: %v \nempty: %s \ntext: %v\n", need, name, version, theTime, empty, text)
// 多级读取
name = viper.GetString("my.name")
name1 := viper.GetString("my.name1")
age := viper.GetInt("my.age")
fmt.Printf("name: %v, name1: %v age: %v \n", name, name1, age)
// 字符串数组
newSta := viper.GetStringSlice("multi.sta")
for idx, value := range newSta {
fmt.Printf("sta[%d]: %v\n", idx, value)
}
fruit := viper.GetStringSlice("fruit")
fmt.Printf("fruit: %v\n", fruit)
// 读取不存在的字段,字符串为空,数值为0
bad := viper.GetString("bad")
bad1 := viper.GetInt("my.bad")
fmt.Printf("bad: [%v] bad1: [%v]\n", bad, bad1)
// 按数值、字符串读取on、off等值
result := viper.GetIntSlice("result_true")
fmt.Printf("result true: [%v]\n", result)
result1 := viper.GetStringSlice("result_true")
fmt.Printf("result1 true: [%v]\n", result1)
result = viper.GetIntSlice("result_false")
fmt.Printf("result false: [%v]\n", result)
result1 = viper.GetStringSlice("result_false")
fmt.Printf("result1 false: [%v]\n", result1)
logdir := viper.GetString("loginfo.log.dir")
fmt.Printf("logdir: %v\n", logdir)
// 多级对象
// tmpMap := make([]mapUrl_t, 0, 20)
var tmpMap []mapUrl_t
viper.UnmarshalKey("mymap.map_data", &tmpMap)
for _, item := range tmpMap {
fmt.Printf("name: %v url: %v\n", item.Name, item.Url)
}
}
测试命令:
go test -v -run TestYaml
测试结果:
test of yaml...
need: true name: conf file
version: 2
time: 2020-10-03T09:21:13
empty: nul
text: hello
world!
name: late \n lee, name1: late
lee age: 99
sta[0]: 110 210 ddd 99
sta[1]: 133 135 1 2 1588 1509
sta[2]: 310-410
sta[3]: 333-444
fruit: [apple apple1 apple2 apple3 apple4 apple5]
bad: [] bad1: [0]
result true: [[1 1 1 1 1 1 1 1 1 1 1]]
result1 true: [[true true true true true true true true true true true]]
result false: [[0 0 0 0 0 0 0 0 0 0 0]]
result1 false: [[false false false false false false false false false false false]]
logdir: log
name: 在线 url: http://abc.com
name: 离线 url: http://ccc.com
1、name: "late \n lee"
输出会换行。而 name: late \n lee
则会原样输出。
2、参数的值不能为 null 或 NULL,但可以为nul。如果为 null,解析的值为空。
3、如果字段不存在,不会报错,按字符串解析得到的值为空,如用数值,值为0。
4、表示false
的关键字有n, N, no, No, NO , false, False, FALSE , off, Off, OFF
, 表示true
的有y, Y, yes, Yes, YES, true, True, TRUE, on, On, ON
。在使用时需要注意。
5、对于多层级的对象,可以用viper.UnmarshalKey
,用法与解析json类似。