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 国际许可协议进行许可。转载请注明出处!

转载于:https://www.cnblogs.com/xiyu714/p/9903640.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值