Files
workspace/notes/后端开发/golang/项目骨架.md
T
2025-10-31 17:28:45 +08:00

6.3 KiB
Raw Blame History

项目结构

myapp/
├── cmd/                  # 启动程序的入口(main.go 通常放在这里)
│   └── myapp/
│       └── main.go       # 主程序入口
│
├── internal/             # 内部模块,不能被外部引入
│   ├── app/              # 应用逻辑层(服务、用例)
│   ├── config/           # 配置读取相关逻辑(如viper/yaml/env)
│   ├── handler/          # HTTP handler(路由处理函数)
│   ├── repository/       # 数据访问层(如数据库、缓存)
│   ├── service/          # 业务逻辑层
│   ├── model/            # 实体结构体、DTO、表结构等
│   ├── logger/           # 日志封装
│   ├── utils/            # 工具函数
│   └── middleware/       # HTTP中间件

├── go.mod                # Go module 定义
├── go.sum                # Go module 校验文件
└── README.md             # 项目说明

假设有 用户服务(8080) 和 订单服务(8081):

project/
├── cmd/
│   ├── user-service/      # main.go,启动用户服务,监听 8080
│   └── order-service/     # main.go,启动订单服务,监听 8081
│
├── internal/              # 内部模块,不对外暴露
│   ├── user/              # 用户服务模块
│   │   ├── handler.go     # HTTP 接口
│   │   └── service.go     # 业务逻辑
│   ├── order/             # 订单服务模块
│   │   ├── handler.go
│   │   └── service.go
│   └── database/          # 数据库连接封装
│
├── pkg/                   # 可复用公共库(跨服务)
│   ├── logger/            # 日志封装
│   ├── utils/             # 工具函数
│   └── types/             # 公共类型定义
│
└── configs/               # 各服务配置
    ├── user.yaml
    └── order.yaml

项目配置

集成 fasthttp

go get -u github.com/valyala/fasthttp

测试

package main

import (
	"fmt"
	"github.com/valyala/fasthttp"
)

func main() {
	requestHandler := func(ctx *fasthttp.RequestCtx) {
		fmt.Fprintf(ctx, "Hello, fasthttp!")
	}

	fmt.Println("Server is running on :8099")
	if err := fasthttp.ListenAndServe(":8099", requestHandler); err != nil {
		fmt.Printf("Error in ListenAndServe: %s\n", err)
	}
}

输出以下内容,即代表成功:

Server is running on :8099

集成 postgres

go get github.com/lib/pq

测试

package main

import (
	"database/sql"
	"fmt"
	"log"

	_ "github.com/lib/pq" // pq 驱动
)

func main() {
	// PostgreSQL 连接信息
	dsn := "host=localhost port=5432 user=postgres password=123456 dbname=testdb sslmode=disable"

	// 连接数据库
	db, err := sql.Open("postgres", dsn)
	if err != nil {
		log.Fatal("连接数据库失败:", err)
	}
	defer db.Close()

	// 测试连接
	err = db.Ping()
	if err != nil {
		log.Fatal("数据库无法访问:", err)
	}
	fmt.Println("成功连接 PostgreSQL!")

	// 测试查询
	var now string
	err = db.QueryRow("SELECT NOW()").Scan(&now)
	if err != nil {
		log.Fatal("查询失败:", err)
	}
	fmt.Println("数据库当前时间:", now)
}

输出以下内容,即代表成功:

成功连接 PostgreSQL!
数据库当前时间: 2025-10-31T03:08:00.125282Z

集成 viper

go get github.com/spf13/viper

测试:

新建 application.yaml :

server:
  port: 8082

main.go:

package main

import (
	"fmt"
	"log"

	"github.com/fsnotify/fsnotify"
	"github.com/spf13/viper"
)

func main() {
	// 设置配置文件路径
	viper.SetConfigFile("application.yaml")

	// 读取配置文件
	if err := viper.ReadInConfig(); err != nil {
		log.Fatalf("读取配置文件失败: %v", err)
	}

	// 获取配置
	port := viper.GetInt("server.port")
	fmt.Println("Server port:", port)

	// 热加载示例
	viper.WatchConfig()
	viper.OnConfigChange(func(e fsnotify.Event) {
		fmt.Println("配置文件修改:", e.Name)
		newPort := viper.GetInt("server.port")
		fmt.Println("新的 server.port:", newPort)
	})

	// 阻塞等待,可以模拟服务运行
	select {}
}

输出以下内容,即代表成功:

Server port:8082

集成 jwt

go get -u github.com/golang-jwt/jwt/v5

测试:

package main

import (
	"fmt"
	"log"
	"time"

	"github.com/golang-jwt/jwt/v5"
)

// 用于签名的密钥(生产环境不要硬编码)
var jwtKey = []byte("my_secret_key")

func main() {
	// 用户 ID
	userID := 123

	// 生成 token
	tokenString, err := GenerateJWT(userID)
	if err != nil {
		log.Fatal("生成 JWT 失败:", err)
	}
	fmt.Println("生成的 JWT:", tokenString)

	// 验证 token
	claims, err := ValidateJWT(tokenString)
	if err != nil {
		log.Fatal("验证 JWT 失败:", err)
	}
	fmt.Printf("解析后的用户 ID: %v, 过期时间: %v\n", claims.UserID, claims.ExpiresAt.Time)
}

// 自定义 claims
type MyClaims struct {
	UserID int `json:"user_id"`
	jwt.RegisteredClaims
}

// 生成 JWT
func GenerateJWT(userID int) (string, error) {
	claims := MyClaims{
		UserID: userID,
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour)), // 1 小时过期
			IssuedAt:  jwt.NewNumericDate(time.Now()),
			Issuer:    "myapp",
		},
	}

	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	return token.SignedString(jwtKey)
}

// 验证 JWT
func ValidateJWT(tokenString string) (*MyClaims, error) {
	claims := &MyClaims{}

	token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
		return jwtKey, nil
	})
	if err != nil {
		return nil, err
	}

	if !token.Valid {
		return nil, fmt.Errorf("token 无效")
	}

	return claims, nil
}

输出以下内容,即代表成功:

生成的 JWT: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxMjMsImlzcyI6Im15YXBwIiwiZXhwIjoxNzYxODg1MTQ2LCJpYXQiOjE3NjE4ODE1NDZ9.f7gZg6YmuYRXzaOLhJu4Vg8tXYgueHIixeoh10caSWg
解析后的用户 ID: 123, 过期时间: 2025-10-31 12:32:26 +0800 CST

集成 zap

go get -u go.uber.org/zap