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 Decoder
Decoder從輸入流中讀取和解析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 國際許可協議進行許可。轉載請注明出處!