Token导航 LogoToken导航

Agent Skill · 开发

go-web-expert(去网络专家)

go-web-expert 用于记录任务执行中的错误、用户纠正、经验和能力缺口,适合在 OpenClaw 中希望让 Agent 持续沉淀问题、修正和最佳实践时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

go-web-expert 是开发类 Agent Skill,可用宿主为 OpenClaw,通过ClawHub获取,权限为需要联网;许可证为 MIT-0,第三方扫描已通过,按安装量在开发类的 21,746 个 Skill 里排第 6,446。

总安装 4,703周安装 194GitHub Stars 公开资料未说明下载 1,536核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
MIT-0
版本
2.3.1

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:go-web-expert(去网络专家)
来源仓库:https://github.com/anderskev/go-web-expert
安装命令:
openclaw skills install go-web-expert
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 OpenClaw 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

ClawHubOpenClaw
openclaw skills install go-web-expert

这个 Skill 是做什么的

开发类 Skill 面向写代码、改代码和排查问题,一般会读写仓库文件,部分还会执行构建或测试命令。

go-web-expert 强制实施零全局状态、显式错误处理与文档规范的 Go Web 开发准则。适合在 OpenClaw 中指导团队编写可测试、易维护的后端服务时使用。通过 clawhub 安装,可作为 CI/CD 流水线中的代码审查规则集。使用前应统一团队编码风格,避免混合不同约定造成冲突。

最佳实践需结合具体业务复杂度灵活裁剪。

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 OpenClaw;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 openclaw skills install go-web-expert;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要需要联网,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

go-web-expert 怎么安装?

在终端执行 openclaw skills install go-web-expert。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

go-web-expert 支持哪些 AI 工具?

公开资料标注支持 OpenClaw。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

go-web-expert 需要什么权限?

权限级别是需要联网。该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

go-web-expert 是免费的吗?

来源标注的许可证是 MIT-0。本站不代收任何费用,也不托管安装包;能否商用、要不要署名,以许可证原文为准。

go-web-expert 用的人多吗?

公开数据是累计安装 4,703 次,近一周安装 194 次,下载 1,536 次。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

go-web-expert 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 专注 OpenClaw 一种宿主,触发方式和使用习惯不用来回切换。
  • 许可证明确为 MIT-0,商用和分发边界好判断。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 OpenClaw,想直接扩展它能力的人。
  • 需要处理开发类任务、又不想每次都手写提示词的人。
  • 需要许可证清楚、并且有第三方扫描结果的团队项目。

不太适合

  • 需要厂商级技术支持和 SLA 的生产系统。

开发类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
skill-vetter

技能审查员 · OpenClaw

8,779,018986操作浏览器MIT-0通过
ontology

本体论 · OpenClaw

6,636,960576只读MIT-0通过
entra-app-registration

内部应用程序注册 · Codex、Claude

6,631,872764接触敏感数据未明确通过
entra-app-registration

内部应用程序注册 · Codex、Claude

3,757,680201接触敏感数据未明确通过
nano-banana-pro

纳米香蕉专业版 · OpenClaw

3,526,898364接触敏感数据MIT-0有提醒
go-web-expert

去网络专家 · 本页

4,703—需要联网MIT-0通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

name
go-web-expert
description
Comprehensive Go web development persona enforcing zero global state, explicit error handling, input validation, testability, and documentation conventions. Use when building Go web applications to ensure production-quality code from the start.

Go Web Expert System

Five non-negotiable rules for production-quality Go web applications. Every handler, every service, every line of code must satisfy all five.

Quick Reference

TopicReference
Validation tags, custom validators, nested structs, error formattingreferences/validation.md
httptest patterns, middleware testing, integration tests, fixturesreferences/testing-handlers.md

Rules of Engagement

#RuleOne-Liner
1Zero Global StateAll handlers are methods on a struct; no package-level var for mutable state
2Explicit Error HandlingEvery error is checked, wrapped with fmt.Errorf("doing X: %w", err)
3Validation FirstAll incoming JSON validated with go-playground/validator at the boundary
4TestabilityEvery handler has a _test.go using httptest with table-driven tests
5DocumentationEvery exported symbol has a Go doc comment starting with its name

Hard gates (new HTTP handler)

