2024-11-16 10:31:47 +08:00
|
|
|
# Book Api Server
|
2024-11-16 11:03:04 +08:00
|
|
|
|
|
|
|
从一个简单的项目开启项目之旅
|
|
|
|
+ 项目介绍: Gin + GORM 开发简单的Book API Server
|
|
|
|
+ 从写脚本开始 与 学会合理使用包来组织你的项目工程
|
|
|
|
+ 使用mvc的模式来 组织你的业务代码
|
|
|
|
+ 完善项目: 项目日志, Api返回与业务异常
|
|
|
|
|
|
|
|
详细说明:
|
|
|
|
|
|
|
|
+ 项目课整体介绍
|
|
|
|
+ 软件开发生命周期流程介绍
|
|
|
|
+ 项目介绍: Gin + GORM 开发简单的API Server
|
|
|
|
+ 如何快速使用Gin开发Api Server
|
|
|
|
+ 如何使用gorm访问数据库
|
|
|
|
+ 如何管理你项目中的配置
|
|
|
|
+ 如何使用MVC模式编写你的业务控制器
|
|
|
|
+ 如何使用zerolog打印程序日志
|
|
|
|
+ 如何为你程序提供统一的Api Response
|
|
|
|
+ 如何自定义业务异常
|
2024-11-16 12:11:19 +08:00
|
|
|
|
|
|
|
|
|
|
|
## 项目准备
|
|
|
|
|
2024-11-16 16:00:55 +08:00
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
## v2 版本
|
|
|
|
|
|
|
|
```go
|
|
|
|
// 初始化数据库, 能过与数据库交互的 连接池对象: db
|
|
|
|
func setupDatabase() *gorm.DB {
|
|
|
|
dsn := "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
|
|
|
|
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
|
|
|
|
if err != nil {
|
|
|
|
panic("failed to connect database")
|
|
|
|
}
|
|
|
|
db.AutoMigrate(&Book{}) // 自动迁移
|
|
|
|
return db.Debug()
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
### 剥离配置
|
|
|
|
|
|
|
|
剥离程序配置,让程序可以通过外部加载配置: config 包: 用来管理程序的配置
|
2024-11-16 17:22:21 +08:00
|
|
|
|
|
|
|
定义了程序配置:
|
|
|
|
```go
|
|
|
|
package config
|
|
|
|
|
|
|
|
// 定义程序配置
|
|
|
|
// dsn := "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
|
|
|
|
// 凡是可以提出出配置的
|
|
|
|
|
|
|
|
// 程序的配置对象
|
|
|
|
type Config struct {
|
|
|
|
App `json:"app"`
|
|
|
|
MySQL `json:"mysql"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// app:
|
|
|
|
//
|
|
|
|
// host: 127.0.0.1
|
|
|
|
// port: 8080
|
|
|
|
type App struct {
|
|
|
|
Host string `json:"host"`
|
|
|
|
Port int `json:"port"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// mysql:
|
|
|
|
//
|
|
|
|
// host: 127.0.0.1
|
|
|
|
// port: 3306
|
|
|
|
// database: test
|
|
|
|
// username: "root"
|
|
|
|
// password: "123456"
|
|
|
|
// debug: true
|
|
|
|
type MySQL struct {
|
|
|
|
Host string `json:"host"`
|
|
|
|
Port int `json:"port"`
|
|
|
|
Database string `json:"database"`
|
|
|
|
Username string `json:"username"`
|
|
|
|
Password string `json:"password"`
|
|
|
|
Debug bool `json:"debug"`
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
### 配置的加载和读取
|
|
|
|
|
|
|
|
```go
|
|
|
|
package config
|
|
|
|
|
|
|
|
import (
|
|
|
|
"os"
|
|
|
|
|
|
|
|
"gopkg.in/yaml.v3"
|
|
|
|
)
|
|
|
|
|
|
|
|
// 程序的配置需要有默认值, 给一个最小的可以运行的配置: 本地开发配置就是默认配置
|
|
|
|
// "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
|
|
|
|
var conf = &Config{
|
|
|
|
App: &App{
|
|
|
|
Host: "127.0.0.1",
|
|
|
|
Port: 8080,
|
|
|
|
},
|
|
|
|
MySQL: &MySQL{
|
|
|
|
Host: "127.0.0.1",
|
|
|
|
Port: 3306,
|
|
|
|
Database: "test",
|
|
|
|
Username: "root",
|
|
|
|
Password: "123456",
|
|
|
|
Debug: true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
func Get() *Config {
|
|
|
|
if conf != nil {
|
|
|
|
panic("配置未初始化")
|
|
|
|
}
|
|
|
|
|
|
|
|
return conf
|
|
|
|
}
|
|
|
|
|
|
|
|
// 配置的加载
|
|
|
|
|
|
|
|
// 程序的其他的部分如何读写程序配置
|
|
|
|
// Yaml File ---> Config
|
|
|
|
func LoadConfigFromYaml(configFilePath string) error {
|
|
|
|
content, err := os.ReadFile(configFilePath)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// 默认值 defaultConfig
|
|
|
|
// 结合配置文件 传达进来的 参数
|
|
|
|
// defualt <-- user defile
|
|
|
|
return yaml.Unmarshal(content, conf)
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
### 编写单元测试,验证模块的正确性
|
2024-11-23 10:04:58 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## 如何组装我们的业务代码
|
|
|
|
|
|
|
|
+ m: model
|
|
|
|
+ v: api
|
2024-11-23 15:17:11 +08:00
|
|
|
+ c: controller
|
|
|
|
|
|
|
|
## 基本的工程化
|
|
|
|
|
|
|
|
+ 日志
|
|
|
|
+ fmt.Println()
|
|
|
|
+ log: 标准库日志
|
|
|
|
+ 第三方的日志库: https://www.mcube.top/docs/framework/config/log/
|
|
|
|
+ https://github.com/rs/zerolog
|
|
|
|
+ 业务异常
|
|
|
|
|
|
|
|
```go
|
|
|
|
log := zerolog.New(os.Stdout)
|
|
|
|
l.log = &log
|
|
|
|
```
|
|
|
|
|
|
|
|
自己封装
|
|
|
|
```go
|
|
|
|
func (l *Log) Logger() *zerolog.Logger {
|
|
|
|
l.lock.Lock()
|
|
|
|
defer l.lock.Unlock()
|
|
|
|
|
|
|
|
if l.log == nil {
|
|
|
|
|
|
|
|
// 文件: os.Stdout --> file
|
|
|
|
log := zerolog.New(os.Stdout)
|
|
|
|
l.log = &log
|
|
|
|
}
|
|
|
|
|
|
|
|
return l.log
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
使用我自己封装好的Zerolog, 支持配置加载
|
|
|
|
|
|
|
|
```go
|
|
|
|
// log.Sub("")
|
|
|
|
// log.L()
|
|
|
|
logger: log.Sub("Book Controller"),
|
|
|
|
```
|