一键导入
go-backend
Go backend development best practices for LLMProxy. Use when writing Go code, handlers, middleware, or backend services.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Go backend development best practices for LLMProxy. Use when writing Go code, handlers, middleware, or backend services.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
RESTful API design best practices. Use when designing endpoints, request/response schemas, error handling, and API versioning.
Perform thorough code reviews with security, performance, and quality checks. Use when reviewing PRs, auditing code changes, or finding potential bugs.
Database design and optimization. Use for schema design, queries, migrations, indexing, and performance tuning.
Systematic debugging methodology for finding and fixing bugs. Use when investigating issues, tracing errors, or fixing production problems.
Docker and containerization best practices. Use for Dockerfile creation, docker-compose, multi-stage builds, and container optimization.
Technical documentation best practices. Use for writing READMEs, API docs, code comments, and project documentation.
| name | go-backend |
| description | Go backend development best practices for LLMProxy. Use when writing Go code, handlers, middleware, or backend services. |
Best practices for Go backend development, specifically tailored for LLMProxy architecture.
.
├── cmd/
│ └── main.go # Application entry point
├── internal/
│ ├── auth/ # Authentication logic
│ ├── config/ # Configuration management
│ ├── database/ # Database layer
│ ├── lb/ # Load balancing
│ ├── middleware/ # HTTP middleware
│ ├── proxy/ # Proxy handlers
│ └── metrics/ # Monitoring
├── pkg/ # Public packages
├── deployments/ # Deployment configs
└── docs/ # Documentation
func (h *Handler) HandleRequest(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
// 1. Parse and validate input
var req RequestDTO
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
h.respondError(w, http.StatusBadRequest, "invalid request body")
return
}
if err := h.validator.Validate(req); err != nil {
h.respondError(w, http.StatusBadRequest, err.Error())
return
}
// 2. Execute business logic
result, err := h.service.Process(ctx, req)
if err != nil {
h.handleError(w, err)
return
}
// 3. Return response
h.respondJSON(w, http.StatusOK, result)
}
type Response struct {
Success bool `json:"success"`
Data interface{} `json:"data,omitempty"`
Error *ErrorInfo `json:"error,omitempty"`
}
type ErrorInfo struct {
Code string `json:"code"`
Message string `json:"message"`
}
func (h *Handler) respondJSON(w http.ResponseWriter, status int, data interface{}) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
json.NewEncoder(w).Encode(Response{
Success: true,
Data: data,
})
}
func (h *Handler) respondError(w http.ResponseWriter, status int, message string) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
json.NewEncoder(w).Encode(Response{
Success: false,
Error: &ErrorInfo{
Code: http.StatusText(status),
Message: message,
},
})
}
type AppError struct {
Code string
Message string
HTTPStatus int
Err error
}
func (e *AppError) Error() string {
if e.Err != nil {
return fmt.Sprintf("%s: %v", e.Message, e.Err)
}
return e.Message
}
func (e *AppError) Unwrap() error {
return e.Err
}
// Predefined errors
var (
ErrNotFound = &AppError{Code: "NOT_FOUND", HTTPStatus: 404}
ErrUnauthorized = &AppError{Code: "UNAUTHORIZED", HTTPStatus: 401}
ErrForbidden = &AppError{Code: "FORBIDDEN", HTTPStatus: 403}
ErrBadRequest = &AppError{Code: "BAD_REQUEST", HTTPStatus: 400}
ErrInternal = &AppError{Code: "INTERNAL_ERROR", HTTPStatus: 500}
)
func NewNotFoundError(resource string) *AppError {
return &AppError{
Code: "NOT_FOUND",
Message: fmt.Sprintf("%s not found", resource),
HTTPStatus: http.StatusNotFound,
}
}
func (h *Handler) handleError(w http.ResponseWriter, err error) {
var appErr *AppError
if errors.As(err, &appErr) {
h.respondError(w, appErr.HTTPStatus, appErr.Message)
return
}
// Log unexpected errors
h.logger.Error("unexpected error", zap.Error(err))
h.respondError(w, http.StatusInternalServerError, "internal server error")
}
type Middleware func(http.Handler) http.Handler
func Chain(middlewares ...Middleware) Middleware {
return func(final http.Handler) http.Handler {
for i := len(middlewares) - 1; i >= 0; i-- {
final = middlewares[i](final)
}
return final
}
}
// Usage
handler := Chain(
LoggingMiddleware,
RecoveryMiddleware,
AuthMiddleware,
RateLimitMiddleware,
)(finalHandler)
func LoggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
// Wrap response writer to capture status
wrapped := &responseWriter{ResponseWriter: w, status: http.StatusOK}
next.ServeHTTP(wrapped, r)
logger.Info("request",
zap.String("method", r.Method),
zap.String("path", r.URL.Path),
zap.Int("status", wrapped.status),
zap.Duration("duration", time.Since(start)),
)
})
}
type responseWriter struct {
http.ResponseWriter
status int
}
func (w *responseWriter) WriteHeader(status int) {
w.status = status
w.ResponseWriter.WriteHeader(status)
}
func RecoveryMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() {
if err := recover(); err != nil {
logger.Error("panic recovered",
zap.Any("error", err),
zap.String("stack", string(debug.Stack())),
)
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
}
}()
next.ServeHTTP(w, r)
})
}
func AuthMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("Authorization")
if token == "" {
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}
// Validate token
claims, err := validateToken(strings.TrimPrefix(token, "Bearer "))
if err != nil {
http.Error(w, "invalid token", http.StatusUnauthorized)
return
}
// Add claims to context
ctx := context.WithValue(r.Context(), userClaimsKey, claims)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
type UserRepository interface {
GetByID(ctx context.Context, id string) (*User, error)
Create(ctx context.Context, user *User) error
Update(ctx context.Context, user *User) error
Delete(ctx context.Context, id string) error
List(ctx context.Context, opts ListOptions) ([]*User, error)
}
type userRepository struct {
db *sql.DB
}
func (r *userRepository) GetByID(ctx context.Context, id string) (*User, error) {
query := `SELECT id, name, email, created_at FROM users WHERE id = $1`
var user User
err := r.db.QueryRowContext(ctx, query, id).Scan(
&user.ID, &user.Name, &user.Email, &user.CreatedAt,
)
if err == sql.ErrNoRows {
return nil, ErrNotFound
}
if err != nil {
return nil, fmt.Errorf("query user: %w", err)
}
return &user, nil
}
func (r *userRepository) CreateWithProfile(ctx context.Context, user *User, profile *Profile) error {
tx, err := r.db.BeginTx(ctx, nil)
if err != nil {
return fmt.Errorf("begin transaction: %w", err)
}
defer tx.Rollback() // No-op if committed
// Insert user
_, err = tx.ExecContext(ctx,
`INSERT INTO users (id, name, email) VALUES ($1, $2, $3)`,
user.ID, user.Name, user.Email,
)
if err != nil {
return fmt.Errorf("insert user: %w", err)
}
// Insert profile
_, err = tx.ExecContext(ctx,
`INSERT INTO profiles (user_id, bio) VALUES ($1, $2)`,
user.ID, profile.Bio,
)
if err != nil {
return fmt.Errorf("insert profile: %w", err)
}
if err := tx.Commit(); err != nil {
return fmt.Errorf("commit transaction: %w", err)
}
return nil
}
db, err := sql.Open("postgres", connString)
if err != nil {
return err
}
// Configure pool
db.SetMaxOpenConns(25)
db.SetMaxIdleConns(5)
db.SetConnMaxLifetime(5 * time.Minute)
db.SetConnMaxIdleTime(1 * time.Minute)
func (h *Handler) HandleRequest(w http.ResponseWriter, r *http.Request) {
// Add timeout to context
ctx, cancel := context.WithTimeout(r.Context(), 30*time.Second)
defer cancel()
result, err := h.service.Process(ctx)
if errors.Is(err, context.DeadlineExceeded) {
h.respondError(w, http.StatusGatewayTimeout, "request timeout")
return
}
// ...
}
var bufferPool = sync.Pool{
New: func() interface{} {
return new(bytes.Buffer)
},
}
func processData(data []byte) {
buf := bufferPool.Get().(*bytes.Buffer)
defer func() {
buf.Reset()
bufferPool.Put(buf)
}()
// Use buffer...
}
func TestHandler_CreateUser(t *testing.T) {
// Setup
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockService := NewMockUserService(ctrl)
handler := NewHandler(mockService)
// Expectations
mockService.EXPECT().
Create(gomock.Any(), gomock.Any()).
Return(&User{ID: "123", Name: "Test"}, nil)
// Request
body := `{"name": "Test", "email": "test@example.com"}`
req := httptest.NewRequest("POST", "/users", strings.NewReader(body))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
// Execute
handler.CreateUser(w, req)
// Assert
assert.Equal(t, http.StatusCreated, w.Code)
}