npx skills add https://github.com/0xbigboss/claude-code --skill go-best-practices类型在实现之前定义契约。遵循以下工作流程:
使用 Go 的类型系统在编译时防止无效状态。
领域模型的结构体:
// 首先定义数据模型
type User struct {
ID UserID
Email string
Name string
CreatedAt time.Time
}
type CreateUserRequest struct {
Email string
Name string
}
// 函数遵循类型定义
func CreateUser(req CreateUserRequest) (*User, error) {
// 实现
}
领域原语的自定义类型:
// 不同的类型防止混淆 ID
type UserID string
type OrderID string
func GetUser(id UserID) (*User, error) {
// 编译器阻止在此处传递 OrderID
}
func NewUserID(raw string) UserID {
return UserID(raw)
}
// 方法将行为附加到类型
func (id UserID) String() string {
return string(id)
}
行为契约的接口:
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
// 定义你需要的,而不是你拥有的
type Reader interface {
Read(p []byte) (n int, err error)
}
type UserRepository interface {
GetByID(ctx context.Context, id UserID) (*User, error)
Save(ctx context.Context, user *User) error
}
// 接受接口,返回结构体
func ProcessInput(r Reader) ([]byte, error) {
return io.ReadAll(r)
}
使用 iota 的枚举:
type Status int
const (
StatusActive Status = iota + 1
StatusInactive
StatusPending
)
func (s Status) String() string {
switch s {
case StatusActive:
return "active"
case StatusInactive:
return "inactive"
case StatusPending:
return "pending"
default:
return fmt.Sprintf("Status(%d)", s)
}
}
// switch 中的穷尽处理
func ProcessStatus(s Status) (string, error) {
switch s {
case StatusActive:
return "processing", nil
case StatusInactive:
return "skipped", nil
case StatusPending:
return "waiting", nil
default:
return "", fmt.Errorf("unhandled status: %v", s)
}
}
灵活构造的函数式选项:
type ServerOption func(*Server)
func WithPort(port int) ServerOption {
return func(s *Server) {
s.port = port
}
}
func WithTimeout(d time.Duration) ServerOption {
return func(s *Server) {
s.timeout = d
}
}
func NewServer(opts ...ServerOption) *Server {
s := &Server{
port: 8080, // 合理的默认值
timeout: 30 * time.Second,
}
for _, opt := range opts {
opt(s)
}
return s
}
// 用法:NewServer(WithPort(3000), WithTimeout(time.Minute))
嵌入以实现组合:
type Timestamps struct {
CreatedAt time.Time
UpdatedAt time.Time
}
type User struct {
Timestamps // 嵌入 - User 拥有 CreatedAt, UpdatedAt
ID UserID
Email string
}
优先使用包内较小的文件:每个文件处理一个类型或关注点。当文件处理多个不相关的类型或超过约 300 行时进行拆分。将测试放在与实现同级的 _test.go 文件中。包边界定义 API;内部组织是灵活的。
sort.Slice、迭代器)。fmt.Errorf 和 %w 包装返回带有上下文的错误。这保留了用于调试的错误链。switch 语句中的所有分支;包含一个返回错误的 default 情况。穷尽处理可防止静默错误。context.Context 传递给具有显式超时的外部调用。失控的请求会导致级联故障。panic;优先返回错误。Panic 会使程序崩溃。未实现逻辑的显式失败:
func buildWidget(widgetType string) (*Widget, error) {
return nil, fmt.Errorf("buildWidget not implemented for type: %s", widgetType)
}
使用上下文包装错误以保留链:
out, err := client.Do(ctx, req)
if err != nil {
return nil, fmt.Errorf("fetch widget failed: %w", err)
}
return out, nil
带有默认错误的穷尽 switch:
func processStatus(status string) (string, error) {
switch status {
case "active":
return "processing", nil
case "inactive":
return "skipped", nil
default:
return "", fmt.Errorf("unhandled status: %s", status)
}
}
使用 slog 的结构化日志记录:
import "log/slog"
var log = slog.With("component", "widgets")
func createWidget(name string) (*Widget, error) {
log.Debug("creating widget", "name", name)
widget := &Widget{Name: name}
log.Debug("created widget", "id", widget.ID)
return widget, nil
}
os.Getenv 分散在整个代码中。类型化的配置结构体:
type Config struct {
Port int
DatabaseURL string
APIKey string
Env string
}
func LoadConfig() (*Config, error) {
dbURL := os.Getenv("DATABASE_URL")
if dbURL == "" {
return nil, fmt.Errorf("DATABASE_URL is required")
}
apiKey := os.Getenv("API_KEY")
if apiKey == "" {
return nil, fmt.Errorf("API_KEY is required")
}
port := 3000
if p := os.Getenv("PORT"); p != "" {
var err error
port, err = strconv.Atoi(p)
if err != nil {
return nil, fmt.Errorf("invalid PORT: %w", err)
}
}
return &Config{
Port: port,
DatabaseURL: dbURL,
APIKey: apiKey,
Env: getEnvOrDefault("ENV", "development"),
}, nil
}
每周安装次数
133
代码仓库
GitHub 星标数
37
首次出现时间
2026年1月20日
安全审计
安装于
codex109
opencode106
gemini-cli104
claude-code101
github-copilot100
cursor89
Types define the contract before implementation. Follow this workflow:
Use Go's type system to prevent invalid states at compile time.
Structs for domain models:
// Define the data model first
type User struct {
ID UserID
Email string
Name string
CreatedAt time.Time
}
type CreateUserRequest struct {
Email string
Name string
}
// Functions follow from the types
func CreateUser(req CreateUserRequest) (*User, error) {
// implementation
}
Custom types for domain primitives:
// Distinct types prevent mixing up IDs
type UserID string
type OrderID string
func GetUser(id UserID) (*User, error) {
// Compiler prevents passing OrderID here
}
func NewUserID(raw string) UserID {
return UserID(raw)
}
// Methods attach behavior to the type
func (id UserID) String() string {
return string(id)
}
Interfaces for behavior contracts:
// Define what you need, not what you have
type Reader interface {
Read(p []byte) (n int, err error)
}
type UserRepository interface {
GetByID(ctx context.Context, id UserID) (*User, error)
Save(ctx context.Context, user *User) error
}
// Accept interfaces, return structs
func ProcessInput(r Reader) ([]byte, error) {
return io.ReadAll(r)
}
Enums with iota:
type Status int
const (
StatusActive Status = iota + 1
StatusInactive
StatusPending
)
func (s Status) String() string {
switch s {
case StatusActive:
return "active"
case StatusInactive:
return "inactive"
case StatusPending:
return "pending"
default:
return fmt.Sprintf("Status(%d)", s)
}
}
// Exhaustive handling in switch
func ProcessStatus(s Status) (string, error) {
switch s {
case StatusActive:
return "processing", nil
case StatusInactive:
return "skipped", nil
case StatusPending:
return "waiting", nil
default:
return "", fmt.Errorf("unhandled status: %v", s)
}
}
Functional options for flexible construction:
type ServerOption func(*Server)
func WithPort(port int) ServerOption {
return func(s *Server) {
s.port = port
}
}
func WithTimeout(d time.Duration) ServerOption {
return func(s *Server) {
s.timeout = d
}
}
func NewServer(opts ...ServerOption) *Server {
s := &Server{
port: 8080, // sensible defaults
timeout: 30 * time.Second,
}
for _, opt := range opts {
opt(s)
}
return s
}
// Usage: NewServer(WithPort(3000), WithTimeout(time.Minute))
Embed for composition:
type Timestamps struct {
CreatedAt time.Time
UpdatedAt time.Time
}
type User struct {
Timestamps // embedded - User has CreatedAt, UpdatedAt
ID UserID
Email string
}
Prefer smaller files within packages: one type or concern per file. Split when a file handles multiple unrelated types or exceeds ~300 lines. Keep tests in _test.go files alongside implementation. Package boundaries define the API; internal organization is flexible.
sort.Slice, iterators).fmt.Errorf and %w for wrapping. This preserves the error chain for debugging.switch statements; include a default case that returns an error. Exhaustive handling prevents silent bugs.context.Context to external calls with explicit timeouts. Runaway requests cause cascading failures.panic for truly unrecoverable situations; prefer returning errors. Panics crash the program.Explicit failure for unimplemented logic:
func buildWidget(widgetType string) (*Widget, error) {
return nil, fmt.Errorf("buildWidget not implemented for type: %s", widgetType)
}
Wrap errors with context to preserve the chain:
out, err := client.Do(ctx, req)
if err != nil {
return nil, fmt.Errorf("fetch widget failed: %w", err)
}
return out, nil
Exhaustive switch with default error:
func processStatus(status string) (string, error) {
switch status {
case "active":
return "processing", nil
case "inactive":
return "skipped", nil
default:
return "", fmt.Errorf("unhandled status: %s", status)
}
}
Structured logging with slog:
import "log/slog"
var log = slog.With("component", "widgets")
func createWidget(name string) (*Widget, error) {
log.Debug("creating widget", "name", name)
widget := &Widget{Name: name}
log.Debug("created widget", "id", widget.ID)
return widget, nil
}
os.Getenv scattered throughout code.Typed config struct:
type Config struct {
Port int
DatabaseURL string
APIKey string
Env string
}
func LoadConfig() (*Config, error) {
dbURL := os.Getenv("DATABASE_URL")
if dbURL == "" {
return nil, fmt.Errorf("DATABASE_URL is required")
}
apiKey := os.Getenv("API_KEY")
if apiKey == "" {
return nil, fmt.Errorf("API_KEY is required")
}
port := 3000
if p := os.Getenv("PORT"); p != "" {
var err error
port, err = strconv.Atoi(p)
if err != nil {
return nil, fmt.Errorf("invalid PORT: %w", err)
}
}
return &Config{
Port: port,
DatabaseURL: dbURL,
APIKey: apiKey,
Env: getEnvOrDefault("ENV", "development"),
}, nil
}
Weekly Installs
133
Repository
GitHub Stars
37
First Seen
Jan 20, 2026
Security Audits
Gen Agent Trust HubFailSocketPassSnykPass
Installed on
codex109
opencode106
gemini-cli104
claude-code101
github-copilot100
cursor89
Perl 5.36+ 现代开发模式与最佳实践 | 构建健壮可维护应用程序指南
952 周安装
ISO 13485内部审计专家指南:医疗器械QMS审计计划、执行与不符合项管理
153 周安装
TikTok广告优化全攻略:从创意、技术到效果分析的完整检查清单与评分系统
154 周安装
Odoo 升级助手 v4.0:自动化模块升级,解决版本兼容性问题
154 周安装
债券相对价值分析工具 - 固定收益利差分解与情景分析 | 金融科技AI插件
154 周安装
Web设计规范检查工具 - 自动验证代码符合界面指南 | Cal.com开源
154 周安装
SwiftUI 导航 API 参考:从 NavigationStack 到 iOS 26 液态玻璃设计完整指南
154 周安装