Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit a56a463

Browse files
Create golang rules
1 parent ce4964b commit a56a463

File tree

1 file changed

+288
-0
lines changed

1 file changed

+288
-0
lines changed

‎golang‎

Lines changed: 288 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
---
2+
description: Enforces best practices for Go development, focusing on context-aware code generation, modern patterns, and maintainable architecture. Provides comprehensive guidelines for writing clean, efficient, and secure Go code with proper context.
3+
globs: **/*.go
4+
---
5+
# Go Best Practices
6+
7+
You are an expert in Go programming and related technologies.
8+
You understand modern Go development practices, architectural patterns, and the importance of providing complete context in code generation.
9+
10+
### Context-Aware Code Generation
11+
- Always provide complete package context including imports and package declarations
12+
- Include relevant configuration files (go.mod, go.sum) when generating projects
13+
- Generate complete function signatures with proper parameters and return values
14+
- Include comprehensive GoDoc comments explaining the purpose, parameters, and return values
15+
- Provide context about the package's role in the larger system architecture
16+
- Follow proper package organization and module structure
17+
18+
### Code Style and Structure
19+
- Follow Go style guide and clean code principles
20+
- Structure code in logical packages following domain-driven design
21+
- Implement proper separation of concerns (handlers, services, repositories)
22+
- Use modern Go features (generics, error wrapping, context) appropriately
23+
- Maintain consistent code formatting using gofmt
24+
- Use proper interface design and composition
25+
- Implement proper error handling with custom error types
26+
- Use proper logging with structured data
27+
- Use strict typing, avoid `any` or its analogues when possible
28+
- Follow DRY, SOLID and KISS principles
29+
- Write unit tests for all public/exported methods and functions
30+
- Document functions, methods and logical blocks
31+
- Critical code sections should always have a comment started with `ATTN:` and followed by explanation
32+
33+
### Type System and Interfaces
34+
- Use proper type definitions and interfaces
35+
- Implement proper interface segregation
36+
- Use proper type assertions and type switches
37+
- Implement proper custom types and methods
38+
- Use proper type embedding and composition
39+
- Implement proper type constraints with generics
40+
- Use proper type aliases when appropriate
41+
- Implement proper type safety patterns
42+
43+
### Testing and Quality
44+
- Write comprehensive unit tests with proper test context
45+
- Include integration tests for critical paths
46+
- Use proper table-driven tests
47+
- Implement proper test helpers and utilities
48+
- Include performance tests for critical components
49+
- Maintain high test coverage for core business logic
50+
- Use proper test data factories
51+
- Implement proper test doubles
52+
- Use proper test organization with test packages
53+
54+
### Dependency Injection
55+
- Use constructor injection pattern for dependencies
56+
- Define interfaces for all services and providers
57+
- Implement providers in the infrastructure layer
58+
- Wire up dependencies in the cmd layer
59+
- Use functional options pattern for configurable components
60+
- Keep service constructors simple and focused
61+
- Avoid global state and singletons
62+
- Use context.Context for request-scoped dependencies
63+
- Inject tracer for distributed tracing
64+
- Inject logger for structured logging
65+
- Use closer.Closer for graceful shutdown
66+
- Separate interface from implementation
67+
68+
### Error Handling
69+
- Domain-specific errors are to be separated (i.g. defined in `internal/domain/errors.go`)
70+
- Use custom error types for domain-specific errors
71+
- Always check errors and propagate them up the call stack
72+
- Use meaningful error messages that describe what went wrong
73+
- In API handlers (if any), map domain errors to appropriate HTTP status codes
74+
- Use structured logging for errors with relevant context
75+
- Don't expose internal errors to API clients
76+
- Wrap errors with additional context when crossing layer boundaries
77+
- Use sentinel errors for expected error conditions
78+
- In workflows and activities, use appropriate error types for retryable vs. non-retryable errors
79+
80+
### Error Prevention
81+
- Always verify type consistency
82+
- Check for potential NPE (Null Pointer Exception or its analogues)
83+
- Validate against business rules
84+
- Always ensure tracability - error handling and logging
85+
86+
### Logging and Tracing Patterns
87+
- Use structured logging with log fields
88+
- Inject logger as a dependency
89+
- Use appropriate log levels (debug, info, warn, error)
90+
- Include relevant context in log messages
91+
- Use OpenTelemetry for distributed tracing
92+
- Inject tracer as a dependency
93+
- Create spans for important operations
94+
- Add attributes to spans for context
95+
- Propagate trace context across service boundaries
96+
- Use correlation IDs to link related operations
97+
- Log errors with stack traces
98+
- Implement proper error context
99+
- Use middleware for request/response logging
100+
- Implement proper log rotation and retention
101+
102+
### Security and Performance
103+
- Implement proper input validation and sanitization
104+
- Use secure authentication and token management
105+
- Configure proper CORS and CSRF protection
106+
- Implement rate limiting and request validation
107+
- Use proper caching strategies
108+
- Optimize memory usage and garbage collection
109+
- Implement proper error handling and logging
110+
- Use proper data validation and sanitization
111+
- Implement proper access control
112+
113+
### API Design
114+
- Follow RESTful principles with proper HTTP methods
115+
- Use proper status codes and error responses
116+
- Implement proper versioning strategies
117+
- Document APIs using OpenAPI/Swagger
118+
- Include proper request/response validation
119+
- Implement proper pagination and filtering
120+
- Use proper serialization and deserialization
121+
- Implement proper rate limiting
122+
- Use proper API authentication
123+
124+
### Concurrency and Parallelism
125+
- Use proper goroutine patterns
126+
- Implement proper channel communication
127+
- Use proper sync primitives
128+
- Implement proper context cancellation
129+
- Use proper worker pools
130+
- Implement proper error handling in goroutines
131+
- Use proper resource cleanup
132+
- Implement proper backpressure
133+
- Use proper concurrent data structures
134+
135+
### Build and Deployment
136+
- Use proper module management
137+
- Implement proper CI/CD pipelines
138+
- Use Docker for containerization
139+
- Configure proper environment variables
140+
- Implement proper logging and monitoring
141+
- Use proper deployment strategies
142+
- Implement proper backup strategies
143+
- Use proper monitoring tools
144+
- Implement proper error tracking
145+
146+
### Examples
147+
148+
```go
149+
// Package user provides user-related operations.
150+
// It handles user management and authentication.
151+
package user
152+
153+
import (
154+
"context"
155+
"encoding/json"
156+
"errors"
157+
"fmt"
158+
"log"
159+
)
160+
161+
// UserService handles user-related operations.
162+
type UserService struct {
163+
apiClient APIClient
164+
cache Cache
165+
logger *log.Logger
166+
}
167+
168+
// NewUserService creates a new UserService instance.
169+
func NewUserService(apiClient APIClient, cache Cache, logger *log.Logger) *UserService {
170+
if logger == nil {
171+
logger = log.Default()
172+
}
173+
return &UserService{
174+
apiClient: apiClient,
175+
cache: cache,
176+
logger: logger,
177+
}
178+
}
179+
180+
// FindUserByEmail finds a user by their email address.
181+
//
182+
// Parameters:
183+
// - ctx: context for cancellation and timeouts
184+
// - email: the email address to search for
185+
//
186+
// Returns:
187+
// - *User: the user if found
188+
// - error: any error that occurred
189+
func (s *UserService) FindUserByEmail(ctx context.Context, email string) (*User, error) {
190+
// Check cache first
191+
cachedUser, err := s.cache.Get(ctx, fmt.Sprintf("user:%s", email))
192+
if err == nil && cachedUser != "" {
193+
var user User
194+
if err := json.Unmarshal([]byte(cachedUser), &user); err == nil {
195+
return &user, nil
196+
}
197+
}
198+
199+
// Fetch from API
200+
user, err := s.apiClient.GetUser(ctx, email)
201+
if err != nil {
202+
s.logger.Printf("Failed to find user by email: %v", err)
203+
return nil, fmt.Errorf("failed to find user by email: %w", err)
204+
}
205+
206+
// Cache the result
207+
if user != nil {
208+
userJSON, err := json.Marshal(user)
209+
if err == nil {
210+
_ = s.cache.Set(ctx, fmt.Sprintf("user:%s", email), string(userJSON))
211+
}
212+
}
213+
214+
return user, nil
215+
}
216+
217+
// Tests for UserService functionality.
218+
func TestUserService_FindUserByEmail(t *testing.T) {
219+
tests := []struct {
220+
name string
221+
email string
222+
cacheResponse string
223+
apiResponse *User
224+
apiError error
225+
wantUser *User
226+
wantError bool
227+
}{
228+
{
229+
name: "user found in cache",
230+
email: "test@example.com",
231+
cacheResponse: `{"id":1,"email":"test@example.com"}`,
232+
wantUser: &User{ID: 1, Email: "test@example.com"},
233+
},
234+
{
235+
name: "user found via API",
236+
email: "test@example.com",
237+
apiResponse: &User{ID: 1, Email: "test@example.com"},
238+
wantUser: &User{ID: 1, Email: "test@example.com"},
239+
},
240+
{
241+
name: "user not found",
242+
email: "nonexistent@example.com",
243+
apiResponse: nil,
244+
wantUser: nil,
245+
},
246+
{
247+
name: "API error",
248+
email: "test@example.com",
249+
apiError: errors.New("API error"),
250+
wantError: true,
251+
},
252+
}
253+
254+
for _, tt := range tests {
255+
t.Run(tt.name, func(t *testing.T) {
256+
// Setup
257+
ctx := context.Background()
258+
apiClient := &mockAPIClient{
259+
getUserResponse: tt.apiResponse,
260+
getUserError: tt.apiError,
261+
}
262+
cache := &mockCache{
263+
getResponse: tt.cacheResponse,
264+
}
265+
service := NewUserService(apiClient, cache, nil)
266+
267+
// Execute
268+
user, err := service.FindUserByEmail(ctx, tt.email)
269+
270+
// Verify
271+
if tt.wantError {
272+
if err == nil {
273+
t.Error("expected error, got nil")
274+
}
275+
return
276+
}
277+
278+
if err != nil {
279+
t.Errorf("unexpected error: %v", err)
280+
return
281+
}
282+
283+
if !reflect.DeepEqual(user, tt.wantUser) {
284+
t.Errorf("got user %v, want %v", user, tt.wantUser)
285+
}
286+
})
287+
}
288+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /