zoukankan      html  css  js  c++  java
  • Golang 解析Yaml格式

    Golang官方并没有提供Yaml解析包,所以需要使用第三方包。可用的第三方包有不少,这里选择的是 gopkg.in/yaml.v2,这个包在github上有不少的star,也的确挺好用。其使用的是Apache License。

    这个包提供的函数还是很少了,这真是一件好事(〃∀〃)

    如果你不了解yaml,查看YAML简要入门


    func Marshal(in interface{}) (out []byte, err error)将提供的对象解析为YAML文档格式。 但要注意这里返回不是string类型


    func Unmarshal(in []byte, out interface{}) (err error)解析给定的字节切片,存储在第二参数中。你必须保证存储类型可以接受被解析的数据,否则yaml.TypeError将被返回

    让我们来看一下这个例子:

    package main
    
    import (
    	"fmt"
    	"gopkg.in/yaml.v2"
    )
    
    func main() {
    	var t T
    	s := `a: 1
    x: 333
    B: 2
    F:
      c: 3
    开心: 10
    愉悦: 30
    S: 9
    `
        yaml.Unmarshal([]byte(s), &t)	//输出为{0 1 0 0 0 0 30 333 0}
        //a不会获得值,说明 结构字段名首字母大小控制是否接受值,首字母大写为接受
        //b和B都没有获得值,未设置键时,默认解析时会将struct中字段的首字母转为小写,再去匹配Yaml,
        //这样就没有能与yaml中B想匹配的了
        //C 不能获得值说明,对应层次的字段才会赋值
        //开心与D的例子,显示如何使用中文作为键
        //X可以获得值说明,解析与声明的顺序无关
    	fmt.Println(t)
    }
    
    type T struct {
    	a int
    	A int	//yaml中a的值会给哪一个?
    	b int
    	B int	//yaml中B的值会给B还是b,或者两者都不?
    	C int	//能获得yaml中c的值吗?
    	开心 int	//能获得yaml开心的值吗?
    	D int `yaml:"愉悦"`	//使用struct标签,为D int设置键为“愉悦”
        //`yaml:"key[, tag]"`
    	X int	//X能获得值吗
    	s int `yaml:"S"`
    }
    

    你可以拷贝运行一下这段代码,自己感受下。

    如果如何struct中还有struct呢?

    package main
    
    import (
    	"fmt"
    	"log"
    
    	"gopkg.in/yaml.v2"
    )
    
    type StructA struct {
    	A string `yaml:"a"`
    }
    
    type StructB struct {
    	StructA
    	C StructA
    	B       string `yaml:"b"`
    }
    
    var data = `
    a: a string from struct A
    b: a string from struct B
    c:
      a: a string from c.a
    `
    
    func main() {
    	var b StructB
    
    	err := yaml.Unmarshal([]byte(data), &b)
    	if err != nil {
    		log.Fatalf("cannot unmarshal data: %v", err)
    	}
    	fmt.Println(b.B)
    	fmt.Println(b.A)
    	fmt.Println(b.C.A)
        /*
        输出为:
        a string from struct B	//可以看到匿名struct没有获得值
    
    	a string from c.a
    	*/
    }
    

    要为匿名结构也作为YAML的一部分解析,需要inline标记

    type StructB struct {
    	StructA`yaml:",inline"`
    	C StructA
    	B       string `yaml:"b"`
    }
    

    func UnmarshalStrict(in []byte, out interface{}) (err error)

    UnmarshalStrict和Unmarshal基本上一样,但是多了一点限制。 Yaml中的字段必须要有给定的接收对象,而在Unmarshal中它们会被忽略。


    type DecoderDecoder从输入流中读取和解析YAML值

    func NewDecoder(r io.Reader) *Decoder使用r创建Decoder

    func (dec *Decoder) Decode(v interface{}) (err error)从YAML中解析v的值

    package main
    
    import (
    	"fmt"
    	"os"
    
    	"gopkg.in/yaml.v2"
    )
    
    type StructA struct {
    	A string `yaml:"a"`
    }
    
    type StructB struct {
    	StructA
    	C StructA
    	B       string `yaml:"b"`
    }
    
    func main() {
    	var b StructB
    
    	yfile, _ := os.Open("test.yaml")	//test.yaml由下一个例子生成
    	defer yfile.Close()
    
    	ydecode:= yaml.NewDecoder(yfile)
    	ydecode.Decode(&b)	//注意这里为指针
    	fmt.Println(b)
    }
    

    type Encoder编码并将YAML写入输出流

    func NewEncoder(w io.Writer) *Encoder返回一个写入r中的Encoder Encoder带有缓冲,所以一定记得调用func (e *Encoder) Close() (err error),以防数据未写入

    func (e *Encoder) Encode(v interface{}) (err error)编码v并写入流,如果多次调用,每次存入的YAML以---分隔

    package main
    
    import (
    	"log"
    	"os"
    
    	"gopkg.in/yaml.v2"
    )
    
    type StructA struct {
    	A string `yaml:"a"`
    }
    
    type StructB struct {
    	StructA
    	C StructA
    	B       string `yaml:"b"`
    }
    
    var data = `
    a: a string from struct A
    b: a string from struct B
    c:
      a: a string from c.a
    `
    
    func main() {
    	var b StructB
    	x := 22
    
    	err := yaml.Unmarshal([]byte(data), &b)
    	if err != nil {
    		log.Fatalf("cannot unmarshal data: %v", err)
    	}
    
    	yfile, _ := os.Create("test.yaml")
    	defer yfile.Close()
    
    	yencoder := yaml.NewEncoder(yfile)
    	defer yencoder.Close()
    	yencoder.Encode(b)
    	yencoder.Encode(b)
    	yencoder.Encode(x)
    	yencoder.Encode(44)
    }
    

    这篇文章根据官方文档写成,我可能没有表述的很清楚,请查阅官方文档


    知识共享许可协议
    本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。转载请注明出处!

  • 相关阅读:
    接口调试之Postman 使用方法详解
    用Vue2仿京东省市区三级联动效果
    高德地图JS API获取经纬度,根据经纬度获取城市
    js 格式化数字,格式化金额:
    CSS Media媒体查询使用大全,完整媒体查询总结
    最新手机号正则表达式 java 、javascript版正则表达式验证是否为11位有效手机号码
    JavaScript 实现textarea限制输入字数, 输入框字数实时统计更新,输入框实时字数计算移动端bug解决
    在上线项目中,用Vue写一个星级评价
    new Date()设置日期在IOS的兼容问题
    javascript 省市区三级联动 附: json数据
  • 原文地址:https://www.cnblogs.com/xiyu714/p/9903640.html
Copyright © 2011-2022 走看看