以下の内容はhttps://golang.hateblo.jp/entry/2018/11/08/183555より取得しました。


Go言語(golang) YAMLの使い方

golang.png


golangにはYAMLの標準パーッケージはありません。
なので yaml.v2 を使って、
YAML から go言語のデータ型(構造体やマップなど) に変換(Unmarshal,Decode) と、
その逆で go言語のデータ型から YAML に変換(Marshal,Encode) します。

以下、パッケージのダウンロード、Unmarshal,Decode,Marshal,Encode それぞれの使い方、
構造体のタグ(アノテーション) についてサンプルコードで説明しています。

※データを読み込むだけなら yaml,json 形式どちらも扱えます。


YAML 公式ページ

ライブラリ yaml.v2



目次



ダウンロード - download

$ go get gopkg.in/yaml.v2

使い方


YAML から map にする - Unmarshal

package main

import (
    "fmt"
    "log"
    "os"

    yaml "gopkg.in/yaml.v2"
)

func main() {
    var m map[string]interface{}

    data := `
  name: Tanaka
  age: 30
`
    // JSONでも同じで、ポインタで渡す
    err := yaml.Unmarshal([]byte(data), &m)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("%v\n", m) // map[name:Tanaka age:30]
}


YAML から構造体にする - UnmarshalStrict

厳格モード。キーの重複や、構造体にフィールド名が無い場合にエラーになる

package main

import (
    "fmt"
    "log"

    yaml "gopkg.in/yaml.v2"
)

type Profile struct {
    Name string `yaml:"name"`
    Age  int    `yaml:"age"`
}

func main() {
    data := `
  name: Tanaka
  age: 31
`
    var p Profile
    err := yaml.UnmarshalStrict([]byte(data), &p)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("%#v\n", p) // main.Profile{Name:"Tanaka", Age:31}


    // 以下は厳格モードなのでエラー
    // name が重複でエラーになる
    // line 3: field name already set in type main.Profile
    // unknown は Profile のフィールド名にないのでエラー
    // line 4: field unknown not found in type main.Profile
    data = `
  name: Tanaka
  name: Suzuki
  unknown: 1000
`

    err = yaml.UnmarshalStrict([]byte(data), &p)
    if err != nil {
        log.Fatal(err)
    }
}


map から YAML([]byte) に変換 - Marshal

Go言語のデータ型(struct,map,slice)から YAML に変換する

package main

import (
    "fmt"
    "log"
    "os"

    yaml "gopkg.in/yaml.v2"
)

func main() {
    m := map[string]interface{}{
        "name": "Tanaka",
        "age":  30,
    }

    data, err := yaml.Marshal(m)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(string(data))
    // age: 30
    // name: Tanaka
}



デコード - NewDecoder - Decode

YAML データから Go のデータ型(map,slice,struct) に変換する

package main

import (
    "fmt"
    "log"
    "os"
    "strings"

    yaml "gopkg.in/yaml.v2"
)

func main() {
    var m map[string]interface{}

    data := `
  name: Tanaka
  age: 30
`

    d := yaml.NewDecoder(strings.NewReader(data))

    // UnmarshalStrict と同じで厳格モードにするなら以下を指定する
    // デフォルトは、厳格モードは無効
    // 当然ですが、 d.Decode(&m) の前に指定する必要がある
    d.SetStrict(true)

    err := d.Decode(&m)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("%v\n", m) // map[name:Tanaka age:30]
}


ファイルから読み込む

package main

import (
    "fmt"
    "log"
    "os"

    yaml "gopkg.in/yaml.v2"
)

func main() {
    f, err := os.Open("hello.yml")
    if err != nil {
        log.Fatal(err)
    }
    defer f.Close()

    d := yaml.NewDecoder(f)

    var m map[string]interface{}

    if err := d.Decode(&m); err != nil {
        log.Fatal(err)
    }

    fmt.Printf("%v\n", m) // map[name:Tanaka age:30]
}



