パフォーマンス
govalid は純粋なリフレクションを使います——コード生成なし、ウォーム アップが必要なキャッシュもありません。以下の数字は Apple M1 Pro 上 の Go 1.26(go test -bench=. -benchmem)で計測したものです:
text
BenchmarkCheck_Simple_Valid-10 745966 1655 ns/op 1136 B/op 29 allocs/op
BenchmarkCheck_Simple_Invalid-10 713349 1644 ns/op 1160 B/op 31 allocs/op
BenchmarkCheck_Rich_Valid-10 262418 4748 ns/op 3216 B/op 73 allocs/op
BenchmarkParseRules-10 2852902 412 ns/op 520 B/op 14 allocs/op10 フィールドの "rich" 構造体(携帯番号、メール、長さ・範囲チェック を含む)に対して、コアあたり約 21 万バリデーション/秒、特別な 最適化なしです。
何にいくらかかるか
| 操作 | コスト |
|---|---|
タグごとの parseRules | ~400 ns / 14 allocs |
| チェッカー呼び出しごと | 各々 ns 単位、正規表現駆動のものは様々 |
| リフレクションでのフィールド走査 | アロケーションを支配 |
| ローカライズされたメッセージ描画 | 非自明テンプレートあたり 1 つの strings.NewReplacer |
ホットパスとコツ
- 正規表現は一度だけコンパイル。 組み込みパターンはパッケージ レベルの
regexp.MustCompileです。カスタムチェッカーも同じパター ンに従ってください。 - 構造体型を再利用。
parseRulesは単一のCheck呼び出し内で タグ毎のルールスライスをキャッシュしますが、呼び出し間ではキャッ シュしません。 - リクエスト毎に一度バリデート。 govalid は HTTP ハンドラー内で インラインに呼ぶのに十分速く、「バリデーションキャッシュ」は不要 です。
- 巨大な
list:ルールは避ける。 各エントリはfmt.Sprintf("%v", value)で比較されます。値が数十なら問題ない ですが、数千ならmap[string]struct{}を使うカスタムチェッカーへ 切り替えてください。
並行性
Check は並行に呼び出して安全です。ホットパス上のパッケージレベル 状態(Checkers、ロケールテンプレートマップ)は書き込みに対して 同期されていません——カスタムチェッカーとテンプレートはプロ グラム起動時、goroutine が Check をヒットし始める前に登録して ください。
ライブラリは go test -race 下で、共有構造体・独立構造体の両方の 並行ワークロードを実行済みです。
ファズカバレッジ
リポジトリには 2 つのファズターゲットが入っています:
sh
go test -run=^$ -fuzz=FuzzCheck -fuzztime=10s ./...
go test -run=^$ -fuzz=FuzzParseRules -fuzztime=10s ./...合計で 数百万回の実行 を経てパニックを起こしていません。クラッ シュする入力を見つけたらシードを添えて issue を立ててください。