golang现代化Go应用开发样板与最佳实践插件库modern-go-application的使用

Golang现代化Go应用开发样板与最佳实践插件库modern-go-application的使用

Modern Go Application

Mentioned in Awesome Go Go Report Card go.dev reference

GitHub Workflow Status CircleCI Gitlab

Go应用程序样板和示例,应用现代实践

这个仓库尝试收集使用Go语言进行应用程序开发的最佳实践。除了语言特定的细节外,它还实现了各种与语言无关的实践。

Modern Go Application涉及的一些领域:

  • 架构
  • 包结构
  • 应用程序构建
  • 测试
  • 配置
  • 运行应用程序(例如在Docker中)
  • 开发环境/体验
  • 遥测

为了帮助采用这些实践,这个仓库还作为新应用程序的样板。

特性

  • 配置(使用spf13/viper)
  • 日志记录(使用logur.dev/logur和sirupsen/logrus)
  • 错误处理(使用emperror.dev/emperror)
  • 使用Prometheus和Jaeger(通过OpenCensus)的指标和追踪
  • 健康检查(使用AppsFlyer/go-sundheit)
  • 优雅重启(使用cloudflare/tableflip)和关闭
  • 支持多个服务器/守护进程实例(使用oklog/run)
  • 消息传递(使用ThreeDotsLabs/watermill)
  • MySQL数据库连接(使用go-sql-driver/mysql)

入门指南

要从样板创建新应用程序,请将此仓库克隆到您的GOPATH中,然后执行以下操作:

chmod +x init.sh && ./init.sh
? Package name (github.com/sagikazarmark/modern-go-application)
? Project name (modern-go-application)
? Binary name (modern-go-application)
? Service name (modern-go-application)
? Friendly service name (Modern Go Application)
? Update README (Y/n)
? Remove init script (y/N) y

它会将仓库中的每个导入路径和名称更新为您项目的值。审查并提交更改。

负载生成

为了测试或演示应用程序,它附带了一个简单的负载生成工具。您可以使用它来测试示例端点并生成一些负载(例如为了用数据填充仪表板)。

示例代码

以下是一个使用modern-go-application的简单示例:

package main

import (
	"context"
	"log"
	"os"
	"os/signal"
	"syscall"

	"github.com/sagikazarmark/modern-go-application/pkg/app"
	"github.com/sagikazarmark/modern-go-application/pkg/buildinfo"
)

func main() {
	ctx := context.Background()
	
	// 创建应用实例
	application := app.New(
		app.WithVersion(buildinfo.Version()),
		app.WithBuildDate(buildinfo.Date()),
		app.WithCommit(buildinfo.Commit()),
	)
	
	// 设置信号处理
	signals := make(chan os.Signal, 1)
	signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM)
	
	// 启动应用
	err := application.Run(ctx)
	if err != nil {
		log.Fatal(err)
	}
	
	// 等待终止信号
	<-signals
	
	// 优雅关闭
	err = application.Close()
	if err != nil {
		log.Fatal(err)
	}
}

配置示例

package config

import (
	"github.com/spf13/viper"
)

type Config struct {
	Server struct {
		Port int
	}
	Database struct {
		Host     string
		Port     int
		User     string
		Password string
		Name     string
	}
}

func Load() (*Config, error) {
	viper.SetConfigName("config")
	viper.AddConfigPath(".")
	viper.AutomaticEnv()
	
	err := viper.ReadInConfig()
	if err != nil {
		return nil, err
	}
	
	var cfg Config
	err = viper.Unmarshal(&cfg)
	if err != nil {
		return nil, err
	}
	
	return &cfg, nil
}

日志记录示例

package main

import (
	"context"
	
	"logur.dev/logur"
	"logur.dev/logur/convenience"
)

func main() {
	// 创建日志记录器
	logger := logur.NewNoopLogger() // 在生产中使用实际的日志实现
	
	// 使用便利函数
	convenience.Info(logger, "Application starting")
	
	// 使用结构化日志
	logger.Info("User logged in", map[string]interface{}{
		"user": "john.doe",
		"ip":   "192.168.1.1",
	})
	
	// 带上下文的日志
	ctx := logur.WithFields(context.Background(), map[string]interface{}{
		"request_id": "12345",
	})
	
	logger.InfoContext(ctx, "Processing request")
}

许可证

MIT许可证。


更多关于golang现代化Go应用开发样板与最佳实践插件库modern-go-application的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang现代化Go应用开发样板与最佳实践插件库modern-go-application的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


现代化Go应用开发样板与最佳实践:modern-go-application

现代Go应用开发需要遵循一系列最佳实践来确保代码质量、可维护性和可扩展性。modern-go-application是一个概念性的样板项目,集成了现代Go开发的各种最佳实践和常用工具链。

核心组件与最佳实践

1. 项目结构

