Skip to main content 首页 创作者 inugamidev ultrathink-oss golang
golang Go patterns, concurrency with goroutines/channels, error handling, interfaces, and production-grade service architecture
跳到安装 Skills Marketplace 发现并探索由社区构建的 Agent Skills
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/InugamiDev/ultrathink-oss --skill golang命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
下载 Zip 下载中... 同仓库更多 Skills Unified design foundations — design system architecture, tokens, component specs, visual principles, creative vision, figma integration, plus brand design system loader (66 real brands via DESIGN.md). Absorbs design, design-system, design-systems, design-principles, design-router, creative-vision, figma, design-md.
Render, summarize, and present markdown documents and structured content in multiple output modes
Ultra UI skill - combines Google's DESIGN.md spec (machine-readable design tokens) with the ui-ux-pro-max knowledge base (91 styles, 161 palettes, 73 font pairings, 161 products, 104 UX guidelines, 25 chart types). Generates lint-clean DESIGN.md files, validates token references and WCAG contrast, exports Tailwind/DTCG tokens, and diffs design systems version-over-version.
name golang description Go patterns, concurrency with goroutines/channels, error handling, interfaces, and production-grade service architecture layer domain category backend triggers ["golang","go lang","goroutine","go concurrency","go interface","go error handling"] inputs ["Go application requirements","Concurrency design needs","Service architecture specifications"] outputs ["Idiomatic Go implementations","Concurrency patterns","Production deployment configurations"] linksTo ["microservices","postgresql","redis","message-queues","graphql","websockets"] linkedFrom ["error-handling","logging","testing"] preferredNextSkills ["postgresql","redis","microservices"] fallbackSkills ["rust","nodejs"] riskLevel low memoryReadPolicy selective memoryWritePolicy none sideEffects []
Go Domain Skill
Purpose
Provide expert-level guidance on writing idiomatic Go code, including concurrency patterns with goroutines and channels, error handling, interface design, testing, and production-grade service architecture.
Key Patterns
1. Project Structure
myservice/
├── cmd/
│ └── server/
│ └── main.go # Entry point
├── internal/
│ ├── domain/
│ │ ├── user.go # Domain types
│ │ └── errors.go # Domain errors
│ ├── service/
│ │ ├── user.go # Business logic
│ │ └── user_test.go
│ ├── repository/
│ │ ├── postgres/
│ │ │ └── user.go # Postgres implementation
│ │ └── repository.go # Interface definitions
│ ├── handler/
│ │ ├── user.go # HTTP handlers
│ │ └── middleware.go
│ └── config/
│ └── config.go
├── pkg/ # Reusable packages (if any)
├── migrations/
├── go.mod
├── go.sum
└── Makefile
2. Interface Design
package repository
import "context"
type UserReader interface {
GetUser(ctx context.Context, id string ) (*domain.User, error )
ListUsers(ctx context.Context, opts ListOptions) ([]domain.User, error )
}
type UserWriter interface {
CreateUser(ctx context.Context, u *domain.User) error
UpdateUser(ctx context.Context, u *domain.User) error
DeleteUser(ctx context.Context, id string ) error
}
type UserRepository interface {
UserReader
UserWriter
}
type UserService struct {
repo UserRepository
cache Cache
logger *slog.Logger
}
func NewUserService (repo UserRepository, cache Cache, logger *slog.Logger) *UserService {
&UserService{repo: repo, cache: cache, logger: logger}
}
return
3. Error Handling package domain
import (
"errors"
"fmt"
)
var (
ErrNotFound = errors.New("not found" )
ErrAlreadyExists = errors.New("already exists" )
ErrUnauthorized = errors.New("unauthorized" )
ErrForbidden = errors.New("forbidden" )
)
type AppError struct {
Code string
Message string
Err error
}
func (e *AppError) Error() string {
if e.Err != nil {
return fmt.Sprintf("%s: %s: %v" , e.Code, e.Message, e.Err)
}
return fmt.Sprintf("%s: %s" , e.Code, e.Message)
}
func (e *AppError) Unwrap() error {
return e.Err
}
func (s *UserService) GetUser(ctx context.Context, id string ) (*User, error ) {
user, err := s.repo.GetUser(ctx, id)
if err != nil {
if errors.Is(err, ErrNotFound) {
return nil , fmt.Errorf("user %s: %w" , id, err)
}
return nil , fmt.Errorf("getting user %s: %w" , id, err)
}
return user, nil
}
func (h *UserHandler) GetUser(w http.ResponseWriter, r *http.Request) {
user, err := h.service.GetUser(r.Context(), chi.URLParam(r, "id" ))
if err != nil {
switch {
case errors.Is(err, domain.ErrNotFound):
writeError(w, http.StatusNotFound, err.Error())
case errors.Is(err, domain.ErrForbidden):
writeError(w, http.StatusForbidden, "access denied" )
default :
h.logger.Error("unexpected error" , "error" , err)
writeError(w, http.StatusInternalServerError, "internal error" )
}
return
}
writeJSON(w, http.StatusOK, user)
}
4. Concurrency Patterns
func processItems (ctx context.Context, items []Item, workers int ) ([]Result, error ) {
var (
wg sync.WaitGroup
mu sync.Mutex
results = make ([]Result, 0 , len (items))
errs []error
sem = make (chan struct {}, workers)
)
for _, item := range items {
wg.Add(1 )
sem <- struct {}{}
go func (item Item) {
defer wg.Done()
defer func () { <-sem }()
result, err := processItem(ctx, item)
mu.Lock()
defer mu.Unlock()
if err != nil {
errs = append (errs, err)
} else {
results = append (results, result)
}
}(item)
}
wg.Wait()
return results, errors.Join(errs...)
}
import "golang.org/x/sync/errgroup"
func fetchAll (ctx context.Context, urls []string ) ([]Response, error ) {
g, ctx := errgroup.WithContext(ctx)
g.SetLimit(10 )
responses := make ([]Response, len (urls))
for i, url := range urls {
g.Go(func () error {
resp, err := fetch(ctx, url)
if err != nil {
return fmt.Errorf("fetching %s: %w" , url, err)
}
responses[i] = resp
return nil
})
}
if err := g.Wait(); err != nil {
return nil , err
}
return responses, nil
}
func fanOutFanIn (ctx context.Context, input <-chan Job, workers int ) <-chan Result {
results := make (chan Result)
var wg sync.WaitGroup
for i := 0 ; i < workers; i++ {
wg.Add(1 )
go func () {
defer wg.Done()
for job := range input {
select {
case <-ctx.Done():
return
case results <- process(job):
}
}
}()
}
go func () {
wg.Wait()
close (results)
}()
return results
}
func (s *UserService) CreateUser(ctx context.Context, u *User) error {
if err := s.validate(ctx, u); err != nil {
return err
}
if err := s.repo.CreateUser(ctx, u); err != nil {
return fmt.Errorf("creating user: %w" , err)
}
go func () {
bgCtx, cancel := context.WithTimeout(context.Background(), 30 *time.Second)
defer cancel()
s.sendWelcomeEmail(bgCtx, u)
}()
return nil
}
5. HTTP Server with Graceful Shutdown func main () {
cfg := config.Load()
logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
Level: cfg.LogLevel,
}))
db, err := sql.Open("postgres" , cfg.DatabaseURL)
if err != nil {
logger.Error("failed to connect to database" , "error" , err)
os.Exit(1 )
}
db.SetMaxOpenConns(cfg.DBMaxConns)
db.SetMaxIdleConns(cfg.DBMaxConns / 2 )
db.SetConnMaxLifetime(30 * time.Minute)
repo := postgres.NewUserRepository(db)
svc := service.NewUserService(repo, logger)
handler := handler.NewRouter(svc, logger)
srv := &http.Server{
Addr: ":" + cfg.Port,
Handler: handler,
ReadTimeout: 15 * time.Second,
WriteTimeout: 15 * time.Second,
IdleTimeout: 60 * time.Second,
}
go func () {
logger.Info("server starting" , "port" , cfg.Port)
if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
logger.Error("server error" , "error" , err)
os.Exit(1 )
}
}()
quit := make (chan os.Signal, 1 )
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
logger.Info("shutting down server..." )
ctx, cancel := context.WithTimeout(context.Background(), 30 *time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
logger.Error("forced shutdown" , "error" , err)
}
db.Close()
logger.Info("server stopped" )
}
Best Practices
Accept interfaces, return structs -- define interfaces at the call site
Always propagate context.Context as the first parameter
Wrap errors with fmt.Errorf("context: %w", err) at every layer
Use slog (Go 1.21+) for structured logging
Use errgroup instead of manual sync.WaitGroup + error collection
Keep goroutine lifetimes bounded -- always have a cancellation path
Use go vet, staticcheck, and golangci-lint in CI
Prefer table-driven tests with t.Run() subtests
Use internal/ package to prevent external imports of private code
Set GOMAXPROCS appropriately in containerized environments (use automaxprocs)
Common Pitfalls Pitfall Impact Fix Goroutine leak (no cancellation path) Memory/CPU leak Always use context cancellation or done channel Race condition on shared state Data corruption Use sync.Mutex, channels, or sync/atomic Closing a channel from receiver side Panic Only the sender should close channels Ignoring errors (using _) Silent failures Handle or explicitly log every error defer in a loopResource accumulation Extract to a function so defer runs per iteration Using interface{} / any liberally Loses type safety Use generics (Go 1.18+) Not setting HTTP server timeouts Slowloris attacks Always set Read/Write/Idle timeouts