Skip to main content

zog-best-practices

Guides correct use of Zog, a Zod-inspired Go schema validation and parsing library with chainable schemas. Use when writing, reviewing, or debugging Go code that imports github.com/Oudwins/zog or mentions Zog schemas, Parse, Validate, zhttp, zjson, zenv, preprocessors, or Zog errors.

跳到安装

来源信息

仓库
Oudwins/zog
最近来源活动
2026年5月16日 18:52
检测到的 SKILL.md 语言
英语
星标
1,217
分支
41

安装方式

默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。

检查来源文件

决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。

正在显示 SKILL.md

SKILL.md
来源说明 · 只读预览
name
zog-best-practices
description
Guides correct use of Zog, a Zod-inspired Go schema validation and parsing library with chainable schemas. Use when writing, reviewing, or debugging Go code that imports github.com/Oudwins/zog or mentions Zog schemas, Parse, Validate, zhttp, zjson, zenv, preprocessors, or Zog errors.
# Zog Usage Use this skill when writing, reviewing, or debugging Go code that uses `github.com/Oudwins/zog`. ## 1. What Is Zog Zog is a Zod-inspired schema validation and parsing library for Go. The API is chainable and schema-first: define a schema, then either parse external input into a destination or validate an already-built Go value. Zog is useful for HTTP handlers, JSON input, environment variables, config, forms, and any place where Go values need validation plus optional coercion. ## 2. Defining A Schema Define reusable schemas with `z.Struct(z.Shape{...})` and primitive schema builders like `z.String()`, `z.Int()`, `z.Bool()`, `z.Time()`, `z.Slice(...)`, and `z.Ptr(...)`. ```go import z "github.com/Oudwins/zog" type User struct { Name string `json:"name" zog:"name"` Age int `json:"age" zog:"age"` } var userSchema = z.Struct(z.Shape{ "Name": z.String().Required().Min(3), "Age": z.Int().Required().GT(18), }) ``` Schema keys for structs are Go field names. Tags such as `json`, `zog`, or `env` map external input keys to those fields during parsing. ```go type User struct { Name string `json:"name" zog:"name"` } var userSchema = z.Struct(z.Shape{ "Name": z.String().Required(), // Go field name, not "name" }) ``` ## 3. Validating And Parsing Use `Parse(data, &dest)` when input is external or loosely typed. `Parse` can coerce values and writes into the destination. ```go var user User errs := userSchema.Parse(map[string]any{"name": "Ada", "age": "42"}, &user) if errs != nil { return errs } ``` Use `Validate(&value)` when the value is already a typed Go value and you only need validation. ```go user := User{Name: "Ada", Age: 42} errs := userSchema.Validate(&user) if errs != nil { return errs } ``` Zog returns `z.ZogIssueList`; `nil` means success. If relevant to the task, fetch https://zog.dev/errors/overview.md for error concepts, or https://zog.dev/errors/formatting.md for helpers like `z.Issues.Flatten`, `z.Issues.Treeify`, `z.Issues.Prettify`, and custom response formatting. ## 4. Supporting Packages - `zhttp`: parse `http.Request` JSON, form, multipart-after-manual-parse, or query input. - `zjson`: parse JSON readers into structs. - `zenv`: parse environment variables into typed config structs. - `i18n`: configure localized error messages. - `zconst`: constants for issue codes, types, and tags. ## 5. Common Mistakes ### Mistake: Using JSON Names As Struct Schema Keys Wrong: ```go var schema = z.Struct(z.Shape{ "name": z.String().Required(), }) ``` Correct: ```go type User struct { Name string `json:"name" zog:"name"` } var schema = z.Struct(z.Shape{ "Name": z.String().Required(), }) ``` ### Mistake: Forgetting That Fields Are Optional By Default Wrong: ```go var schema = z.Struct(z.Shape{ "Email": z.String().Email(), // missing input is allowed }) ``` Correct: ```go var schema = z.Struct(z.Shape{ "Email": z.String().Required().Email(), }) ``` ### Mistake: Passing Non-Pointers To Execution Methods Wrong: ```go var user User errs := userSchema.Parse(data, user) errs := userSchema.Validate(user) ``` Correct: ```go var user User errs := userSchema.Parse(data, &user) errs := userSchema.Validate(&user) ``` ### Mistake: Treating Parse And Validate As Interchangeable Wrong: ```go // Validating an already-zero-valued struct cannot prove an absent field was present. var user User errs := userSchema.Validate(&user) ``` Correct: ```go // Use Parse for external input when presence and coercion matter. var user User errs := userSchema.Parse(input, &user) ``` ### Mistake: Blind Type Assertions In Preprocessors Wrong: ```go schema := z.Preprocess(func(data any, ctx z.Ctx) (any, error) { return strings.Split(data.(string), ","), nil }, z.Slice(z.String())) ``` Correct: ```go schema := z.Preprocess(func(data any, ctx z.Ctx) (any, error) { s, ok := data.(string) if !ok { return nil, fmt.Errorf("expected string but got %T", data) } return strings.Split(s, ","), nil }, z.Slice(z.String())) ``` ## 6. Best Practices ### Reuse Schemas Instead Of Rebuilding Them Prefer global or package-level schemas for hot paths such as HTTP requests. ```go var createUserSchema = z.Struct(z.Shape{ "Name": z.String().Required().Min(3), "Age": z.Int().Required().GT(18), }) func handleCreateUser(w http.ResponseWriter, r *http.Request) { var user User errs := createUserSchema.Parse(zhttp.Request(r), &user) _ = errs } ``` If a schema must be built dynamically and performance matters, consider `sync.Pool` to reuse schemas. ### Prefer Validate When Coercion Is Not Needed `Validate` is faster than `Parse` when you already have a typed Go value. ```go func saveUser(user *User) error { if errs := userSchema.Validate(user); errs != nil { return fmt.Errorf("invalid user: %v", z.Issues.Flatten(errs)) } return nil } ``` ### Collect Issues After Using Them On Hot Paths Issue generation is allocation-heavy. After formatting or logging issues, collect them for reuse. ```go errs := userSchema.Validate(&user) if errs != nil { defer z.Issues.Collect(errs) return z.Issues.Flatten(errs) } ``` ### Wrap Reusable Custom Tests Use helper functions for repeated custom validation so messages and options stay consistent. ```go func StrongPassword(opts ...z.TestOption) z.Test[*string] { return z.TestFunc("strong_password", func(password *string, ctx z.Ctx) bool { return len(*password) >= 12 }, opts...) } var schema = z.Struct(z.Shape{ "Password": z.String().Required().Test(StrongPassword()), }) ``` ### Be Careful With Global Configuration The `conf` package changes behavior globally for all schemas. Prefer local schema options unless the whole application needs the change. ```go conf.Coercers.Float64 = func(data any) (any, error) { if str, ok := data.(string); ok && strings.Contains(str, ",") { return parseCommaFloat(str) } return conf.DefaultCoercers.Float64(data) } ``` ## References - Full API Reference: https://zog.dev/reference.md - Package docs: - `zhttp`: https://zog.dev/packages/zhttp.md - `zjson`: https://zog.dev/packages/zjson.md - `zenv`: https://zog.dev/packages/zenv.md - `i18n`: https://zog.dev/packages/i18n.md - `zconst`: https://zog.dev/packages/zconst.md - `internals`: https://zog.dev/packages/internals.md - When fetched docs pages contain relative links, follow them as markdown by using `https://zog.dev/{relative_path}.md`. ## SOP When using this skill, first understand the user's request and identify which Zog concepts or packages are involved. Fetch the reference or package docs above only when they are relevant or needed to avoid guessing. After gathering the necessary context, perform the user's request.
在 GitHub 查看