// 推荐的项目结构
project/
├── cmd/              // 主应用程序入口
│   └── app/
│       └── main.go
├── internal/         // 私有应用程序代码
│   ├── config/       // 配置管理
│   ├── handler/      // HTTP处理器
│   ├── repository/   // 数据访问层
│   └── service/      // 业务逻辑层
├── pkg/              // 可公开的库代码
├── api/              // API定义(Swagger/Protobuf等)
├── migrations/       // 数据库迁移
├── test/             // 测试代码
├── go.mod
└── go.sum

2. 配置管理

使用Viper进行配置管理:

package config

import (
	"github.com/spf13/viper"
	"log"
)

type Config struct {
	Server   ServerConfig
	Database DatabaseConfig
}

func LoadConfig(path string) (*Config, error) {
	viper.SetConfigFile(path)
	
	if err := viper.ReadInConfig(); err != nil {
		return nil, err
	}
	
	var cfg Config
	if err := viper.Unmarshal(&cfg); err != nil {
		return nil, err
	}
	
	return &cfg, nil
}

3. Web框架

推荐使用Chi或Gin作为路由框架:

// 使用Chi的示例
package main

import (
	"net/http"
	"github.com/go-chi/chi/v5"
	"github.com/go-chi/chi/v5/middleware"
)

func main() {
	r := chi.NewRouter()
	
	// 中间件
	r.Use(middleware.Logger)
	r.Use(middleware.Recoverer)
	
	// 路由
	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("Welcome!"))
	})
	
	http.ListenAndServe(":8080", r)
}

4. 依赖注入

使用Wire进行编译时依赖注入:

// wire.go
package main

import (
	"github.com/google/wire"
	"your-app/internal/config"
	"your-app/internal/repository"
	"your-app/internal/service"
	"your-app/internal/handler"
)

func InitializeApp() (*App, error) {
	wire.Build(
		config.LoadConfig,
		repository.NewUserRepository,
		service.NewUserService,
		handler.NewUserHandler,
		NewApp,
	)
	return &App{}, nil
}

5. 日志记录

使用Zap或Logrus进行结构化日志记录:

package logger

import (
	"go.uber.org/zap"
)

var Logger *zap.Logger

func InitLogger() {
	var err error
	Logger, err = zap.NewProduction()
	if err != nil {
		panic(err)
	}
	defer Logger.Sync()
}

// 使用示例
Logger.Info("Server started",
	zap.String("port", "8080"),
	zap.String("env", "production"),
)

6. 数据库访问

使用GORM或sqlx进行数据库访问:

package repository

import (
	"gorm.io/gorm"
	"your-app/internal/model"
)

type UserRepository struct {
	db *gorm.DB
}

func NewUserRepository(db *gorm.DB) *UserRepository {
	return &UserRepository{db: db}
}

func (r *UserRepository) FindByID(id uint) (*model.User, error) {
	var user model.User
	if err := r.db.First(&user, id).Error; err != nil {
		return nil, err
	}
	return &user, nil
}

7. 测试

使用Testify进行测试:

package service_test

import (
	"testing"
	"github.com/stretchr/testify/assert"
	"your-app/internal/service"
	"your-app/internal/repository/mocks"
)

func TestUserService_GetUser(t *testing.T) {
	mockRepo := new(mocks.UserRepository)
	service := service.NewUserService(mockRepo)
	
	// 设置mock行为
	mockRepo.On("FindByID", uint(1)).Return(&model.User{ID: 1, Name: "John"}, nil)
	
	user, err := service.GetUser(1)
	
	assert.NoError(t, err)
	assert.Equal(t, "John", user.Name)
	mockRepo.AssertExpectations(t)
}

8. API文档

使用Swagger生成API文档:

// main.go
package main

import (
	_ "your-app/docs" // 生成的swagger文档
	"github.com/swaggo/http-swagger"
)

// @title Your API
// @version 1.0
// @description This is a sample server.
func main() {
	r := chi.NewRouter()
	
	// Swagger UI
	r.Get("/swagger/*", httpSwagger.WrapHandler)
	
	// ...其他路由
}

现代化工具链

  1. 代码格式化: gofmt, goimports
  2. 静态分析: golangci-lint
  3. 测试覆盖率: go test -cover
  4. 性能分析: pprof
  5. 构建工具: Makefile或Taskfile
  6. 容器化: Docker多阶段构建
  7. CI/CD: GitHub Actions, GitLab CI

示例Makefile

.PHONY: build test lint run

build:
	go build -o bin/app cmd/app/main.go

test:
	go test -v -cover ./...

lint:
	golangci-lint run

run: build
	./bin/app

总结

现代化Go应用开发应该关注:

  1. 清晰的项目结构
  2. 模块化设计
  3. 依赖注入
  4. 配置管理
  5. 结构化日志
  6. 完善的测试
  7. 自动化工具链
  8. 良好的文档

虽然modern-go-application不是一个具体的库,但遵循这些最佳实践可以帮助你构建健壮、可维护的Go应用程序。你可以根据项目需求选择具体的实现库,如Viper、Zap、GORM等。

回到顶部