Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
// Good: Clear and directfuncGetUser(id string) (*User, error) {
user, err := db.FindUser(id)
if err != nil {
returnnil, fmt.Errorf("get user %s: %w", id, err)
}
return user, nil
}
// Bad: Overly cleverfuncGetUser(id string) (*User, error) {
returnfunc() (*User, error) {
if u, e := db.FindUser(id); e == {
u,
} {
, e
}
}()
}
nil
return
nil
else
return
nil
2. 让零值变得有用
设计类型时,应使其零值无需初始化即可立即使用。
// Good: Zero value is usefultype Counter struct {
mu sync.Mutex
count int// zero value is 0, ready to use
}
func(c *Counter) Inc() {
c.mu.Lock()
c.count++
c.mu.Unlock()
}
// Good: bytes.Buffer works with zero valuevar buf bytes.Buffer
buf.WriteString("hello")
// Bad: Requires initializationtype BadCounter struct {
counts map[string]int// nil map will panic
}
// In the consumer package, not the providerpackage service
// UserStore defines what this service needstype UserStore interface {
GetUser(id string) (*User, error)
SaveUser(user *User) error
}
type Service struct {
store UserStore
}
// Concrete implementation can be in another package// It doesn't need to know about this interface
使用类型断言实现可选行为
type Flusher interface {
Flush() error
}
funcWriteAndFlush(w io.Writer, data []byte)error {
if _, err := w.Write(data); err != nil {
return err
}
// Flush if supportedif f, ok := w.(Flusher); ok {
return f.Flush()
}
returnnil
}
包组织
标准项目布局
myproject/
├── cmd/
│ └── myapp/
│ └── main.go # Entry point
├── internal/
│ ├── handler/ # HTTP handlers
│ ├── service/ # Business logic
│ ├── repository/ # Data access
│ └── config/ # Configuration
├── pkg/
│ └── client/ # Public API client
├── api/
│ └── v1/ # API definitions (proto, OpenAPI)
├── testdata/ # Test fixtures
├── go.mod
├── go.sum
└── Makefile
包命名
// Good: Short, lowercase, no underscorespackage http
package json
package user
// Bad: Verbose, mixed case, or redundantpackage httpHandler
package json_parser
package userService // Redundant 'Service' suffix
避免包级状态
// Bad: Global mutable statevar db *sql.DB
funcinit() {
db, _ = sql.Open("postgres", os.Getenv("DATABASE_URL"))
}
// Good: Dependency injectiontype Server struct {
db *sql.DB
}
funcNewServer(db *sql.DB) *Server {
return &Server{db: db}
}
结构体设计
函数式选项模式
type Server struct {
addr string
timeout time.Duration
logger *log.Logger
}
type Option func(*Server)funcWithTimeout(d time.Duration) Option {
returnfunc(s *Server) {
s.timeout = d
}
}
funcWithLogger(l *log.Logger) Option {
returnfunc(s *Server) {
s.logger = l
}
}
funcNewServer(addr string, opts ...Option) *Server {
s := &Server{
addr: addr,
timeout: 30 * time.Second, // default
logger: log.Default(), // default
}
for _, opt := range opts {
opt(s)
}
return s
}
// Usage
server := NewServer(":8080",
WithTimeout(60*time.Second),
WithLogger(customLogger),
)
// Bad: Creates many string allocationsfuncjoin(parts []string)string {
var result stringfor _, p := range parts {
result += p + ","
}
return result
}
// Good: Single allocation with strings.Builderfuncjoin(parts []string)string {
var sb strings.Builder
for i, p := range parts {
if i > 0 {
sb.WriteString(",")
}
sb.WriteString(p)
}
return sb.String()
}
// Best: Use standard libraryfuncjoin(parts []string)string {
return strings.Join(parts, ",")
}
Go 工具集成
基本命令
# Build and run
go build ./...
go run ./cmd/myapp
# Testing
go test ./...
go test -race ./...
go test -cover ./...
# Static analysis
go vet ./...
staticcheck ./...
golangci-lint run
# Module management
go mod tidy
go mod verify
# Formatting
gofmt -w .
goimports -w .
// Bad: Naked returns in long functionsfuncprocess() (result int, err error) {
// ... 50 lines ...return// What is being returned?
}
// Bad: Using panic for control flowfuncGetUser(id string) *User {
user, err := db.Find(id)
if err != nil {
panic(err) // Don't do this
}
return user
}
// Bad: Passing context in structtype Request struct {
ctx context.Context // Context should be first param
ID string
}
// Good: Context as first parameterfuncProcessRequest(ctx context.Context, id string)error {
// ...
}
// Bad: Mixing value and pointer receiverstype Counter struct{ n int }
func(c Counter) Value() int { return c.n } // Value receiverfunc(c *Counter) Increment() { c.n++ } // Pointer receiver// Pick one style and be consistent