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)
讓我們來看一下這個例子:
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 國際許可協議進行許可。轉載請註明出處!