golangでYAMLファイルを読み込んで構造体に入れる

使い方がかなり特殊だったのでメモ
(ドキュメントには書いてありますが…)

goyamlでは、YAMLの構造とGoの構造体の構造を揃えておくと、
データを構造体にセットした状態で読み込むことが出来ます。

特にGoでは構造体を使わない場合、interfaceへの変換を書きまくる事になるので、
できる限り構造体を利用した方がお勧めです。

以下のように、YAMLのキーとGoの構造体の名前を揃えることで、
YAMLから構造体に直接データを代入できます。

type Data struct {
  UserId      int
  UserName    string `yaml:"user_name"`
  Follownum   int    `yaml:"followNum"`
  MessageText string
  invaliddata string
}
userid: 123
user_name: name
followNum: 42
messageText: text
invaliddata: data

後述するコードでYAMLを読み込むと、出力は以下の通りになります、
=> {123 name 42 }

UserIdに123、UserNameにname、Follownumに42、
MessageTextとinvaliddataは空になっています。

構造体とYAMLの対応付け仕様

特に指定をしない場合、構造体の変数名に対応するキーと対応付けられます。
対応するキーは以下のような仕様になっているようです。

  • 指定が無い場合、変数名を全て小文字にしたYAMLのキーと対応付ける
    • UserIdはuseridと対応付けられます
  • 後述する方法で明示的な指定をしない限り、YAMLのキーは全て小文字のみ受け付けます
    • messageTextはダメで、messagetextでないといけません
  • 構造体のメンバは大文字から始まる
    • そのため、invaliddataにはデータ入っていません
    • 大文字から始まれば、途中が大文字でも大丈夫です
      • UserIdはuseridと対応付けられます
    • 途中を大文字にしても、全て小文字のキーを見に行きます
      • MessageTextはmessagetextと対応付けられます
  • 明示的に対応を設定することもできる
    • UserNameをuser_nameと対応付けたり(通常はUser_Nameというメンバ変数にしないといけない)
    • Follownumの変数をfollowNumと対応付けるなど、上記の制限は無くなる

暗黙のルールが多いですが、それさえ理解すればかなり簡単に書くことができます。

サンプルコード

package main

import (
  "gopkg.in/yaml.v2"
  "io/ioutil"
  "fmt"
)

type Data struct {
  UserId      int
  UserName    string `yaml:"user_name"`
  Follownum   int     `yaml:"followNum"`
  MessageText string
  invaliddata string
}

func main() {
  buf, err := ioutil.ReadFile("test.yml")
  if err != nil {
    panic(err)
  }

  var d Data
  err = yaml.Unmarshal(buf, &d)
  fmt.Println(d)
}