Golang 解析Yaml格式

Golang官方並無提供Yaml解析包,因此須要使用第三方包。可用的第三方包有很多,這裏選擇的是
gopkg.in/yaml.v2,這個包在github上有很多的star,也的確挺好用。其使用的是Apache License。html

這個包提供的函數仍是不多了,這真是一件好事(〃∀〃)git

若是你不瞭解yaml,查看YAML簡要入門github


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"`
}

你能夠拷貝運行一下這段代碼,本身感覺下。code

若是如何struct中還有struct呢?htm

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)blog

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 國際許可協議進行許可。轉載請註明出處!

相關文章
相關標籤/搜索