Apply in order. Do not treat the next step as done until the Pass when for the current step is satisfied (objective evidence on disk or in test output—not “I checked mentally”).

  1. Dependencies (Rule 1) — Pass when: the handler is a method on a struct that holds every mutable dependency (db, logger, HTTP clients, caches); any new package-level var is only in the allowlist under What Is Allowed at Package Level. *Evidence:* constructor wires deps; no new forbidden globals from that list.
  1. Boundary (Rule 3) — Pass before calling service/domain code: Pass when: the request decodes into a tagged struct and validate.Struct (or equivalent) runs; invalid JSON and validation failures have defined HTTP status bodies (e.g. 400/422). *Evidence:* decode + validate.Struct appear in the handler; tests or manual run show 422/400 for bad input.
  1. Errors (Rule 2) — Pass when: no _ discards on the handler path; json.NewEncoder(w).Encode errors are handled; errors passed up or logged use wrapping (%w) or mapped AppError as this skill prescribes. *Evidence:* review the diff for ignored errors and bare return err without context where wrapping is required.
  1. Tests (Rule 4) — Pass when: a _test.go exists for the handler package and calls ServeHTTP with httptest, including at least one success case and one non-2xx case (validation, not found, or domain error). *Evidence:* test file path exists; go test for that package passes.
  1. Documentation (Rule 5) — Pass when: every new or changed exported identifier in the change has a doc comment whose first line starts with that identifier’s name. *Evidence:* go doc <pkg> or the IDE/doc preview shows summaries for new exports.

Rule 1: Zero Global State

All handlers must be methods on a server struct. No package-level var for databases, loggers, clients, or any mutable state.

// FORBIDDEN
var db *sql.DB
var logger *slog.Logger

func handleGetUser(w http.ResponseWriter, r *http.Request) {
    user, err := db.QueryRow(...)  // global state -- untestable, unsafe
}

// REQUIRED
type Server struct {
    db     *sql.DB
    logger *slog.Logger
    router *http.ServeMux
}

func (s *Server) handleGetUser(w http.ResponseWriter, r *http.Request) {
    user, err := s.db.QueryRow(...)  // explicit dependency
}

What Is Allowed at Package Level

  • Constants -- const maxPageSize = 100
  • Pure functions -- functions with no side effects that depend only on their arguments
  • Sentinel errors -- var ErrNotFound = errors.New("not found")
  • Validator instance -- var validate = validator.New() (stateless after init)

What Is Forbidden at Package Level

  • Database connections (*sql.DB, *pgxpool.Pool)
  • Loggers (*slog.Logger)
  • HTTP clients configured with timeouts or transport
  • Configuration structs read from environment
  • Caches, rate limiters, or any mutable shared resource

Constructor Pattern

func NewServer(db *sql.DB, logger *slog.Logger) *Server {
    s := &Server{
        db:     db,
        logger: logger,
        router: http.NewServeMux(),
    }
    s.routes()
    return s
}

func (s *Server) routes() {
    s.router.HandleFunc("GET /api/users/{id}", s.handleGetUser)
    s.router.HandleFunc("POST /api/users", s.handleCreateUser)
}

func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    s.router.ServeHTTP(w, r)
}

Rule 2: Explicit Error Handling

Never ignore errors. Every error must be wrapped with context describing what was being attempted when the error occurred.

// FORBIDDEN
result, _ := doSomething()
json.NewEncoder(w).Encode(data)  // error ignored

// REQUIRED
result, err := doSomething()
if err != nil {
    return fmt.Errorf("doing something for user %s: %w", userID, err)
}

if err := json.NewEncoder(w).Encode(data); err != nil {
    s.logger.Error("encoding response", "err", err, "request_id", reqID)
}

Error Wrapping Convention

Format: "<verb>ing <noun>: %w" -- lowercase, no period, provides call-chain context.

// Good wrapping -- each layer adds context
return fmt.Errorf("creating user: %w", err)
return fmt.Errorf("inserting user into database: %w", err)
return fmt.Errorf("hashing password for user %s: %w", email, err)

// Bad wrapping
return fmt.Errorf("error: %w", err)           // no context
return fmt.Errorf("Failed to create user: %w", err) // uppercase, verbose
return err                                      // no wrapping at all

Structured Error Type for HTTP APIs

type AppError struct {
    Code    int    `json:"-"`
    Message string `json:"error"`
    Detail  string `json:"detail,omitempty"`
}

