Skip to content

基本コンセプト

govalid を構成するプリミティブの短いツアー。これを一度読めば、残り のドキュメントは自明に感じられるはずです。

バリデーションループ

govalid.Check(v) は次のことを行います:

  1. リフレクションで v を構造体値に解決。ポインタは自動的に解参照 され、nil はパニックではなく (nil, true) を返します。
  2. すべての公開フィールドを走査し、構造体フィールドと構造体スライス に再帰的に入ります。
  3. valid タグを持つフィールドごとにルールリストをパースし、その フィールドの値に対して各チェッカーを順に実行します。
  4. チェッカーが返す *ErrContext を集めます。
  5. その値(あるいはそのポインタ形)が Validate() error を実装して いれば最後にそれを呼び、非 nil のエラーを追加します。
  6. (errs, len(errs) == 0) を返します。

タグ

govalid は 3 つの構造体タグを読みます。タグ名は govalid.RulesFieldgovalid.LabelFieldgovalid.MessageField で設定可能で、他のタグ名前空間と共存させられます。

タグデフォルト役割
validルールリスト、; 区切り。パラメータは : の後、複数のパラメータは , で区切ります。
labelフィールド名エラーメッセージで使う人が読みやすい名前。label-<lang> でロケール別の上書きが可能。
msgそのフィールドの最初に失敗したルールのエラーメッセージ全体を上書き。

詳細は タグリファレンス を参照。

チェッカー

チェッカーfunc(CheckerContext) *ErrContext です。govalid は パッケージレベルの Checkers map に 17 個を予め登録しています:

go
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

各チェッカーは完全に埋まったコンテキストを受け取ります。カスタム チェッカーも同じ形を使います:

go
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 エラーと同じく包む・ログ出力する・返却することができます:

go
type ErrContext struct {
    FieldName        string
    FieldLabel       string
    FieldValue       interface{}
    TemplateLanguage language.Tag
    // ... 内部のテンプレート状態
}

func (e *ErrContext) Error() string

通常は返ってきたスライスを単に走査します:

go
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)を同梱し、次の順序で解決します:

  1. 呼び出し時に渡されたロケール:Check(v, language.English)
  2. 未登録のロケール → デフォルトロケールにフォールバック。
  3. 未登録のルール → ロケールの _unknownErrorTemplate にフォール バック。

SetMessageTemplates でテンプレートを上書き・拡張できます:

go
govalid.SetMessageTemplates(map[string]string{
    "required": "must not be empty",
}, language.English)

完全なライフサイクルは 国際化 を参照。

required の本当の意味

required は最も誤解されやすいルールです。govalid の定義は次の通り:

フィールド種別required 失敗の条件
stringslicearraymapchan長さが 0
pointerinterfacefuncnil
その他の比較可能な種別値がゼロ値と等しい
比較不可能な構造体型スキップ(パニックしない)

これは bool フィールドにとって重要です——bool 上の required は 「true でなければならない」を意味します。「どちらの値でもいい、 ただ存在せよ」が欲しいなら、ルールを外してください。

MIT ライセンスのもとで公開されています。