基本コンセプト
govalid を構成するプリミティブの短いツアー。これを一度読めば、残り のドキュメントは自明に感じられるはずです。
バリデーションループ
govalid.Check(v) は次のことを行います:
- リフレクションで
vを構造体値に解決。ポインタは自動的に解参照 され、nil はパニックではなく(nil, true)を返します。 - すべての公開フィールドを走査し、構造体フィールドと構造体スライス に再帰的に入ります。
validタグを持つフィールドごとにルールリストをパースし、その フィールドの値に対して各チェッカーを順に実行します。- チェッカーが返す
*ErrContextを集めます。 - その値(あるいはそのポインタ形)が
Validate() errorを実装して いれば最後にそれを呼び、非 nil のエラーを追加します。 (errs, len(errs) == 0)を返します。
タグ
govalid は 3 つの構造体タグを読みます。タグ名は govalid.RulesField、govalid.LabelField、govalid.MessageField で設定可能で、他のタグ名前空間と共存させられます。
| タグ | デフォルト | 役割 |
|---|---|---|
valid | — | ルールリスト、; 区切り。パラメータは : の後、複数のパラメータは , で区切ります。 |
label | フィールド名 | エラーメッセージで使う人が読みやすい名前。label-<lang> でロケール別の上書きが可能。 |
msg | — | そのフィールドの最初に失敗したルールのエラーメッセージ全体を上書き。 |
詳細は タグリファレンス を参照。
チェッカー
チェッカーは func(CheckerContext) *ErrContext です。govalid は パッケージレベルの Checkers map に 17 個を予め登録しています:
var Checkers = map[string]CheckFunc{
"required": required,
"min": min,
"max": max,
"minlen": minlen,
"maxlen": maxlen,
"alpha": alpha,
"alphanumeric": alphaNumeric,
"alphadash": alphaDash,
"username": userName,
"email": email,
"ipv4": ipv4,
"mobile": mobile,
"tel": tel,
"phone": phone,
"idcard": idCard,
"equal": equal,
"list": list,
}このマップ上のエントリは実行時に置換・拡張・削除できます。登録は Check を並行呼び出しする前に終えてください——マップ自体は同期 されていません。
CheckerContext
各チェッカーは完全に埋まったコンテキストを受け取ります。カスタム チェッカーも同じ形を使います:
type CheckerContext struct {
StructValue reflect.Value // 外側の構造体
FieldName string // Go フィールド名
FieldType reflect.Type
FieldValue interface{} // 検査対象の値
FieldLabel string // 解決済みラベル
TemplateLanguage language.Tag
Rule *rule // Rule.params を含む
}ErrContext
失敗は *ErrContext として返されます。error を実装しているので、 他の Go エラーと同じく包む・ログ出力する・返却することができます:
type ErrContext struct {
FieldName string
FieldLabel string
FieldValue interface{}
TemplateLanguage language.Tag
// ... 内部のテンプレート状態
}
func (e *ErrContext) Error() string通常は返ってきたスライスを単に走査します:
errs, ok := govalid.Check(form)
if !ok {
for _, e := range errs {
log.Printf("[%s] %s = %v: %s", e.FieldName, e.FieldLabel, e.FieldValue, e)
}
}テンプレートとロケール
各ルールには対応するメッセージテンプレートがあります。govalid は 2 つのロケール辞書(language.Chinese——デフォルト——と language.English)を同梱し、次の順序で解決します:
- 呼び出し時に渡されたロケール:
Check(v, language.English)。 - 未登録のロケール → デフォルトロケールにフォールバック。
- 未登録のルール → ロケールの
_unknownErrorTemplateにフォール バック。
SetMessageTemplates でテンプレートを上書き・拡張できます:
govalid.SetMessageTemplates(map[string]string{
"required": "must not be empty",
}, language.English)完全なライフサイクルは 国際化 を参照。
required の本当の意味
required は最も誤解されやすいルールです。govalid の定義は次の通り:
| フィールド種別 | required 失敗の条件 |
|---|---|
string、slice、array、map、chan | 長さが 0 |
pointer、interface、func | nil |
| その他の比較可能な種別 | 値がゼロ値と等しい |
| 比較不可能な構造体型 | スキップ(パニックしない) |
これは bool フィールドにとって重要です——bool 上の required は 「true でなければならない」を意味します。「どちらの値でもいい、 ただ存在せよ」が欲しいなら、ルールを外してください。