308 lines
6.3 KiB
Markdown
308 lines
6.3 KiB
Markdown
# 项目结构
|
||
|
||
```
|
||
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
|
||
```
|
||
|