[teamai] Push 87 resource(s) from XingfenD
This commit is contained in:
@@ -0,0 +1,210 @@
|
||||
# Application Documentation
|
||||
|
||||
→ See `samber/cc-skills-golang@golang-cli` skill for CLI application patterns and frameworks.
|
||||
|
||||
## CLI Help Text
|
||||
|
||||
For CLI applications, `--help` output is the primary documentation. CLI tools MUST have comprehensive `--help` text:
|
||||
|
||||
```go
|
||||
// Use cobra or similar framework for structured help text
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "mytool",
|
||||
Short: "A brief description of mytool",
|
||||
Long: `A longer description that explains the tool in detail.
|
||||
|
||||
mytool helps you do X, Y, and Z. It connects to your
|
||||
database and performs analysis on the data.
|
||||
|
||||
Environment variables:
|
||||
MYTOOL_DB_URL Database connection string (required)
|
||||
MYTOOL_LOG_LEVEL Log level: debug, info, warn, error (default: info)
|
||||
MYTOOL_TIMEOUT Request timeout (default: 30s)`,
|
||||
Example: ` # Basic usage
|
||||
mytool analyze --input data.csv
|
||||
|
||||
# With custom configuration
|
||||
mytool analyze --input data.csv --output report.json --format json
|
||||
|
||||
# Using environment variables
|
||||
export MYTOOL_DB_URL="postgres://localhost/mydb"
|
||||
mytool serve`,
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Configuration Documentation
|
||||
|
||||
Configuration SHOULD be documented. Document all configuration sources in the README or a dedicated `docs/configuration.md`:
|
||||
|
||||
````markdown
|
||||
## Configuration
|
||||
|
||||
Configuration is loaded in this order (later sources override earlier ones):
|
||||
|
||||
1. Default values
|
||||
2. Configuration file (`~/.config/mytool/config.yaml`)
|
||||
3. Environment variables
|
||||
4. Command-line flags
|
||||
|
||||
### Environment Variables
|
||||
|
||||
| Variable | Description | Default | Required |
|
||||
| ------------------ | -------------------------- | ------- | -------- |
|
||||
| `MYTOOL_DB_URL` | Database connection string | — | Yes |
|
||||
| `MYTOOL_LOG_LEVEL` | Log verbosity | `info` | No |
|
||||
| `MYTOOL_PORT` | HTTP server port | `8080` | No |
|
||||
| `MYTOOL_TIMEOUT` | Request timeout | `30s` | No |
|
||||
|
||||
### Configuration File
|
||||
|
||||
```yaml
|
||||
# ~/.config/mytool/config.yaml
|
||||
database:
|
||||
url: postgres://localhost/mydb
|
||||
max_connections: 25
|
||||
server:
|
||||
port: 8080
|
||||
read_timeout: 30s
|
||||
logging:
|
||||
level: info
|
||||
format: json
|
||||
```
|
||||
````
|
||||
|
||||
---
|
||||
|
||||
## Architecture & design decisions
|
||||
|
||||
For complex applications, document architectural decisions in `docs/architecture/`:
|
||||
|
||||
```
|
||||
docs/
|
||||
architecture/
|
||||
0001-use-postgres-as-primary-store.md
|
||||
0002-event-driven-architecture.md
|
||||
0003-jwt-for-authentication.md
|
||||
README.md
|
||||
```
|
||||
|
||||
Each design document follows a standard format:
|
||||
|
||||
```markdown
|
||||
# Use PostgreSQL as Primary Store
|
||||
|
||||
## Context
|
||||
|
||||
We need a persistent data store that supports...
|
||||
|
||||
## Design
|
||||
|
||||
We use PostgreSQL because...
|
||||
|
||||
## Consequences
|
||||
|
||||
- Positive: ACID transactions, rich query language...
|
||||
- Negative: Operational overhead, connection management...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API Documentation
|
||||
|
||||
### REST APIs — OpenAPI / Swagger
|
||||
|
||||
Use [swaggo/swag](https://github.com/swaggo/swag) to auto-generate OpenAPI docs from Go annotations:
|
||||
|
||||
```go
|
||||
// @Summary Get user by ID
|
||||
// @Description Returns a single user
|
||||
// @Tags users
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "User ID"
|
||||
// @Success 200 {object} User
|
||||
// @Failure 404 {object} ErrorResponse
|
||||
// @Failure 500 {object} ErrorResponse
|
||||
// @Router /users/{id} [get]
|
||||
func GetUser(w http.ResponseWriter, r *http.Request) {
|
||||
```
|
||||
|
||||
Generate the spec:
|
||||
|
||||
```bash
|
||||
go get -tool github.com/swaggo/swag/cmd/swag@latest
|
||||
go tool swag init -g cmd/server/main.go -o docs/swagger
|
||||
```
|
||||
|
||||
This produces `docs/swagger/swagger.json` and `docs/swagger/swagger.yaml`. Serve with Swagger UI or Redoc.
|
||||
|
||||
### Event-Driven — AsyncAPI
|
||||
|
||||
For message-based APIs (Kafka, NATS, RabbitMQ), use [AsyncAPI](https://www.asyncapi.com/):
|
||||
|
||||
```yaml
|
||||
asyncapi: "2.6.0"
|
||||
info:
|
||||
title: Order Events
|
||||
version: "1.0.0"
|
||||
channels:
|
||||
orders/created:
|
||||
publish:
|
||||
message:
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
orderId:
|
||||
type: string
|
||||
amount:
|
||||
type: number
|
||||
```
|
||||
|
||||
### gRPC — Protobuf
|
||||
|
||||
Protobuf files serve as both code contracts and documentation. Add comments to messages and RPCs:
|
||||
|
||||
```protobuf
|
||||
syntax = "proto3";
|
||||
|
||||
// UserService manages user accounts.
|
||||
service UserService {
|
||||
// GetUser retrieves a user by their unique identifier.
|
||||
// Returns NOT_FOUND if the user does not exist.
|
||||
rpc GetUser(GetUserRequest) returns (User);
|
||||
|
||||
// CreateUser registers a new user account.
|
||||
// Returns ALREADY_EXISTS if the email is taken.
|
||||
rpc CreateUser(CreateUserRequest) returns (User);
|
||||
}
|
||||
|
||||
// User represents a registered user account.
|
||||
message User {
|
||||
// Unique identifier for the user (UUID v4).
|
||||
string id = 1;
|
||||
// User's display name (1-100 characters).
|
||||
string name = 2;
|
||||
// User's email address (must be unique across all users).
|
||||
string email = 3;
|
||||
}
|
||||
```
|
||||
|
||||
Use [buf](https://buf.build/) for linting and breaking change detection:
|
||||
|
||||
```bash
|
||||
buf lint
|
||||
buf breaking --against '.git#branch=main'
|
||||
```
|
||||
|
||||
For REST+gRPC, use [grpc-gateway](https://github.com/grpc-ecosystem/grpc-gateway) to serve both from the same protobuf definition.
|
||||
|
||||
### When to Use Each Format
|
||||
|
||||
| API Style | Format | Auto-generation |
|
||||
| --- | --- | --- |
|
||||
| REST/HTTP with Go handlers | OpenAPI 3.x | swaggo/swag from annotations |
|
||||
| REST/HTTP with framework | OpenAPI 3.x | Framework-specific (e.g., huma) |
|
||||
| gRPC services | Protobuf | Proto files are the source of truth |
|
||||
| gRPC + REST gateway | Protobuf + OpenAPI | grpc-gateway generates OpenAPI |
|
||||
| Message queues / events | AsyncAPI | Manual or code-gen |
|
||||
| GraphQL | SDL schema | Schema is the docs |
|
||||
@@ -0,0 +1,329 @@
|
||||
# Code Comments
|
||||
|
||||
→ See `samber/cc-skills-golang@golang-naming` skill for naming conventions that reduce the need for comments.
|
||||
|
||||
## Function & Method Doc Comments
|
||||
|
||||
### Why, Not What
|
||||
|
||||
The most common mistake in doc comments is restating the code. The code already tells the reader _what_ happens — comments SHOULD explain why, not what:
|
||||
|
||||
- **Why** this function exists (its purpose in the system)
|
||||
- **When** to use it (and when not to)
|
||||
- **What constraints** apply (preconditions, thread safety, performance)
|
||||
- **What can go wrong** (error cases, panics, edge cases)
|
||||
|
||||
Bad — restates the code:
|
||||
|
||||
```go
|
||||
// GetUser gets a user by ID.
|
||||
func GetUser(id string) (*User, error) {
|
||||
```
|
||||
|
||||
Good — explains why, when, and what can go wrong:
|
||||
|
||||
```go
|
||||
// GetUser retrieves a user from the database by their unique identifier.
|
||||
// Use this for authenticated endpoints where you need the full user profile.
|
||||
// For listing or searching, use ListUsers instead — it returns lighter projections.
|
||||
//
|
||||
// Returns ErrNotFound if no user exists with the given ID.
|
||||
// Returns ErrDatabaseUnavailable if the connection pool is exhausted.
|
||||
func GetUser(id string) (*User, error) {
|
||||
```
|
||||
|
||||
### Anti-Patterns to Remove on Sight
|
||||
|
||||
| Anti-pattern | Example | Fix |
|
||||
| --- | --- | --- |
|
||||
| Pure paraphrase | `// GetUser gets a user` on `func GetUser()` — starts with the name (required by godoc) but adds nothing | After the name, add _when_ to use it, constraints, and what can go wrong |
|
||||
| Signature restatement | `// Returns a string and an error` | Document _which_ error and _why_ — the signature already shows types |
|
||||
| Marketing vocabulary | `seamlessly`, `powerful`, `robust`, `enterprise-grade` | Remove — state facts instead |
|
||||
| Invented rationale | `// designed to improve scalability` | Only document what the code actually does |
|
||||
| Groundless future claims | `// supports future extensibility` | Remove or back it with an interface or configuration |
|
||||
| Hollow filler | `// It's worth noting that...`, `// As mentioned above` | Cut — restate the fact directly if it matters |
|
||||
|
||||
### Format
|
||||
|
||||
Every doc comment MUST start with the function/method name followed by a verb phrase. This is how godoc renders it in package indexes.
|
||||
|
||||
```go
|
||||
// FuncName verb-phrase describing what it does.
|
||||
```
|
||||
|
||||
### Full Comment Template
|
||||
|
||||
Use this structure for exported functions and complex internal functions. Omit sections that don't apply (e.g., no Parameters section for zero-arg functions). Focus on the "why" — don't restate what the code already makes obvious:
|
||||
|
||||
```go
|
||||
// FuncName summarizes what this function does in one sentence.
|
||||
// Additional context explaining behavior, algorithms, or design decisions
|
||||
// that callers need to know.
|
||||
//
|
||||
// Parameters:
|
||||
// - paramName: description of what this parameter represents
|
||||
// - anotherParam: description with valid ranges or constraints
|
||||
//
|
||||
// Returns description of the return value(s).
|
||||
// Returns ErrSomething if [condition].
|
||||
// Returns ErrAnother if [different condition].
|
||||
//
|
||||
// Panics if [condition] (only document if the function can panic).
|
||||
//
|
||||
// It is safe for concurrent use (or: It is NOT safe for concurrent use).
|
||||
//
|
||||
// Play: https://go.dev/play/p/xxxxx
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// result, err := pkg.FuncName(arg1, arg2)
|
||||
// if err != nil {
|
||||
// log.Fatal(err)
|
||||
// }
|
||||
// fmt.Println(result)
|
||||
func FuncName(paramName Type, anotherParam Type) (ResultType, error) {
|
||||
```
|
||||
|
||||
### What to Document
|
||||
|
||||
| Element | Document? |
|
||||
| --- | --- |
|
||||
| Exported functions/methods | Always |
|
||||
| Exported types and interfaces | Always |
|
||||
| Exported constants and variables | Always |
|
||||
| Complex internal functions | Yes — algorithms, non-obvious logic |
|
||||
| Simple internal helpers | Optional — only if the name isn't self-explanatory |
|
||||
| Test functions | No |
|
||||
| Getters/setters with no logic | Brief one-liner is enough |
|
||||
|
||||
`TODO` comments SHOULD include a tracking issue reference when one exists (e.g., `// TODO(#123): ...`). For informal notes, `// TODO(username): ...` or plain `// TODO: ...` is acceptable.
|
||||
|
||||
### Error Cases and Limitations
|
||||
|
||||
Document every error a function can return, and any edge cases or limitations:
|
||||
|
||||
```go
|
||||
// Parse parses a duration string such as "300ms", "1.5h", or "2h45m".
|
||||
//
|
||||
// Parameters:
|
||||
// - s: A duration string. Valid time units are "ns", "us", "ms", "s", "m", "h".
|
||||
//
|
||||
// Returns the parsed duration.
|
||||
// Returns ErrInvalidDuration if the string is empty or has an invalid format.
|
||||
// Returns ErrOverflow if the duration exceeds math.MaxInt64 nanoseconds.
|
||||
//
|
||||
// Limitations:
|
||||
// - Does not support day, week, month, or year units.
|
||||
// - Precision is limited to nanoseconds.
|
||||
func Parse(s string) (time.Duration, error) {
|
||||
```
|
||||
|
||||
### Deprecated Functions
|
||||
|
||||
Use the `Deprecated:` marker. godoc renders this with special styling:
|
||||
|
||||
```go
|
||||
// OldFunc does something.
|
||||
//
|
||||
// Deprecated: Use NewFunc instead. OldFunc will be removed in v3.0.0.
|
||||
func OldFunc() {}
|
||||
```
|
||||
|
||||
### Interface Documentation
|
||||
|
||||
Document the interface itself and each method. Explain the contract that implementations must satisfy:
|
||||
|
||||
```go
|
||||
// Store defines a persistent key-value storage backend.
|
||||
// Implementations must be safe for concurrent use by multiple goroutines.
|
||||
//
|
||||
// All methods accept a context for cancellation and deadlines.
|
||||
// Implementations should respect context cancellation and return
|
||||
// ctx.Err() when the context is done.
|
||||
type Store interface {
|
||||
// Get retrieves the value associated with key.
|
||||
// Returns ErrNotFound if the key does not exist.
|
||||
// Returns ErrExpired if the key exists but has expired.
|
||||
Get(ctx context.Context, key string) ([]byte, error)
|
||||
|
||||
// Set stores a key-value pair with an optional TTL.
|
||||
// If ttl is 0, the entry does not expire.
|
||||
// Overwrites any existing value for the same key.
|
||||
Set(ctx context.Context, key string, value []byte, ttl time.Duration) error
|
||||
|
||||
// Delete removes a key from the store.
|
||||
// Returns nil (not an error) if the key does not exist.
|
||||
Delete(ctx context.Context, key string) error
|
||||
}
|
||||
```
|
||||
|
||||
### Method Comments on Structs
|
||||
|
||||
```go
|
||||
// Close gracefully shuts down the server.
|
||||
// It waits for active connections to complete up to the configured timeout.
|
||||
//
|
||||
// Returns an error if the shutdown times out or if the server
|
||||
// encounters an error while draining connections.
|
||||
//
|
||||
// Close is idempotent — calling it multiple times is safe.
|
||||
// It is NOT safe to call Close concurrently from multiple goroutines.
|
||||
func (s *Server) Close() error {
|
||||
```
|
||||
|
||||
### Inline Code Examples in Comments
|
||||
|
||||
Indent code examples by one tab in doc comments. godoc renders these as formatted code blocks:
|
||||
|
||||
```go
|
||||
// Transform applies a function to each element of a slice and returns
|
||||
// a new slice with the results.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// names := []string{"alice", "bob"}
|
||||
// upper := Transform(names, strings.ToUpper)
|
||||
// // upper: ["ALICE", "BOB"]
|
||||
func Transform[T any, U any](slice []T, fn func(T) U) []U {
|
||||
```
|
||||
|
||||
### Playground Links
|
||||
|
||||
Add a `Play:` line linking to a runnable Go Playground example of a public library. Use the samber/go-playground-mcp tool to create and share playground URLs when available:
|
||||
|
||||
```go
|
||||
// Map applies a function to each element of a slice.
|
||||
//
|
||||
// Play: https://go.dev/play/p/abc123xyz
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// doubled := Map([]int{1, 2, 3}, func(x int) int { return x * 2 })
|
||||
// // doubled: [2, 4, 6]
|
||||
func Map[T any, U any](s []T, fn func(T) U) []U {
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## File & Package Comments
|
||||
|
||||
### Package Comment
|
||||
|
||||
Every package should have a doc comment. Place it in one of these locations:
|
||||
|
||||
1. **At the top of the main `.go` file** — for small packages with one or two files
|
||||
2. **In a dedicated `doc.go` file** — for packages with many files
|
||||
|
||||
```go
|
||||
// Package httputil provides HTTP utility functions for request parsing,
|
||||
// response writing, and middleware chaining.
|
||||
//
|
||||
// It is designed to work with the standard net/http package and does not
|
||||
// depend on any specific HTTP framework.
|
||||
package httputil
|
||||
```
|
||||
|
||||
Use `doc.go` when the package has 3+ files or the package comment is longer than ~10 lines:
|
||||
|
||||
```go
|
||||
// Package auth implements authentication and authorization for the API server.
|
||||
//
|
||||
// # Architecture
|
||||
//
|
||||
// The package uses a middleware-based approach where each authentication
|
||||
// strategy (JWT, API key, OAuth2) implements the Authenticator interface.
|
||||
// Strategies are chained and tried in order until one succeeds.
|
||||
//
|
||||
// # Token Lifecycle
|
||||
//
|
||||
// Access tokens expire after 15 minutes. Refresh tokens expire after 7 days.
|
||||
// Token rotation is automatic — each refresh request issues a new refresh token
|
||||
// and invalidates the previous one.
|
||||
//
|
||||
// # Thread Safety
|
||||
//
|
||||
// All exported functions and types are safe for concurrent use.
|
||||
package auth
|
||||
```
|
||||
|
||||
### File-Level Description
|
||||
|
||||
For files that implement a specific algorithm, feature, or contain complex logic, add a descriptive comment block below the imports. This is a macro description — explain **why** this file or package exists, what problem it solves, and what design choices were made. Use ASCII art to describe complex flows or architectures. Don't describe what each line does:
|
||||
|
||||
```go
|
||||
package scheduler
|
||||
|
||||
import (
|
||||
"container/heap"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// This file implements a priority-queue-based task scheduler.
|
||||
//
|
||||
// Tasks are scheduled with a target execution time and stored in a min-heap
|
||||
// ordered by deadline. A single dispatcher goroutine polls the heap and
|
||||
// executes tasks when their deadline arrives.
|
||||
//
|
||||
// Supports: recurring tasks, one-shot tasks, task cancellation, and
|
||||
// graceful shutdown with drain timeout.
|
||||
//
|
||||
// Architecture:
|
||||
//
|
||||
// Schedule(task)
|
||||
// |
|
||||
// v
|
||||
// [Min-Heap Queue]
|
||||
// (by deadline)
|
||||
// |
|
||||
// Dispatcher Goroutine
|
||||
// (polling loop)
|
||||
// / \
|
||||
// / \
|
||||
// Deadline Deadline
|
||||
// not reached reached
|
||||
// | |
|
||||
// wait v
|
||||
// Execute
|
||||
// |
|
||||
// Recurring? | One-shot
|
||||
// / | \
|
||||
// / v \
|
||||
// Re-queue Complete Discard
|
||||
// \ | /
|
||||
// \ | /
|
||||
// v v v
|
||||
// [Continue polling]
|
||||
|
||||
type Scheduler struct {
|
||||
```
|
||||
|
||||
### When to Add File Descriptions
|
||||
|
||||
| Scenario | Add description? |
|
||||
| --- | --- |
|
||||
| File implements an algorithm (sorting, scheduling, tree traversal) | Yes |
|
||||
| File contains a complex state machine or protocol | Yes |
|
||||
| File has 200+ lines of related logic | Yes |
|
||||
| File is a simple CRUD handler or data model | No |
|
||||
| File name already explains everything (`json_parser.go`) | Only if non-obvious |
|
||||
|
||||
### Godoc Headings in Comments
|
||||
|
||||
Use `# Heading` syntax in doc comments (Go 1.19+) for structured documentation:
|
||||
|
||||
```go
|
||||
// Package config provides configuration loading and validation.
|
||||
//
|
||||
// # Supported Sources
|
||||
//
|
||||
// Configuration can be loaded from environment variables, YAML files,
|
||||
// or command-line flags. Sources are merged in order of precedence:
|
||||
// flags > env vars > config file > defaults.
|
||||
//
|
||||
// # Validation
|
||||
//
|
||||
// All configuration values are validated at load time. Invalid values
|
||||
// cause an immediate error rather than failing later at runtime.
|
||||
package config
|
||||
```
|
||||
@@ -0,0 +1,197 @@
|
||||
# Library Documentation
|
||||
|
||||
→ See `samber/cc-skills-golang@golang-testing` skill for writing effective Example test functions.
|
||||
|
||||
## Public vs Private Libraries
|
||||
|
||||
Not all documentation applies equally. Adapt to your audience:
|
||||
|
||||
| Documentation | Public Library | Private Library |
|
||||
| --- | --- | --- |
|
||||
| Doc comments on exported symbols | Required | Required |
|
||||
| Package comments | Required | Required |
|
||||
| README.md | Required | Required |
|
||||
| Code examples in comments | Generous | Generous |
|
||||
| `ExampleXxx()` test functions | Recommended | Recommended |
|
||||
| Go Playground demos | Recommended | N/A (code not public) |
|
||||
| pkg.go.dev / godoc | Primary docs surface | Use `go doc` locally or internal tooling |
|
||||
| Documentation website | Large projects | Only if many teams consume the library |
|
||||
| Register in Context7/DeepWiki/etc. | Recommended | N/A |
|
||||
| llms.txt | Recommended | Optional |
|
||||
| CHANGELOG.md | Recommended | Recommended |
|
||||
| CONTRIBUTING.md | Recommended | Recommended (internal wiki may suffice) |
|
||||
|
||||
**Private libraries** should still have excellent doc comments and examples — teams rotate, people forget, and AI agents need context to help effectively. The main difference is you skip public-facing artifacts (playground, pkg.go.dev, registries).
|
||||
|
||||
---
|
||||
|
||||
## Go Playground Demos
|
||||
|
||||
Create runnable demos on the Go Playground and link them in doc comments. This lets users try your library without installing anything. Only applicable to public libraries.
|
||||
|
||||
Add a `Play:` line in the doc comment:
|
||||
|
||||
```go
|
||||
// Map applies fn to each element of the slice and returns a new slice.
|
||||
//
|
||||
// Play: https://go.dev/play/p/abc123xyz
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// doubled := Map([]int{1, 2, 3}, func(x int) int { return x * 2 })
|
||||
// // doubled: [2, 4, 6]
|
||||
func Map[T any, U any](s []T, fn func(T) U) []U {
|
||||
```
|
||||
|
||||
When the samber/go-playground-mcp tool is available, use it to create and share playground URLs. Otherwise, create them manually at <https://go.dev/play/>.
|
||||
|
||||
Guidelines for playground demos:
|
||||
|
||||
- Keep demos self-contained — include all imports and a `main()` function
|
||||
- Show the most common use case first
|
||||
- Show real-world examples
|
||||
- Print results so the output is visible when someone clicks "Run"
|
||||
- Add comments explaining what each section does
|
||||
|
||||
---
|
||||
|
||||
## Example Test Functions
|
||||
|
||||
Libraries MUST have Example test functions for exported APIs. Example functions are executable documentation. They appear in godoc and are verified by `go test`:
|
||||
|
||||
```go
|
||||
// In map_example_test.go
|
||||
|
||||
package mypackage_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/{owner}/{repo}"
|
||||
)
|
||||
|
||||
// ExampleMap demonstrates mapping over a slice.
|
||||
func ExampleMap() {
|
||||
result := mypackage.Map([]int{1, 2, 3}, func(x int) int {
|
||||
return x * 2
|
||||
})
|
||||
fmt.Println(result)
|
||||
// Output: [2 4 6]
|
||||
}
|
||||
|
||||
// ExampleMap_strings demonstrates mapping with string transformation.
|
||||
func ExampleMap_strings() {
|
||||
result := mypackage.Map([]string{"hello", "world"}, strings.ToUpper)
|
||||
fmt.Println(result)
|
||||
// Output: [HELLO WORLD]
|
||||
}
|
||||
```
|
||||
|
||||
Naming conventions:
|
||||
|
||||
- `ExampleFuncName()` — example for a package-level function
|
||||
- `ExampleTypeName()` — example for a type
|
||||
- `ExampleTypeName_MethodName()` — example for a method
|
||||
- `ExampleFuncName_suffix()` — multiple examples for the same function (suffix is lowercase)
|
||||
- `Example()` — example for the whole package
|
||||
|
||||
The `// Output:` comment MUST be included for `go test` to verify the example. Without it, the example compiles but doesn't verify output.
|
||||
|
||||
---
|
||||
|
||||
## Code Examples in Doc Comments
|
||||
|
||||
Be generous with examples in doc comments. Show common use cases, edge cases, and error handling:
|
||||
|
||||
```go
|
||||
// NewClient creates a new HTTP client with the given options.
|
||||
//
|
||||
// Example — basic client:
|
||||
//
|
||||
// client := NewClient()
|
||||
//
|
||||
// Example — with custom timeout and retries:
|
||||
//
|
||||
// client := NewClient(
|
||||
// WithTimeout(10 * time.Second),
|
||||
// WithRetries(3),
|
||||
// WithRetryBackoff(time.Second),
|
||||
// )
|
||||
//
|
||||
// Example — with authentication:
|
||||
//
|
||||
// client := NewClient(
|
||||
// WithBearerToken(os.Getenv("API_TOKEN")),
|
||||
// )
|
||||
func NewClient(opts ...Option) *Client {
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## godoc and pkg.go.dev
|
||||
|
||||
Your doc comments automatically render on [pkg.go.dev](https://pkg.go.dev) when you tag a release and someone imports your package. This is the primary documentation surface for public Go libraries.
|
||||
|
||||
**How godoc renders comments:**
|
||||
|
||||
- First sentence of each doc comment appears in the package index
|
||||
- `// Package foo provides...` appears as the package description
|
||||
- Code blocks (indented by one tab) render as formatted code
|
||||
- `# Heading` syntax (Go 1.19+) creates sections
|
||||
- `[Link text]` syntax creates hyperlinks
|
||||
- `[Identifier]` links to other symbols in the package
|
||||
- `Deprecated:` marker gets special styling
|
||||
|
||||
**For private libraries:** pkg.go.dev won't index private modules. Use `go doc` locally or run `pkgsite` on your internal network. Some teams set up a shared pkgsite instance for internal Go modules.
|
||||
|
||||
```bash
|
||||
# View docs for a specific symbol
|
||||
go doc github.com/{owner}/{repo}.FuncName
|
||||
|
||||
# View full package docs
|
||||
go doc -all github.com/{owner}/{repo}
|
||||
|
||||
# Start a local godoc server
|
||||
go get -tool golang.org/x/pkgsite/cmd/pkgsite@latest
|
||||
go tool pkgsite -http=:6060
|
||||
# Then open http://localhost:6060
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Documentation Website
|
||||
|
||||
For larger libraries or frameworks, consider a dedicated documentation website.
|
||||
|
||||
### Recommended Frameworks
|
||||
|
||||
- **Docusaurus** (React-based) — best for large projects, supports versioning natively
|
||||
- **MkDocs Material** (Python-based) — simpler setup, great search, clean design
|
||||
|
||||
Both can be deployed on Vercel.
|
||||
|
||||
### Recommended Sections
|
||||
|
||||
Follow the [Diataxis framework](https://diataxis.fr/) for organizing documentation:
|
||||
|
||||
| Section | Purpose | Example |
|
||||
| --- | --- | --- |
|
||||
| Getting Started | First steps, installation, hello world | "Install and run your first query in 5 minutes" |
|
||||
| Tutorial | Step-by-step learning | "Build a REST API with authentication" |
|
||||
| How-to Guides | Task-oriented recipes | "How to configure connection pooling" |
|
||||
| Reference | Complete API documentation | Auto-generated from godoc |
|
||||
| Deep dive / internals | Conceptual understanding | "How the scheduler algorithm works" |
|
||||
|
||||
### llms.txt
|
||||
|
||||
Add a `llms.txt` file at the repository root to help AI agents understand your project. Copy the template from [templates/llms.txt](./templates/llms.txt).
|
||||
|
||||
This is an emerging convention for making projects AI-friendly. Place it alongside your README.
|
||||
|
||||
### Register for Discoverability
|
||||
|
||||
Make your library findable by AI agents and documentation aggregators:
|
||||
|
||||
- **Context7** — <https://context7.com> — submit your library for inclusion in AI-accessible documentation
|
||||
- **DeepWiki** — <https://deepwiki.com> — auto-generates wiki-style docs from GitHub repos
|
||||
- **OpenDeep** — <https://opendeep.wiki> — open documentation platform for AI consumption
|
||||
- **zRead** — <https://zread.ai> — developer documentation reader
|
||||
@@ -0,0 +1,115 @@
|
||||
# Project Documentation
|
||||
|
||||
→ See `samber/cc-skills-golang@golang-continuous-integration` skill for automating changelog generation and release workflows.
|
||||
|
||||
## README.md
|
||||
|
||||
A LICENSE file MUST exist in every project. A README is the front page of your project. Make it simple, clear, and scannable. A copy-paste template with empty sections is available at [templates/README.md](./templates/README.md).
|
||||
|
||||
### Section Order
|
||||
|
||||
Follow this exact order (all sections are in the template):
|
||||
|
||||
1. **Title** — project name as `# heading`
|
||||
2. **Badges** — shields.io pictograms (Go version, license, CI, coverage, Go Report Card)
|
||||
3. **Summary** — 1-2 sentences explaining what the project does
|
||||
4. **Demo** — code snippet (libraries), GIF/video (CLIs), or screenshot (web UIs)
|
||||
5. **Getting Started** — installation + minimal working example
|
||||
6. **Features / Specification** — the longest section, organized by feature area
|
||||
7. **Contributing** — link to CONTRIBUTING.md or inline if very short
|
||||
8. **License** — license name + link
|
||||
|
||||
The template includes commented-out sections for applications (binary download table, Docker, Homebrew) that you can uncomment as needed.
|
||||
|
||||
---
|
||||
|
||||
## CONTRIBUTING.md
|
||||
|
||||
The goal: a new contributor should be able to clone the repo, make a change, and run the tests **in under 10 minutes**. If your project takes longer, add tooling to fix that.
|
||||
|
||||
Copy the template from [templates/CONTRIBUTING.md](./templates/CONTRIBUTING.md).
|
||||
|
||||
### The 10-Minute Rule
|
||||
|
||||
If setup takes more than 10 minutes, add these improvements:
|
||||
|
||||
| Problem | Solution |
|
||||
| --- | --- |
|
||||
| Complex build steps | Add a `Makefile` with `make build`, `make test`, `make lint` |
|
||||
| External service dependencies | Add `docker-compose.yml` for local dev |
|
||||
| Inconsistent dev environments | Add `.devcontainer/` for VS Code devcontainers |
|
||||
| Slow test suite | Separate unit tests (fast) from integration tests (build tags) |
|
||||
| Missing documentation | Add `make help` that lists available targets |
|
||||
|
||||
---
|
||||
|
||||
## Changelog
|
||||
|
||||
CHANGELOG MUST be updated for every release. Track notable changes for each release. Use [Keep a Changelog](https://keepachangelog.com/) format. Copy the template from [templates/CHANGELOG.md](./templates/CHANGELOG.md).
|
||||
|
||||
### Format
|
||||
|
||||
```markdown
|
||||
## [1.2.0] - 2026-03-08
|
||||
|
||||
### Added
|
||||
|
||||
- New `WithTimeout` option for client configuration
|
||||
|
||||
### Changed
|
||||
|
||||
- Improved retry logic to use exponential backoff
|
||||
|
||||
### Fixed
|
||||
|
||||
- Race condition in connection pool under heavy load
|
||||
|
||||
### Deprecated
|
||||
|
||||
- `SetTimeout()` method — use `WithTimeout()` option instead
|
||||
|
||||
[1.2.0]: https://github.com/{owner}/{repo}/compare/v1.1.0...v1.2.0
|
||||
```
|
||||
|
||||
### Change Categories
|
||||
|
||||
- **Added** — new features
|
||||
- **Changed** — changes in existing functionality
|
||||
- **Deprecated** — features that will be removed
|
||||
- **Removed** — removed features
|
||||
- **Fixed** — bug fixes
|
||||
- **Security** — vulnerability fixes
|
||||
|
||||
### GitHub Releases as Alternative
|
||||
|
||||
For simpler projects, GitHub Releases can replace a CHANGELOG file. GoReleaser auto-generates release notes from git commits.
|
||||
|
||||
---
|
||||
|
||||
## Distribution
|
||||
|
||||
**YOU MUST offer multiple installation paths** (binaries, containers, APT/Homebrew/... package managers, source). Because:
|
||||
|
||||
- Each installation method eliminates friction for a different user segment
|
||||
- Users adopt tools that fit their workflow, not tools that force workflow changes
|
||||
- A single installation path is a hidden tax on adoption—DevOps engineers skip tools requiring npm, macOS developers skip tools without Homebrew
|
||||
- Tools users _want to_ use spread faster than tools users _have to_ accommodate
|
||||
|
||||
### Dockerfile Best Practices
|
||||
|
||||
Use multi-stage builds with a minimal final image:
|
||||
|
||||
```dockerfile
|
||||
# Build stage
|
||||
FROM golang:1.26-alpine AS builder
|
||||
WORKDIR /app
|
||||
COPY go.mod go.sum ./
|
||||
RUN go mod download
|
||||
COPY . .
|
||||
RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o /app/binary ./cmd/server
|
||||
|
||||
# Final stage
|
||||
FROM gcr.io/distroless/static-debian12:nonroot
|
||||
COPY --from=builder /app/binary /binary
|
||||
ENTRYPOINT ["/binary"]
|
||||
```
|
||||
Reference in New Issue
Block a user