Agent Skill
2/7/2026go-conventions
Go conventions, best practices, and idiomatic patterns for production code
J
jonathan0823
2GitHub Stars
1Views
npx skills add Jonathan0823/opencode-config
SKILL.md
| Name | go-conventions |
| Description | Go conventions, best practices, and idiomatic patterns for production code |
name: go-conventions description: Go conventions, best practices, and idiomatic patterns for production code license: MIT compatibility: opencode
Go Conventions Skill
Overview
This skill provides guidelines for writing idiomatic, production-ready Go code following Go conventions, best practices, and patterns optimized for backend development with Gin and standard library.
Core Principles
1. Idiomatic Go
- Follow Go's philosophy: "Simple is better"
- Prefer composition over inheritance
- Use small interfaces
- Write self-documenting code with clear variable names
- Keep functions short and focused
2. Error Handling
// DO: Explicit error handling with context
result, err := processData(input)
if err != nil {
return fmt.Errorf("failed to process data: %w", err)
}
// DON'T: Ignore errors
result, _ := processData(input) // Never do this
// DO: Wrap errors for context
return fmt.Errorf("database operation failed: %w", err)
// DO: Use custom error types for domain-specific errors
type ValidationError struct {
Field string
Message string
}
func (e ValidationError) Error() string {
return fmt.Sprintf("validation failed for %s: %s", e.Field, e.Message)
}
3. Concurrency Patterns
// DO: Use context for cancellation
func fetchData(ctx context.Context, url string) ([]byte, error) {
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
return nil, err
}
// ...
}
// DO: Use channels with select for timeouts
select {
case result := <-ch:
return result, nil
case <-time.After(timeout):
return nil, errors.New("timeout")
case <-ctx.Done():
return nil, ctx.Err()
}
// DO: Use sync.WaitGroup for goroutine coordination
var wg sync.WaitGroup
for _, task := range tasks {
wg.Add(1)
go func(t Task) {
defer wg.Done()
process(t)
}(task)
}
wg.Wait()
4. Struct and Interface Design
// DO: Small interfaces (Interface Segregation)
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
// DO: Constructor patterns for complex structs
func NewService(db *sql.DB, cache *redis.Client, logger *zap.Logger) *Service {
return &Service{
db: db,
cache: cache,
logger: logger,
}
}
// DO: Method receivers - pointer vs value
func (s *Service) Update(data Data) error // Pointer for mutation
func (c Config) Validate() error // Value for read-only
5. Package Organization
myproject/
├── cmd/
│ └── api/ # Main application entry point
│ └── main.go
├── internal/
│ ├── domain/ # Business logic (entities, use cases)
│ ├── repository/ # Data access layer
│ ├── service/ # Business services
│ └── handler/ # HTTP handlers
├── pkg/
│ ├── middleware/ # Shared middleware
│ └── utils/ # Shared utilities
└── go.mod
Gin-Specific Patterns
1. Handler Structure
// DO: Use dependency injection
func (h *UserHandler) CreateUser(c *gin.Context) {
var req CreateUserRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
user, err := h.service.CreateUser(c.Request.Context(), req)
if err != nil {
handleError(c, err)
return
}
c.JSON(http.StatusCreated, user)
}
// DO: Centralized error handling
func handleError(c *gin.Context, err error) {
switch e := err.(type) {
case *ValidationError:
c.JSON(http.StatusBadRequest, gin.H{"error": e.Error()})
case *NotFoundError:
c.JSON(http.StatusNotFound, gin.H{"error": e.Error()})
default:
c.JSON(http.StatusInternalServerError, gin.H{"error": "internal server error"})
}
}
2. Middleware Patterns
// DO: Authentication middleware
func AuthMiddleware(secret string) gin.HandlerFunc {
return func(c *gin.Context) {
token := c.GetHeader("Authorization")
if token == "" {
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "missing token"})
return
}
claims, err := validateToken(token, secret)
if err != nil {
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "invalid token"})
return
}
c.Set("user", claims)
c.Next()
}
}
// DO: Logging middleware
func LoggerMiddleware(logger *zap.Logger) gin.HandlerFunc {
return func(c *gin.Context) {
start := time.Now()
path := c.Request.URL.Path
c.Next()
logger.Info("request",
zap.String("method", c.Request.Method),
zap.String("path", path),
zap.Int("status", c.Writer.Status()),
zap.Duration("duration", time.Since(start)),
)
}
}
Database Patterns (PostgreSQL)
// DO: Repository pattern
type UserRepository interface {
Create(ctx context.Context, user *User) error
GetByID(ctx context.Context, id int64) (*User, error)
Update(ctx context.Context, user *User) error
Delete(ctx context.Context, id int64) error
List(ctx context.Context, opts ListOptions) ([]User, error)
}
// DO: Transaction handling
func (r *userRepo) CreateWithProfile(ctx context.Context, user *User, profile *Profile) error {
tx, err := r.db.BeginTx(ctx, nil)
if err != nil {
return err
}
defer tx.Rollback()
if err := r.createUserTx(ctx, tx, user); err != nil {
return err
}
if err := r.createProfileTx(ctx, tx, profile); err != nil {
return err
}
return tx.Commit()
}
Testing Patterns
// DO: Table-driven tests
func TestCalculateTotal(t *testing.T) {
tests := []struct {
name string
items []Item
expected float64
}{
{
name: "empty cart",
items: []Item{},
expected: 0,
},
{
name: "single item",
items: []Item{{Price: 10, Quantity: 2}},
expected: 20,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := calculateTotal(tt.items)
assert.Equal(t, tt.expected, result)
})
}
}
// DO: Mock interfaces for testing
type MockUserService struct {
mock.Mock
}
func (m *MockUserService) GetUser(ctx context.Context, id int64) (*User, error) {
args := m.Called(ctx, id)
return args.Get(0).(*User), args.Error(1)
}
When to Use
Use this skill when:
- Writing or reviewing Go code
- Designing Go architecture
- Refactoring Go projects
- Implementing Go backend services with Gin
- Writing Go tests
- Setting up Go project structure
Skills Info
Original Name:go-conventionsAuthor:jonathan0823
Download