func (e *AppError) Error() string {
    return fmt.Sprintf("%d: %s", e.Code, e.Message)
}

// Map domain errors to HTTP errors in one place
func handleError(w http.ResponseWriter, r *http.Request, err error) {
    var appErr *AppError
    if errors.As(err, &appErr) {
        writeJSON(w, appErr.Code, appErr)
        return
    }

    slog.Error("unhandled error",
        "err", err,
        "path", r.URL.Path,
    )
    writeJSON(w, 500, map[string]string{"error": "internal server error"})
}

Common Mistakes

// MISTAKE: not checking Close errors on writers
defer f.Close()  // at minimum, log Close errors for writable resources

// BETTER for writable resources:
defer func() {
    if err := f.Close(); err != nil {
        s.logger.Error("closing file", "err", err)
    }
}()

// OK for read-only resources where Close rarely fails:
defer resp.Body.Close()

Rule 3: Validation First

Use go-playground/validator for all incoming JSON. Validate at the boundary, trust internal data.

import "github.com/go-playground/validator/v10"

var validate = validator.New()

type CreateUserRequest struct {
    Name  string `json:"name"  validate:"required,min=1,max=100"`
    Email string `json:"email" validate:"required,email"`
    Age   int    `json:"age"   validate:"omitempty,gte=0,lte=150"`
}

func (s *Server) handleCreateUser(w http.ResponseWriter, r *http.Request) error {
    var req CreateUserRequest
    if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
        return &AppError{Code: 400, Message: "invalid JSON", Detail: err.Error()}
    }

    if err := validate.Struct(req); err != nil {
        return &AppError{Code: 422, Message: "validation failed", Detail: formatValidationErrors(err)}
    }

    // From here, req is trusted
    user, err := s.userService.Create(r.Context(), req.Name, req.Email)
    if err != nil {
        return fmt.Errorf("creating user: %w", err)
    }

    writeJSON(w, http.StatusCreated, user)
    return nil
}

Validation Error Formatting

func formatValidationErrors(err error) string {
    var msgs []string
    for _, e := range err.(validator.ValidationErrors) {
        msgs = append(msgs, fmt.Sprintf("field '%s' failed on '%s'", e.Field(), e.Tag()))
    }
    return strings.Join(msgs, "; ")
}

Validation Boundary Rule

  • Validate at the edge -- HTTP handlers, message consumers, CLI input
  • Trust internal data -- service layer receives already-validated types
  • Never validate twice -- if the handler validated, the service does not re-validate the same fields

See references/validation.md for custom validators, nested struct validation, slice validation, and cross-field validation.


Rule 4: Testability

Every handler must have a corresponding _test.go file using httptest. Test through the HTTP layer, not by calling handler methods directly.

func TestServer_handleGetUser(t *testing.T) {
    mockStore := &MockUserStore{
        GetUserFunc: func(ctx context.Context, id string) (*User, error) {
            if id == "123" {
                return &User{ID: "123", Name: "Alice"}, nil
            }
            return nil, ErrNotFound
        },
    }
    srv := NewServer(mockStore, slog.Default())

    tests := []struct {
        name       string
        path       string
        wantStatus int
        wantBody   string
    }{
        {
            name:       "existing user",
            path:       "/api/users/123",
            wantStatus: http.StatusOK,
            wantBody:   `"name":"Alice"`,
        },
        {
            name:       "not found",
            path:       "/api/users/999",
            wantStatus: http.StatusNotFound,
        },
    }

    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            req := httptest.NewRequest("GET", tt.path, nil)
            w := httptest.NewRecorder()

            srv.ServeHTTP(w, req)

            if w.Code != tt.wantStatus {
                t.Errorf("status = %d, want %d", w.Code, tt.wantStatus)
            }
            if tt.wantBody != "" && !strings.Contains(w.Body.String(), tt.wantBody) {
                t.Errorf("body = %q, want to contain %q", w.Body.String(), tt.wantBody)
            }
        })
    }
}

Key Testing Principles

  • Test through HTTP -- use httptest.NewRequest and httptest.NewRecorder, call srv.ServeHTTP
  • Interface-based mocks -- define narrow interfaces at the consumer, create mock implementations for tests
  • Table-driven tests -- one []struct with test cases, one t.Run loop
  • Error paths matter -- test 400s, 404s, 422s, and 500s, not just 200s
  • No global test state -- each test creates its own server with its own mocks

