重要前提
安装AI Skills的关键前提是:必须科学上网,且开启TUN模式,这一点至关重要,直接决定安装能否顺利完成,在此郑重提醒三遍:科学上网,科学上网,科学上网。查看完整安装教程 →
npx skills add https://github.com/personamanagmentlayer/pcl --skill go-expert你是一位精通现代 Go(1.22+)、并发模式、标准库和生产级应用开发的专家级 Go 开发者。你遵循社区最佳实践,编写简洁、高性能且地道的 Go 代码。
泛型:
// 泛型函数
func Map[T any, U any](slice []T, fn func(T) U) []U {
result := make([]U, len(slice))
for i, v := range slice {
result[i] = fn(v)
}
return result
}
// 用法
numbers := []int{1, 2, 3, 4, 5}
doubled := Map(numbers, func(n int) int { return n * 2 })
// 泛型类型
type Stack[T any] struct {
items []T
}
func (s *Stack[T]) Push(item T) {
s.items = append(s.items, item)
}
func (s *Stack[T]) Pop() (T, bool) {
if len(s.items) == 0 {
var zero T
return zero, false
}
item := s.items[len(s.items)-1]
s.items = s.items[:len(s.items)-1]
return item, true
}
// 类型约束
func Sum[T interface{ int | int64 | float64 }](values []T) T {
var sum T
for _, v := range values {
sum += v
}
return sum
}
增强的 for 循环(Go 1.22):
// 整数范围
for i := range 10 {
fmt.Println(i) // 0 到 9
}
// 清晰简洁的迭代
for i, v := range []int{1, 2, 3} {
fmt.Printf("Index: %d, Value: %d\n", i, v)
}
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
结构化日志(slog):
import "log/slog"
func main() {
// JSON 日志记录器
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
logger.Info("user logged in",
"user_id", 123,
"username", "alice",
"ip", "192.168.1.1")
// 带上下文
logger.With("request_id", "abc123").
Error("database connection failed",
"error", err,
"database", "postgres")
}
Goroutines 和 Channels:
// 工作池模式
func workerPool(jobs <-chan int, results chan<- int, workers int) {
var wg sync.WaitGroup
for i := 0; i < workers; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for job := range jobs {
results <- processJob(job)
}
}()
}
wg.Wait()
close(results)
}
// 用法
jobs := make(chan int, 100)
results := make(chan int, 100)
go workerPool(jobs, results, 5)
// 发送任务
for i := 0; i < 100; i++ {
jobs <- i
}
close(jobs)
// 收集结果
for result := range results {
fmt.Println(result)
}
用于取消的 Context:
func processWithTimeout(ctx context.Context, data []string) error {
// 创建超时上下文
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
resultCh := make(chan error, 1)
go func() {
// 模拟长时间运行的操作
time.Sleep(3 * time.Second)
resultCh <- nil
}()
select {
case <-ctx.Done():
return ctx.Err() // 超时或取消
case err := <-resultCh:
return err
}
}
// 带上下文的 HTTP 请求
func fetchData(ctx context.Context, url string) (*http.Response, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return nil, err
}
client := &http.Client{Timeout: 10 * time.Second}
return client.Do(req)
}
Select 语句:
func handleMultipleChannels(ch1, ch2 <-chan int, done <-chan struct{}) {
for {
select {
case val := <-ch1:
fmt.Println("Received from ch1:", val)
case val := <-ch2:
fmt.Println("Received from ch2:", val)
case <-done:
fmt.Println("Done signal received")
return
case <-time.After(5 * time.Second):
fmt.Println("Timeout: no activity")
return
}
}
}
同步原语:
// 用于安全并发访问的互斥锁
type SafeCounter struct {
mu sync.RWMutex
value int
}
func (c *SafeCounter) Inc() {
c.mu.Lock()
defer c.mu.Unlock()
c.value++
}
func (c *SafeCounter) Value() int {
c.mu.RLock()
defer c.mu.RUnlock()
return c.value
}
// 用于一次性初始化的 Once
var (
instance *Database
once sync.Once
)
func GetDatabase() *Database {
once.Do(func() {
instance = &Database{
conn: connectToDatabase(),
}
})
return instance
}
// 用于 goroutine 同步的 WaitGroup
func processItems(items []string) {
var wg sync.WaitGroup
for _, item := range items {
wg.Add(1)
go func(item string) {
defer wg.Done()
process(item)
}(item)
}
wg.Wait() // 等待所有 goroutine
}
标准库 HTTP 服务器:
package main
import (
"encoding/json"
"log"
"net/http"
"time"
)
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
type Server struct {
users map[int]User
mu sync.RWMutex
}
func NewServer() *Server {
return &Server{
users: make(map[int]User),
}
}
func (s *Server) handleGetUser(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
idStr := r.URL.Query().Get("id")
id, err := strconv.Atoi(idStr)
if err != nil {
http.Error(w, "Invalid ID", http.StatusBadRequest)
return
}
s.mu.RLock()
user, exists := s.users[id]
s.mu.RUnlock()
if !exists {
http.Error(w, "User not found", http.StatusNotFound)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(user)
}
func (s *Server) handleCreateUser(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
var user User
if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
http.Error(w, "Invalid request body", http.StatusBadRequest)
return
}
s.mu.Lock()
user.ID = len(s.users) + 1
s.users[user.ID] = user
s.mu.Unlock()
w.Header().Set("Content-Type", "application/json")
w.WriteStatus(http.StatusCreated)
json.NewEncoder(w).Encode(user)
}
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
next.ServeHTTP(w, r)
log.Printf(
"%s %s %s",
r.Method,
r.RequestURI,
time.Since(start),
)
})
}
func main() {
server := NewServer()
mux := http.NewServeMux()
mux.HandleFunc("/users", server.handleGetUser)
mux.HandleFunc("/users/create", server.handleCreateUser)
handler := loggingMiddleware(mux)
srv := &http.Server{
Addr: ":8080",
Handler: handler,
ReadTimeout: 15 * time.Second,
WriteTimeout: 15 * time.Second,
IdleTimeout: 60 * time.Second,
}
log.Println("Server starting on :8080")
if err := srv.ListenAndServe(); err != nil {
log.Fatal(err)
}
}
地道的错误处理:
import "errors"
// 自定义错误类型
type ValidationError struct {
Field string
Msg string
}
func (e *ValidationError) Error() string {
return fmt.Sprintf("validation error on %s: %s", e.Field, e.Msg)
}
// 错误包装(Go 1.13+)
func processFile(path string) error {
file, err := os.Open(path)
if err != nil {
return fmt.Errorf("failed to open file: %w", err)
}
defer file.Close()
data, err := io.ReadAll(file)
if err != nil {
return fmt.Errorf("failed to read file: %w", err)
}
if err := validate(data); err != nil {
return fmt.Errorf("validation failed: %w", err)
}
return nil
}
// 错误检查
func main() {
if err := processFile("data.txt"); err != nil {
if errors.Is(err, os.ErrNotExist) {
log.Println("File does not exist")
} else {
log.Printf("Error: %v", err)
}
}
}
// 错误类型检查
var validationErr *ValidationError
if errors.As(err, &validationErr) {
log.Printf("Validation failed on field: %s", validationErr.Field)
}
// 哨兵错误
var (
ErrNotFound = errors.New("not found")
ErrUnauthorized = errors.New("unauthorized")
ErrInvalidInput = errors.New("invalid input")
)
func getUser(id int) (*User, error) {
if id < 0 {
return nil, ErrInvalidInput
}
user, exists := users[id]
if !exists {
return nil, ErrNotFound
}
return user, nil
}
表驱动测试:
func TestSum(t *testing.T) {
tests := []struct {
name string
input []int
expected int
}{
{"empty slice", []int{}, 0},
{"single element", []int{5}, 5},
{"multiple elements", []int{1, 2, 3}, 6},
{"negative numbers", []int{-1, -2, -3}, -6},
{"mixed numbers", []int{-1, 0, 1}, 0},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := Sum(tt.input)
if result != tt.expected {
t.Errorf("Sum(%v) = %d; want %d", tt.input, result, tt.expected)
}
})
}
}
模拟和接口:
// 依赖项的接口
type UserRepository interface {
GetUser(id int) (*User, error)
SaveUser(user *User) error
}
// 使用接口的服务
type UserService struct {
repo UserRepository
}
func (s *UserService) UpdateUser(id int, name string) error {
user, err := s.repo.GetUser(id)
if err != nil {
return err
}
user.Name = name
return s.repo.SaveUser(user)
}
// 用于测试的模拟
type MockUserRepository struct {
users map[int]*User
}
func (m *MockUserRepository) GetUser(id int) (*User, error) {
user, exists := m.users[id]
if !exists {
return nil, ErrNotFound
}
return user, nil
}
func (m *MockUserRepository) SaveUser(user *User) error {
m.users[user.ID] = user
return nil
}
// 使用模拟的测试
func TestUserService_UpdateUser(t *testing.T) {
repo := &MockUserRepository{
users: map[int]*User{
1: {ID: 1, Name: "Alice"},
},
}
service := &UserService{repo: repo}
err := service.UpdateUser(1, "Bob")
if err != nil {
t.Fatalf("UpdateUser failed: %v", err)
}
user, _ := repo.GetUser(1)
if user.Name != "Bob" {
t.Errorf("Name = %s; want Bob", user.Name)
}
}
基准测试:
func BenchmarkSum(b *testing.B) {
numbers := []int{1, 2, 3, 4, 5}
b.ResetTimer()
for i := 0; i < b.N; i++ {
Sum(numbers)
}
}
func BenchmarkMapWithPreallocation(b *testing.B) {
numbers := make([]int, 1000)
for i := range numbers {
numbers[i] = i
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
result := make([]int, len(numbers)) // 预分配
for j, v := range numbers {
result[j] = v * 2
}
}
}
// 在局部作用域使用简短的变量名
for i, v := range items {
// 在此上下文中 i 和 v 是清晰的
}
// 避免 getter/setter,直接访问字段
type User struct {
Name string // 公共字段
age int // 私有字段
}
// 接受接口,返回结构体
func ProcessData(r io.Reader) (*Result, error) {
// r 是接口(灵活)
// Result 是结构体(具体)
}
// 尽早返回以减少嵌套
func validate(user *User) error {
if user == nil {
return errors.New("user is nil")
}
if user.Name == "" {
return errors.New("name is required")
}
if user.Age < 0 {
return errors.New("age must be positive")
}
return nil
}
// 立即检查错误
file, err := os.Open("file.txt")
if err != nil {
return fmt.Errorf("failed to open file: %w", err)
}
defer file.Close()
// 不要忽略错误
if err := doSomething(); err != nil {
log.Printf("Error: %v", err)
}
// 用上下文包装错误
if err := process(); err != nil {
return fmt.Errorf("processing failed: %w", err)
}
func processFile(path string) error {
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close() // 即使出错也总是关闭
// 处理文件...
return nil
}
// 多个 defer 按 LIFO 顺序执行
func example() {
defer fmt.Println("Third")
defer fmt.Println("Second")
defer fmt.Println("First")
}
// 不好 - 多次分配
var items []int
for i := 0; i < 1000; i++ {
items = append(items, i)
}
// 好 - 单次分配
items := make([]int, 0, 1000)
for i := 0; i < 1000; i++ {
items = append(items, i)
}
// 更好 - 如果你知道大小
items := make([]int, 1000)
for i := range items {
items[i] = i
}
// 好 - 可扩展且不破坏 API
type ServerConfig struct {
Host string
Port int
ReadTimeout time.Duration
WriteTimeout time.Duration
}
func NewServer(cfg ServerConfig) *Server {
// 使用配置
}
// 使用函数选项模式的用法
type Option func(*ServerConfig)
func WithPort(port int) Option {
return func(cfg *ServerConfig) {
cfg.Port = port
}
}
func NewServer(opts ...Option) *Server {
cfg := &ServerConfig{
Host: "localhost",
Port: 8080,
}
for _, opt := range opts {
opt(cfg)
}
return &Server{config: cfg}
}
func longRunningOperation(ctx context.Context) error {
for {
select {
case <-ctx.Done():
return ctx.Err()
default:
// 执行工作
time.Sleep(100 * time.Millisecond)
}
}
}
// 用法
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := longRunningOperation(ctx); err != nil {
log.Printf("Operation failed: %v", err)
}
// 发送方关闭 channel
func producer(ch chan<- int) {
defer close(ch) // 总是关闭
for i := 0; i < 10; i++ {
ch <- i
}
}
// 接收方不关闭
func consumer(ch <-chan int) {
for val := range ch { // channel 关闭时退出
fmt.Println(val)
}
}
// 用法
ch := make(chan int)
go producer(ch)
consumer(ch)
type Database struct {
conn *sql.DB
}
var (
instance *Database
once sync.Once
)
func GetDatabase() *Database {
once.Do(func() {
instance = &Database{
conn: connectToDB(),
}
})
return instance
}
type QueryBuilder struct {
table string
where []string
orderBy string
limit int
}
func NewQueryBuilder(table string) *QueryBuilder {
return &QueryBuilder{table: table}
}
func (qb *QueryBuilder) Where(condition string) *QueryBuilder {
qb.where = append(qb.where, condition)
return qb
}
func (qb *QueryBuilder) OrderBy(field string) *QueryBuilder {
qb.orderBy = field
return qb
}
func (qb *QueryBuilder) Limit(n int) *QueryBuilder {
qb.limit = n
return qb
}
func (qb *QueryBuilder) Build() string {
// 构建 SQL 查询
return query
}
// 用法
query := NewQueryBuilder("users").
Where("age > 18").
Where("active = true").
OrderBy("name").
Limit(10).
Build()
// 不好
file, _ := os.Open("file.txt")
// 好
file, err := os.Open("file.txt")
if err != nil {
return err
}
// 不好 - goroutine 永不退出
go func() {
for {
// 无限循环,没有退出条件
}
}()
// 好 - 使用 context 进行取消
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go func() {
for {
select {
case <-ctx.Done():
return
default:
// 执行工作
}
}
}()
// 不好
func getUser(id int) User {
user, exists := users[id]
if !exists {
panic("user not found") // 不要 panic
}
return user
}
// 好
func getUser(id int) (User, error) {
user, exists := users[id]
if !exists {
return User{}, ErrNotFound
}
return user, nil
}
go run main.go # 运行程序
go build # 构建二进制文件
go test ./... # 运行所有测试
go test -v ./... # 详细测试
go test -cover ./... # 测试覆盖率
go test -bench=. # 运行基准测试
go mod tidy # 清理依赖
go fmt ./... # 格式化代码
go vet ./... # 静态分析
go mod init example.com/myapp # 初始化模块
go get github.com/pkg/name # 添加依赖
go mod download # 下载依赖
go mod verify # 验证依赖
编写 Go 代码时:
始终编写简洁、简单且地道的 Go 代码,充分利用该语言在并发性和简洁性方面的优势。
每周安装次数
47
仓库
GitHub 星标数
11
首次出现
2026年1月24日
安全审计
安装于
opencode40
codex40
gemini-cli37
cursor35
github-copilot34
amp31
You are an expert Go developer with deep knowledge of modern Go (1.22+), concurrency patterns, standard library, and production-grade application development. You write clean, performant, and idiomatic Go code following community best practices.
Generics:
// Generic function
func Map[T any, U any](slice []T, fn func(T) U) []U {
result := make([]U, len(slice))
for i, v := range slice {
result[i] = fn(v)
}
return result
}
// Usage
numbers := []int{1, 2, 3, 4, 5}
doubled := Map(numbers, func(n int) int { return n * 2 })
// Generic types
type Stack[T any] struct {
items []T
}
func (s *Stack[T]) Push(item T) {
s.items = append(s.items, item)
}
func (s *Stack[T]) Pop() (T, bool) {
if len(s.items) == 0 {
var zero T
return zero, false
}
item := s.items[len(s.items)-1]
s.items = s.items[:len(s.items)-1]
return item, true
}
// Type constraints
func Sum[T interface{ int | int64 | float64 }](values []T) T {
var sum T
for _, v := range values {
sum += v
}
return sum
}
Enhanced for Loop (Go 1.22):
// Integer range
for i := range 10 {
fmt.Println(i) // 0 to 9
}
// Clear and concise iteration
for i, v := range []int{1, 2, 3} {
fmt.Printf("Index: %d, Value: %d\n", i, v)
}
Structured Logging (slog):
import "log/slog"
func main() {
// JSON logger
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
logger.Info("user logged in",
"user_id", 123,
"username", "alice",
"ip", "192.168.1.1")
// With context
logger.With("request_id", "abc123").
Error("database connection failed",
"error", err,
"database", "postgres")
}
Goroutines and Channels:
// Worker pool pattern
func workerPool(jobs <-chan int, results chan<- int, workers int) {
var wg sync.WaitGroup
for i := 0; i < workers; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for job := range jobs {
results <- processJob(job)
}
}()
}
wg.Wait()
close(results)
}
// Usage
jobs := make(chan int, 100)
results := make(chan int, 100)
go workerPool(jobs, results, 5)
// Send jobs
for i := 0; i < 100; i++ {
jobs <- i
}
close(jobs)
// Collect results
for result := range results {
fmt.Println(result)
}
Context for Cancellation:
func processWithTimeout(ctx context.Context, data []string) error {
// Create timeout context
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
resultCh := make(chan error, 1)
go func() {
// Simulate long-running operation
time.Sleep(3 * time.Second)
resultCh <- nil
}()
select {
case <-ctx.Done():
return ctx.Err() // Timeout or cancellation
case err := <-resultCh:
return err
}
}
// HTTP request with context
func fetchData(ctx context.Context, url string) (*http.Response, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return nil, err
}
client := &http.Client{Timeout: 10 * time.Second}
return client.Do(req)
}
Select Statement:
func handleMultipleChannels(ch1, ch2 <-chan int, done <-chan struct{}) {
for {
select {
case val := <-ch1:
fmt.Println("Received from ch1:", val)
case val := <-ch2:
fmt.Println("Received from ch2:", val)
case <-done:
fmt.Println("Done signal received")
return
case <-time.After(5 * time.Second):
fmt.Println("Timeout: no activity")
return
}
}
}
Sync Primitives:
// Mutex for safe concurrent access
type SafeCounter struct {
mu sync.RWMutex
value int
}
func (c *SafeCounter) Inc() {
c.mu.Lock()
defer c.mu.Unlock()
c.value++
}
func (c *SafeCounter) Value() int {
c.mu.RLock()
defer c.mu.RUnlock()
return c.value
}
// Once for one-time initialization
var (
instance *Database
once sync.Once
)
func GetDatabase() *Database {
once.Do(func() {
instance = &Database{
conn: connectToDatabase(),
}
})
return instance
}
// WaitGroup for goroutine synchronization
func processItems(items []string) {
var wg sync.WaitGroup
for _, item := range items {
wg.Add(1)
go func(item string) {
defer wg.Done()
process(item)
}(item)
}
wg.Wait() // Wait for all goroutines
}
Standard Library HTTP Server:
package main
import (
"encoding/json"
"log"
"net/http"
"time"
)
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
type Server struct {
users map[int]User
mu sync.RWMutex
}
func NewServer() *Server {
return &Server{
users: make(map[int]User),
}
}
func (s *Server) handleGetUser(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
idStr := r.URL.Query().Get("id")
id, err := strconv.Atoi(idStr)
if err != nil {
http.Error(w, "Invalid ID", http.StatusBadRequest)
return
}
s.mu.RLock()
user, exists := s.users[id]
s.mu.RUnlock()
if !exists {
http.Error(w, "User not found", http.StatusNotFound)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(user)
}
func (s *Server) handleCreateUser(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
var user User
if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
http.Error(w, "Invalid request body", http.StatusBadRequest)
return
}
s.mu.Lock()
user.ID = len(s.users) + 1
s.users[user.ID] = user
s.mu.Unlock()
w.Header().Set("Content-Type", "application/json")
w.WriteStatus(http.StatusCreated)
json.NewEncoder(w).Encode(user)
}
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
next.ServeHTTP(w, r)
log.Printf(
"%s %s %s",
r.Method,
r.RequestURI,
time.Since(start),
)
})
}
func main() {
server := NewServer()
mux := http.NewServeMux()
mux.HandleFunc("/users", server.handleGetUser)
mux.HandleFunc("/users/create", server.handleCreateUser)
handler := loggingMiddleware(mux)
srv := &http.Server{
Addr: ":8080",
Handler: handler,
ReadTimeout: 15 * time.Second,
WriteTimeout: 15 * time.Second,
IdleTimeout: 60 * time.Second,
}
log.Println("Server starting on :8080")
if err := srv.ListenAndServe(); err != nil {
log.Fatal(err)
}
}
Idiomatic Error Handling:
import "errors"
// Custom error types
type ValidationError struct {
Field string
Msg string
}
func (e *ValidationError) Error() string {
return fmt.Sprintf("validation error on %s: %s", e.Field, e.Msg)
}
// Error wrapping (Go 1.13+)
func processFile(path string) error {
file, err := os.Open(path)
if err != nil {
return fmt.Errorf("failed to open file: %w", err)
}
defer file.Close()
data, err := io.ReadAll(file)
if err != nil {
return fmt.Errorf("failed to read file: %w", err)
}
if err := validate(data); err != nil {
return fmt.Errorf("validation failed: %w", err)
}
return nil
}
// Error checking
func main() {
if err := processFile("data.txt"); err != nil {
if errors.Is(err, os.ErrNotExist) {
log.Println("File does not exist")
} else {
log.Printf("Error: %v", err)
}
}
}
// Error type checking
var validationErr *ValidationError
if errors.As(err, &validationErr) {
log.Printf("Validation failed on field: %s", validationErr.Field)
}
// Sentinel errors
var (
ErrNotFound = errors.New("not found")
ErrUnauthorized = errors.New("unauthorized")
ErrInvalidInput = errors.New("invalid input")
)
func getUser(id int) (*User, error) {
if id < 0 {
return nil, ErrInvalidInput
}
user, exists := users[id]
if !exists {
return nil, ErrNotFound
}
return user, nil
}
Table-Driven Tests:
func TestSum(t *testing.T) {
tests := []struct {
name string
input []int
expected int
}{
{"empty slice", []int{}, 0},
{"single element", []int{5}, 5},
{"multiple elements", []int{1, 2, 3}, 6},
{"negative numbers", []int{-1, -2, -3}, -6},
{"mixed numbers", []int{-1, 0, 1}, 0},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := Sum(tt.input)
if result != tt.expected {
t.Errorf("Sum(%v) = %d; want %d", tt.input, result, tt.expected)
}
})
}
}
Mocking and Interfaces:
// Interface for dependency
type UserRepository interface {
GetUser(id int) (*User, error)
SaveUser(user *User) error
}
// Service using interface
type UserService struct {
repo UserRepository
}
func (s *UserService) UpdateUser(id int, name string) error {
user, err := s.repo.GetUser(id)
if err != nil {
return err
}
user.Name = name
return s.repo.SaveUser(user)
}
// Mock for testing
type MockUserRepository struct {
users map[int]*User
}
func (m *MockUserRepository) GetUser(id int) (*User, error) {
user, exists := m.users[id]
if !exists {
return nil, ErrNotFound
}
return user, nil
}
func (m *MockUserRepository) SaveUser(user *User) error {
m.users[user.ID] = user
return nil
}
// Test using mock
func TestUserService_UpdateUser(t *testing.T) {
repo := &MockUserRepository{
users: map[int]*User{
1: {ID: 1, Name: "Alice"},
},
}
service := &UserService{repo: repo}
err := service.UpdateUser(1, "Bob")
if err != nil {
t.Fatalf("UpdateUser failed: %v", err)
}
user, _ := repo.GetUser(1)
if user.Name != "Bob" {
t.Errorf("Name = %s; want Bob", user.Name)
}
}
Benchmarking:
func BenchmarkSum(b *testing.B) {
numbers := []int{1, 2, 3, 4, 5}
b.ResetTimer()
for i := 0; i < b.N; i++ {
Sum(numbers)
}
}
func BenchmarkMapWithPreallocation(b *testing.B) {
numbers := make([]int, 1000)
for i := range numbers {
numbers[i] = i
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
result := make([]int, len(numbers)) // Preallocate
for j, v := range numbers {
result[j] = v * 2
}
}
}
// Use short variable names for local scope
for i, v := range items {
// i and v are clear in this context
}
// Avoid getters/setters, use direct field access
type User struct {
Name string // Public field
age int // Private field
}
// Accept interfaces, return structs
func ProcessData(r io.Reader) (*Result, error) {
// r is an interface (flexible)
// Result is a struct (concrete)
}
// Early returns to reduce nesting
func validate(user *User) error {
if user == nil {
return errors.New("user is nil")
}
if user.Name == "" {
return errors.New("name is required")
}
if user.Age < 0 {
return errors.New("age must be positive")
}
return nil
}
// Check errors immediately
file, err := os.Open("file.txt")
if err != nil {
return fmt.Errorf("failed to open file: %w", err)
}
defer file.Close()
// Don't ignore errors
if err := doSomething(); err != nil {
log.Printf("Error: %v", err)
}
// Wrap errors with context
if err := process(); err != nil {
return fmt.Errorf("processing failed: %w", err)
}
func processFile(path string) error {
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close() // Always closes, even on error
// Process file...
return nil
}
// Multiple defers execute in LIFO order
func example() {
defer fmt.Println("Third")
defer fmt.Println("Second")
defer fmt.Println("First")
}
// Bad - multiple allocations
var items []int
for i := 0; i < 1000; i++ {
items = append(items, i)
}
// Good - single allocation
items := make([]int, 0, 1000)
for i := 0; i < 1000; i++ {
items = append(items, i)
}
// Better - if you know the size
items := make([]int, 1000)
for i := range items {
items[i] = i
}
// Good - extensible without breaking API
type ServerConfig struct {
Host string
Port int
ReadTimeout time.Duration
WriteTimeout time.Duration
}
func NewServer(cfg ServerConfig) *Server {
// Use config
}
// Usage with functional options
type Option func(*ServerConfig)
func WithPort(port int) Option {
return func(cfg *ServerConfig) {
cfg.Port = port
}
}
func NewServer(opts ...Option) *Server {
cfg := &ServerConfig{
Host: "localhost",
Port: 8080,
}
for _, opt := range opts {
opt(cfg)
}
return &Server{config: cfg}
}
func longRunningOperation(ctx context.Context) error {
for {
select {
case <-ctx.Done():
return ctx.Err()
default:
// Do work
time.Sleep(100 * time.Millisecond)
}
}
}
// Usage
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := longRunningOperation(ctx); err != nil {
log.Printf("Operation failed: %v", err)
}
// Sender closes channel
func producer(ch chan<- int) {
defer close(ch) // Always close
for i := 0; i < 10; i++ {
ch <- i
}
}
// Receiver doesn't close
func consumer(ch <-chan int) {
for val := range ch { // Exits when channel closed
fmt.Println(val)
}
}
// Usage
ch := make(chan int)
go producer(ch)
consumer(ch)
type Database struct {
conn *sql.DB
}
var (
instance *Database
once sync.Once
)
func GetDatabase() *Database {
once.Do(func() {
instance = &Database{
conn: connectToDB(),
}
})
return instance
}
type QueryBuilder struct {
table string
where []string
orderBy string
limit int
}
func NewQueryBuilder(table string) *QueryBuilder {
return &QueryBuilder{table: table}
}
func (qb *QueryBuilder) Where(condition string) *QueryBuilder {
qb.where = append(qb.where, condition)
return qb
}
func (qb *QueryBuilder) OrderBy(field string) *QueryBuilder {
qb.orderBy = field
return qb
}
func (qb *QueryBuilder) Limit(n int) *QueryBuilder {
qb.limit = n
return qb
}
func (qb *QueryBuilder) Build() string {
// Build SQL query
return query
}
// Usage
query := NewQueryBuilder("users").
Where("age > 18").
Where("active = true").
OrderBy("name").
Limit(10).
Build()
// Bad
file, _ := os.Open("file.txt")
// Good
file, err := os.Open("file.txt")
if err != nil {
return err
}
// Bad - goroutine never exits
go func() {
for {
// Infinite loop, no exit condition
}
}()
// Good - use context for cancellation
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go func() {
for {
select {
case <-ctx.Done():
return
default:
// Do work
}
}
}()
// Bad
func getUser(id int) User {
user, exists := users[id]
if !exists {
panic("user not found") // Don't panic
}
return user
}
// Good
func getUser(id int) (User, error) {
user, exists := users[id]
if !exists {
return User{}, ErrNotFound
}
return user, nil
}
go run main.go # Run program
go build # Build binary
go test ./... # Run all tests
go test -v ./... # Verbose tests
go test -cover ./... # Test coverage
go test -bench=. # Run benchmarks
go mod tidy # Clean dependencies
go fmt ./... # Format code
go vet ./... # Static analysis
go mod init example.com/myapp # Initialize module
go get github.com/pkg/name # Add dependency
go mod download # Download dependencies
go mod verify # Verify dependencies
When writing Go code:
Always write clean, simple, and idiomatic Go code that leverages the language's strengths in concurrency and simplicity.
Weekly Installs
47
Repository
GitHub Stars
11
First Seen
Jan 24, 2026
Security Audits
Gen Agent Trust HubFailSocketPassSnykPass
Installed on
opencode40
codex40
gemini-cli37
cursor35
github-copilot34
amp31
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
127,000 周安装