読者です 読者をやめる 読者になる 読者になる

デフォルトの設定値に関する考察

go json

設定ファイルで明示的に指定されなかったパラメータに関する考察

問題

Go以外の多くの言語の場合, JSONを decodeしたとき、ハッシュ(map, dictinary)や
専用のオブジェクトが返ってくるので, そのオブジェクトを見れば明示的に指定されなかった
パラメータがわかります(ハッシュだとそのキーに対応する値がない等).


しかし Goの場合は, 構造体にバインドするという形になるので, 上記の方法では確かめる
ことはできません. さらにデフォルト値が設定されるので, 指定されなかったからデフォルト値
なのか, デフォルト値を指定されたのかの区別もつきません. 明示的に指定しなかった場合,
Goのデフォルト値とするならいいのですが, ある booleanパラメータを明示的に指定しなかった
場合は trueとしたいというような場合に困ります.

解決案

そのようなパラメータをポインタとして宣言する. そうすることで, 指定されない場合は
該当するパラメータが nilになるので, 指定されなかったことを判定することができる.

コード

具体例を示します. "use_vim"というパラメータが指定されなかった場合, それを
"true"として扱いたいとする例です.

package main

import (
	"encoding/json"
	"fmt"
	"log"
)

var sample = `
{
   "version": 4
}
`
type Config struct {
	Version int `json:"version"`
	UseVim *bool `json:"use_vim"`
}

func main() {
	var conf Config

	err := json.Unmarshal([]byte(sample), &conf)
	if err != nil {
		log.Fatal(err)
	}

	if conf.UseVim == nil {
		fmt.Println("Not set use_vim parameter")

		defaultUse := true
		conf.UseVim = &defaultUse
	} else {
		fmt.Println("Set use_vim parameter")
	}

	fmt.Printf("version=%d use_vim = %v\n", conf.Version, *conf.UseVim)
}


これを実行すると下記のような出力となります.

% go run default_value.go
Not set use_vim parameter
version=4 use_vim = true

use_vim パラメータが明示的に指定されていないことが判定できています.


次に JSONの内容を下記のように変更してみましょう(明示的にデフォルト値を
設定するようにする)

var sample = `
{
   "version": 4,
   "use_vim": false
}
`


結果は次のとおりです.

% go run default_value.go
Set use_vim parameter
version=4 use_vim = false

falseという bool型のデフォルト値を設定しましたが, 明示的に設定された
ことが判定できます.

おわりに

もっといい方法があるかもしれないので, 何かあれば教えていただければと
思います.