# Book Api Server 从一个简单的项目开启项目之旅 + 项目介绍: Gin + GORM 开发简单的Book API Server + 从写脚本开始 与 学会合理使用包来组织你的项目工程 + 使用mvc的模式来 组织你的业务代码 + 完善项目: 项目日志, Api返回与业务异常 详细说明: + 项目课整体介绍 + 软件开发生命周期流程介绍 + 项目介绍: Gin + GORM 开发简单的API Server + 如何快速使用Gin开发Api Server + 如何使用gorm访问数据库 + 如何管理你项目中的配置 + 如何使用MVC模式编写你的业务控制器 + 如何使用zerolog打印程序日志 + 如何为你程序提供统一的Api Response + 如何自定义业务异常 ## 项目准备 ![alt text](image.png) ## 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 包: 用来管理程序的配置 定义了程序配置: ```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) } ``` ### 编写单元测试,验证模块的正确性 ## 如何组装我们的业务代码 + m: model + v: api + 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"), ```