diff --git a/book/README.md b/book/README.md index 8816ed2..3178fcb 100644 --- a/book/README.md +++ b/book/README.md @@ -43,3 +43,99 @@ func setupDatabase() *gorm.DB { ### 剥离配置 剥离程序配置,让程序可以通过外部加载配置: 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) +} +``` + +### 编写单元测试,验证模块的正确性 diff --git a/book/config/README.md b/book/config/README.md new file mode 100644 index 0000000..d69a802 --- /dev/null +++ b/book/config/README.md @@ -0,0 +1,79 @@ +# 程序配置管理 + + + + +## 测试验证包 + +要考虑测序的是否如预期运行 + +## 如果定义单元测试 + +1. 包的命名规范: pkg_test +我想测试 LoadConfigFromYaml 这个函数能不能正常运行, Go里的每一个Package 都允许有2个包: ++ pkg: 目标包 ++ pkg_test: 正对目标包的测试包 + +2. 定义测试函数: TestLoadConfigFromYaml(t *testing.T) ++ TestXXXX ++ (t *testing.T) + +那么你的单元测试定义成功: +![alt text](image.png) + +## 如何查看单测单元的信息 + +在单元测试里: 是不是被显示 +```go +t.Log(config.Get()) +``` + +我Run时, vscode生成的 go test命令 +```sh +Running tool: /usr/local/go/bin/go test -timeout 300s -run ^TestLoadConfigFromYaml$ gitlab.com/go-course-project/go17/book/config -v -count=1 +``` + +怎么才能配置vscode 添加go test的 参数, 你需要对的vscode做配置 +![alt text](image-1.png) + +修改 TestFlag +```json + "go.testFlags": [ + "-v", + "-count=1" + ], +``` ++ -v 就是打印 debug信息, t.Log的信息 ++ -count=1: 必须执行一次 + +## 为你的对象实现Stringger 接口 + +```go +// &{0x102317ec0 0x10231c8a0} +// +// String() string, fmt.Strigger接口 +// +// fmt. +func (c *Config) String() string { + v, _ := json.Marshal(c) + return string(v) +} +``` + +```sh +/Users/yumaojun/Projects/go-course/go17/book/config/load_test.go:17: {"app":{"host":"localhost","port":8090},"mysql":{"host":"127.0.0.1","port":3306,"database":"test","username":"root","password":"888888","debug":false}} +``` + +```go +// Stringer is implemented by any value that has a String method, +// which defines the “native” format for that value. +// The String method is used to print values passed as an operand +// to any format that accepts a string or to an unformatted printer +// such as Print. +type Stringer interface { + String() string +} +``` + +## debug 测试 + diff --git a/book/config/application.yaml b/book/config/application.yaml new file mode 100644 index 0000000..de6ecff --- /dev/null +++ b/book/config/application.yaml @@ -0,0 +1,10 @@ +app: + host: localhost + port: 8090 +mysql: + host: 127.0.0.1 + port: 3306 + database: test + username: "root" + password: "888888" + debug: false diff --git a/book/config/config.go b/book/config/config.go index 0342c6f..047f859 100644 --- a/book/config/config.go +++ b/book/config/config.go @@ -1,13 +1,25 @@ package config +import "encoding/json" + // 定义程序配置 // 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 *App `json:"app"` + MySQL *MySQL `json:"mysql"` +} + +// &{0x102317ec0 0x10231c8a0} +// +// String() string, fmt.Strigger接口 +// +// fmt. +func (c *Config) String() string { + v, _ := json.Marshal(c) + return string(v) } // app: diff --git a/book/config/image-1.png b/book/config/image-1.png new file mode 100644 index 0000000..c03f833 Binary files /dev/null and b/book/config/image-1.png differ diff --git a/book/config/image.png b/book/config/image.png new file mode 100644 index 0000000..0b96506 Binary files /dev/null and b/book/config/image.png differ diff --git a/book/config/load.go b/book/config/load.go index 2c022e3..15391b4 100644 --- a/book/config/load.go +++ b/book/config/load.go @@ -1,5 +1,48 @@ 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) +} diff --git a/book/config/load_test.go b/book/config/load_test.go new file mode 100644 index 0000000..0cf70bf --- /dev/null +++ b/book/config/load_test.go @@ -0,0 +1,18 @@ +package config_test + +import ( + "testing" + + "gitlab.com/go-course-project/go17/book/config" +) + +// LoadConfigFromYaml +func TestLoadConfigFromYaml(t *testing.T) { + if err := config.LoadConfigFromYaml("application.yaml"); err != nil { + // 报错测试失败,并且结束 + t.Fatal(err) + } + + // 加载成功 + t.Log(config.Get()) +} diff --git a/book/main.go b/book/main.go new file mode 100644 index 0000000..2378180 --- /dev/null +++ b/book/main.go @@ -0,0 +1,22 @@ +package main + +import ( + "fmt" + "os" + + "gitlab.com/go-course-project/go17/book/config" +) + +func main() { + // 从配置文件中加载配置 + // 加载配置 + path := os.Getenv("CONFIG_PATH") + if path == "" { + path = "application.yaml" + } + config.LoadConfigFromYaml(path) + + // 访问加载后的配置 + conf := config.Get() + fmt.Println(conf) +} diff --git a/go.mod b/go.mod index ed3e04d..8cf8cdb 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.22.0 require ( github.com/gin-gonic/gin v1.10.0 + gopkg.in/yaml.v3 v3.0.1 gorm.io/driver/mysql v1.5.7 gorm.io/gorm v1.25.12 ) @@ -37,5 +38,4 @@ require ( golang.org/x/sys v0.20.0 // indirect golang.org/x/text v0.15.0 // indirect google.golang.org/protobuf v1.34.1 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect )