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

308 lines
6.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 项目结构
```
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](https://github.com/valyala/fasthttp)
```bash
go get -u github.com/valyala/fasthttp
```
测试
```go
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](https://github.com/lib/pq)
```bash
go get github.com/lib/pq
```
测试
```go
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](https://github.com/spf13/viper)
```bash
go get github.com/spf13/viper
```
测试:
新建 `application.yaml` :
```yaml
server:
port: 8082
```
`main.go`:
```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](https://github.com/golang-jwt/jwt)
```bash
go get -u github.com/golang-jwt/jwt/v5
```
测试:
```go
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](https://pkg.go.dev/go.uber.org/zap)
```bash
go get -u go.uber.org/zap
```