エンコード - NewEncoder - Encode

Goのデータ型(map,slice,struct) などから、YAML に変換して書き込む

package main

import (
    "bytes"
    "fmt"
    "log"

    yaml "gopkg.in/yaml.v2"
)

func main() {
    data := map[string]interface{}{"name": "Tanaka", "age": 31}

    var b bytes.Buffer
    d := yaml.NewEncoder(&b)

    err := d.Encode(&data)
    if err != nil {
        log.Fatal(err)
    }

    d.Close() // 残りのデータを書き込んでエンコーダを終了する

    fmt.Printf("%s\n", b.String())
    // name: Tanaka
    // age: 30
}


ファイルに書き込む

package main

import (
    "log"
    "os"

    yaml "gopkg.in/yaml.v2"
)

func main() {
    data := map[string]interface{}{"name": "Tanaka", "age": 31}

    f, err := os.OpenFile("hello.yml", os.O_WRONLY|os.O_CREATE, 0664)
    if err != nil {
        log.Fatal(err)
    }
    defer f.Close()

    d := yaml.NewEncoder(f)

    if err := d.Encode(&data); err != nil {
        log.Fatal(err)
    }

    d.Close()
}



構造体のタグ - tags

タグの指定方法

yaml:"[名前][,オプション1[,オプション2]]"


オプション

  • omitempty
    構造体の値が初期値だった場合は、YAMLとして出力されない
    初期値とは string型 なら 空文字、int型 なら 0 など


  • flow YAML のフロースタイルで出力する
    フロースタイルとは JSON のような形式(デフォルトはブロックスタイル) { name: Tanaka, age: 30 }


  • inline
    構造体またはマップに使うことができる


  • "-"
    タグの名前に yaml:"-" を指定した場合は、そのフィールドは無視される


名前を指定しても Name string `yaml:"name"` は Name でも name でもどちらでもよい。
構造体のフィールド名が小文字 name string `yaml:"name"` の場合は、"-" 同様で無視される。



inline,flow を指定した場合と指定しない場合

package main

import (
    "fmt"
    "log"

    yaml "gopkg.in/yaml.v2"
)

func main() {

    { // オプションの指定なし
        u := struct {
            Name  string         `yaml:"name"`
            Age   int            `yaml:"age"`
            Score map[string]int `yaml:"score"`
        }{
            Name:  "Tanaka",
            Age:   30,
            Score: map[string]int{"1st": 10, "2nd": 20, "3rd": 30},
        }

        data, err := yaml.Marshal(u)
        if err != nil {
            log.Fatal(err)
        }

        fmt.Println(string(data))
        // name: Tanaka
        // age: 30
        // score:
        //   1st: 10
        //   2nd: 20
        //   3rd: 30

    }

    { // inline を指定

        u := struct {
            Name  string
            Age   int
            Score map[string]int `yaml:"score,inline"`
        }{
            Name:  "Tanaka",
            Age:   30,
            Score: map[string]int{"1st": 10, "2nd": 20, "3rd": 30},
        }

        data, err := yaml.Marshal(u)
        if err != nil {
            log.Fatal(err)
        }

        fmt.Println(string(data))
        // name: Tanaka
        // age: 30
        // 1st: 10
        // 2nd: 20
        // 3rd: 30
    }

    { // flow を指定

        u := struct {
            Name  string
            Age   int
            Score map[string]int `yaml:"score,flow"`
        }{
            Name:  "Tanaka",
            Age:   30,
            Score: map[string]int{"1st": 10, "2nd": 20, "3rd": 30},
        }

        data, err := yaml.Marshal(u)
        if err != nil {
            log.Fatal(err)
        }

        fmt.Println(string(data))
        // name: Tanaka
        // age: 30
        // score: {1st: 10, 2nd: 20, 3rd: 30}
    }
}






以上の内容はhttps://golang.hateblo.jp/entry/2018/11/08/183555より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14