よくある質問
値とポインタ、どちらを渡せば?
どちらでも動きます。Check は interface{} を受け取り——ポインタは 自動的に解参照され、nil は「バリデートするものがない」と扱われて パニックしません。
govalid.Check(form) // 値
govalid.Check(&form) // ポインタポインタレシーバーの Validate() error を発火させたい場合はポインタ を渡してください。値レシーバーはどちらでも発火します。
フィールドをオプショナルだがフォーマットは検査したい場合は?
required ルールを外してください。フォーマット系チェッカー (email、mobile など)は空文字を有効として扱います:
type Form struct {
Backup string `valid:"email"` // 空 OK、設定されたら有効でなければならない
}bool が true であることを必須にするには?
required を使います。govalid の required は bool フィールドを 「非ゼロ」、つまり true と解釈します:
type Terms struct {
Accepted bool `valid:"required" label:"服务条款"`
}スライスを要素ごとにバリデートするには?
構造体のスライスにし、その構造体のフィールドにタグを付けます。 govalid は要素を自動で走査します:
type Item struct {
Name string `valid:"required"`
}
type Order struct {
Items []Item `valid:"required"`
}[]*Item(ポインタのスライス)の要素ごとバリデーションは今日のとこ ろ未対応です——[]Item を使うか手動でループしてください。
フィールドの元のエラー型を取り戻すには?
現在 *ErrContext は Unwrap を公開していないので、errors.As 経由 での型アサーションは Validate() メソッドの裏のエラーには届きません。 よくある回避策は 2 つ:
- 必要なデータをエラー文字列にエンコードする。
Validate()から副チャネルでエラーを返す(例:フォーム構造体上に 載せる)。
これは既知の粗いところです——困っていたら issue を立ててください。
なぜ min/max は bool フィールドを無視するのか?
数値種別(符号付き/符号なし int と float)にしか作用しないからです。 ブーリアンには required か list:true,false を選んでください。
なぜ equal は文字列で比較するのか?
equal は両辺を fmt.Sprintf("%v", …) で文字列化します。これにより 異種タイプ間(int vs string)でも動きますが、微妙な型不一致を 拾えなくなる代わりです。厳密な型相等が必要ならカスタムチェッカーを 書いてください。
同じ構造体で複数のバリデーターを実行できますか?
できます。呼び出し側から見て govalid はステートレスです——Check は 同じ値で繰り返し呼び出せます。各呼び出しで構造体を新たに走査します。
チェッカーマップのホットリロードで安全?
Checkers、errorTemplateChinese などの読み込みは書き手が無い限り 並行安全です。実行時に変更しなければならない場合、自前のミューテッ クスで包み、入れ替え中は飛んでいるトラフィックを止めてください。