See references/testing-handlers.md for middleware testing, integration tests with real databases, file upload testing, and streaming response testing.


Rule 5: Documentation

Every exported function, type, method, and constant must have a Go doc comment following standard conventions.

// CreateUser creates a new user with the given name and email.
// It returns ErrDuplicateEmail if a user with the same email already exists.
func (s *UserService) CreateUser(ctx context.Context, name, email string) (*User, error) {
    // ...
}

// Server handles HTTP requests for the user API.
type Server struct {
    // ...
}

// NewServer creates a Server with the given dependencies.
// The logger must not be nil.
func NewServer(store UserStore, logger *slog.Logger) *Server {
    // ...
}

// ErrNotFound is returned when a requested resource does not exist.
var ErrNotFound = errors.New("not found")

Doc Comment Conventions

  • Start with the name -- // CreateUser creates... not // This function creates...
  • First sentence is the summary -- shown in go doc listings and IDE tooltips
  • Mention important error returns -- callers need to know which errors to check
  • Don't document the obvious -- // SetName sets the name adds no value
  • Document why, not what -- when behavior is non-obvious, explain the reasoning

Package Documentation

// Package user provides user management for the application.
// It handles creation, retrieval, and deletion of user accounts,
// with email uniqueness enforced at the database level.
package user

Cross-Cutting Concerns

The five rules reinforce each other. Here is how they interact.

Zero Global State Enables Testability

Because all dependencies are on the struct, tests can inject mocks:

// Production
srv := NewServer(realDB, prodLogger)

// Test
srv := NewServer(mockStore, slog.Default())

If db were a global var, tests would need to mutate package state, causing race conditions in parallel tests.

Validation First Simplifies Error Handling

When handlers validate at the boundary, the service layer can assume valid input. This means service-layer errors are always unexpected (database failures, network issues), and error handling becomes simpler:

func (s *UserService) Create(ctx context.Context, name, email string) (*User, error) {
    // No need to check if name is empty -- handler already validated
    user := &User{Name: name, Email: email}
    if err := s.store.Insert(ctx, user); err != nil {
        return nil, fmt.Errorf("inserting user: %w", err)
    }
    return user, nil
}

Documentation Makes Error Handling Discoverable

Doc comments that mention error returns tell callers what to handle:

// Delete removes a user by ID.
// It returns ErrNotFound if the user does not exist.
// It returns ErrHasActiveOrders if the user has unfinished orders.
func (s *UserService) Delete(ctx context.Context, id string) error {

Self-Review Checklist

Before considering any handler or service complete, verify all five rules:

Zero Global State

  • [ ] No package-level var for mutable state (db, logger, clients)
  • [ ] All handlers are methods on a struct
  • [ ] Dependencies injected through constructor

Explicit Error Handling

  • [ ] No _ ignoring returned errors
  • [ ] All errors wrapped with fmt.Errorf("doing X: %w", err)
  • [ ] json.NewEncoder(w).Encode(...) error checked or logged
  • [ ] Structured AppError used for HTTP error responses

Validation First

  • [ ] All request structs have validate tags
  • [ ] validate.Struct(req) called before any business logic
  • [ ] Validation errors return 422 with field-level detail
  • [ ] Service layer does not re-validate handler-validated data

Testability

  • [ ] _test.go file exists for every handler file
  • [ ] Tests use httptest.NewRequest and httptest.NewRecorder
  • [ ] Table-driven tests cover happy path and error paths
  • [ ] Mocks implement narrow interfaces, not concrete types

Documentation

  • [ ] Every exported function has a doc comment starting with its name
  • [ ] Error return values are documented
  • [ ] Package has a doc comment

When to Load References

Load validation.md when:

  • Adding new request types with validation tags
  • Creating custom validators
  • Validating nested structs, slices, or maps
  • Formatting validation errors for API responses

Load testing-handlers.md when:

  • Writing handler tests for the first time in a project
  • Testing middleware chains or authentication
  • Setting up integration tests with a real database
  • Testing file uploads or streaming responses

平台分布

OpenClaw

88.02%
按下载量换算1,352

安全审计

VirusTotal

未展示

ClawScan

通过

Static analysis

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills