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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM