LoginSignup
1
1

【Go言語】意図的に0や空文字を使うとvalidatorが反応してしまう問題

Last updated at Posted at 2023-12-19

TL;DR

必須チェックを行う場合は構造体の変数をポインタ型にすることで0や空文字を使ってもバリデーションエラーを返さないようにできます。

type Human struct {
	Name *string `validate:"required"`
	Age  *int    `validate:"required"`
}

遭遇した問題

Goで構造体をバリデーションを行っていたとき、Ageに0を入れるとバリデーションエラーを返してしまう問題に遭遇しました。

type Human struct {
	Name string `validate:"required"`
	Age  int    `validate:"required"`
}

func main() {
	h := Human{
		Name: "Taro",
		Age:  0, // 意図的に0を入れている
	}
	if err := validator.New().Struct(h); err != nil {
		var ve validator.ValidationErrors
		if errors.As(err, &ve) {
			for _, fe := range ve {
				fmt.Printf("フィールド %s が %s 違反です(値:%v)\n", fe.Field(), fe.Tag(), fe.Value())
        // フィールド Age が required 違反です(値:0)
			}
		}
	}
}

原因

Goが変数に与える初期値により、validatorが「値が与えられたのか、そうでなかったのか」を判別できなくなるから。

Goの変数の初期値について

Goの変数は宣言時に初期値が与えられます。初期値は型によって異なりますが、以下のようになっています。

  • 数値型: 0
  • bool型: false
  • string型: ""

validatorと初期値の問題

validatorを使って構造体のバリデーションを行うときに、0や""などの値を意図的に入れたとしても、validatorは「値が与えられなかった」と勘違いしてしまいます。

そのため、意図的に0を入れていたのにも関わらず、バリデーションエラーが返ってきたわけです。

解決策

構造体の変数をポインタ型にすることで0や空文字を使ってもバリデーションエラーを返さないようにできます。

type Human struct {
	Name *string `validate:"required"`
	Age  *int    `validate:"required"`
}

ポインタにすると値が未設定のとき値はnilになります。そのため、意図的に0や空文字を与えたか、そうでないかを判別できるようになります。

var i int
var j *int

fmt.Printf("%v\n", i)
fmt.Printf("%v\n", j)

// 0
// <nil>

そのため以下の場合、Ageに0を与えてもバリデーションエラーは返ってきません。

type Human struct {
	Name *string `validate:"required"`
	Age  *int    `validate:"required"`
}

func main() {
	h := Human{
		Name: "Taro",
		Age:  0,
	}
	if err := validator.New().Struct(h); err != nil {
		var ve validator.ValidationErrors
		if errors.As(err, &ve) {
			for _, fe := range ve {
				fmt.Printf("フィールド %s が %s 違反です(値:%v)\n", fe.Field(), fe.Tag(), fe.Value())
			}
		}
	}
}

参考

実用Go言語 : https://www.oreilly.co.jp/books/9784873119694/

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1