上一节,咱们曾经定义和创立了咱们须要的目录,和我的项目初始化。这一节咱们就能够开始编写博客配置性能了。
下面咱们提到,咱们的配置处理函数将寄存在 config
目录中。咱们的我的项目还须要配置文件。配置文件咱们就命名为config.json
。它是一个 json 文件,外面将蕴含了博客网站的根本信息、数据库配置信息等。
config.json
配置文件
为了不便查看和读取config.json
,咱们将它放在我的项目的 config 目录下。它外面将蕴含的字段信息有:
{
"mysql": {
"database": "irisweb",
"user": "root",
"password": "123456",
"host": "localhost",
"port": 3306
},
"server": {
"site_name": "irisweb 博客",
"env": "development",
"port": 8001,
"log_level": "debug"
}
}
字段阐明:
mysql
字段蕴含了连贯 mysql 数据库的信息。database
为数据库名称;user
为数据库用户名;password
为数据库明码;host
为数据库域名或 ip 地址;port
为数据库端口。server
字段蕴含了博客网站的根本信息。site_name
为网站名称,网站页面会调用到;env
为博客网站的开发环境,值为 development 时,示意开发中,将会输入一些开发信息供参考,值为 production 示意部署在生产环境中,程序将不输入 debug 信息;port
为博客网站 golang 运行的端口,通过这个端口能够拜访到网站页面;log_level
示意日志的记录级别,值为 debug 的时候,示意记录 debug 级别的信息。
读取 json 文件
下面的配置文件 config.json
定义好并放到 config 目录后,咱们还须要编写代码,让 golang 能够读取它,能力在我的项目中调用配置文件中的信息。这些文件咱们都搁置在 config
文件夹中。
为了不便程序读取,咱们先给下面两个字段创立两个承载这些具体字段的构造体:
mysql.go
package config
type mysqlConfig struct {
Database string `json:"database"`
User string `json:"user"`
Password string `json:"password"`
Host string `json:"host"`
Port int `json:"port"`
Url string `json:"-"`
}
它对应的是方才咱们定义的 json 文件中的 mysql 字段。
构造体的定义是应用关键字 type 和 struct 来申明一个构造体,以关键字 type 开始,之后是新类型的名字,最初是关键字 struct。
构造体里的字段都有名字,比方下面例子中的 Database 和 User 等等。如果一个字段在代码中从来不会被用到,那能够把它命名为 _,即空标识符。
构造体变量采纳大写能够从内部拜访到,两头的 string、int 为这个字段的字段类型,“ 蕴含的内容为构造体字段指定一个标记信息,下面的标记示意是 json 字段的对应字段名称。
构造体中的字段能够是任何类型,甚至是构造体自身,也能够是函数或者接口。能够申明构造体类型的一个变量。
同一个包中,不能呈现同名的构造体,不同包不受限制。
server.go
package config
type serverConfig struct {
SiteName string `json:"site_name"`
Env string `json:"env"`
Port int `json:"port"`
LogLevel string `json:"log_level"`
}
server.go 对应的的是 json 文件的 server 字段。
config.go
package config
type configData struct {
DB mysqlConfig `json:"mysql"`
Server serverConfig `json:"server"`
}
这个示意 config.json 的整体构造。
用构造体解析 json
解析 json 须要一些函数来反对,咱们将这些函数都写在 config.go 外面。
定义变量
var ExecPath string
var JsonData configData
var ServerConfig serverConfig
var DB *gorm.DB
定义的这四个变量,将是前面咱们博客我的项目中须要应用的变量。
定义执行目录
func initPath() {sep := string(os.PathSeparator)
//root := filepath.Dir(os.Args[0])
//ExecPath, _ = filepath.Abs(root
ExecPath, _ = os.Getwd()
length := utf8.RuneCountInString(ExecPath)
lastChar := ExecPath[length-1:]
if lastChar != sep {ExecPath = ExecPath + sep}
}
下面次要是获取运行环境的目录,来确定我的项目目录,它有 2 种解决办法,一种是应用执行文件所在的目录,另一种是应用执行命令时所在的目录。
执行文件所在目录的获取形式是:
root := filepath.Dir(os.Args[0])
ExecPath, _ := filepath.Abs(root)
执行命令时所在目录的获取形式是:
ExecPath, _ := os.Getwd()
他们的利用场景有所不同,依据理论抉择应用。
为了开发中测试不便,本我的项目临时应用执行时目录。
读取 json 文件
func InitJSON() {rawConfig, err := ioutil.ReadFile("./config.json")
if err != nil {
// 未初始化
fmt.Println("Invalid Config:", err.Error())
os.Exit(-1)
}
if err := json.Unmarshal(rawConfig, &JsonData); err != nil {fmt.Println("Invalid Config:", err.Error())
os.Exit(-1)
}
}
读取 json 函数,咱们应用 ioutil 包来将 json 文件读取到字节变量中。这里减少了判断,如果文件不存在,则返回谬误。接着将内容解析到构造体中,如果是一个规范的 json 字符串,则这里能够解析胜利,如果不胜利,则要查看 config.json 是否配置正确了。
解析 server
func initServer() {ServerConfig = JsonData.Server}
将 server 的字段赋值给 ServerConfig 变量
解析 mysql
func InitDB(setting *mysqlConfig) error {
var db *gorm.DB
var err error
url := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
setting.User, setting.Password, setting.Host, setting.Port, setting.Database)
setting.Url = url
db, err = gorm.Open(mysql.Open(url), &gorm.Config{})
if err != nil {return err}
sqlDB, err := db.DB()
if err != nil {return err}
sqlDB.SetMaxIdleConns(1000)
sqlDB.SetMaxOpenConns(100000)
sqlDB.SetConnMaxLifetime(-1)
DB = db
return nil
}
咱们在解析 mysql 的时候,先组装好 mysql 包连贯所用的连贯字符串,而后通过连贯字符串,应用 mysql 包来关上链接,再将 mysql 连贯交给 gorm 来治理,这样子,最终咱们就能够应用 gorm 的 orm 性能了。
在连贯完了之后,咱们还须要做一些检测,比方,是否连贯胜利。
连贯胜利后,尝试抉择获取到连贯对象,给连贯对象设置闲暇时的最大连接数、设置与数据库的最大关上连接数,每一个连贯的生命周期等信息。
在开始的时候执行
func init() {initPath()
// 读取 json
initJSON()
// 读取 server
initServer()
// 初始化数据库
err := InitDB(&JsonData.DB)
if err != nil {fmt.Println("Failed To Connect Database:", err.Error())
os.Exit(-1)
}
}
golang 中的 init 函数是 golang 的一个非凡函数,它优先于 golang 的 main 函数执行,实现包级别的一些初始化操作。
所以,咱们能够在这里初始化我的项目的根本信息,让后续程序跑起来的时候能够失去设置好的配置信息。
残缺的config.go
下面分步解释了配置文件和配置文件的各个函数,这里将它组合起来成一个残缺的文件。
package config
import (
"encoding/json"
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"io/ioutil"
"os"
"unicode/utf8"
)
type configData struct {
DB mysqlConfig `json:"mysql"`
Server serverConfig `json:"server"`
}
func initPath() {sep := string(os.PathSeparator)
//root := filepath.Dir(os.Args[0])
//ExecPath, _ = filepath.Abs(root
ExecPath, _ = os.Getwd()
length := utf8.RuneCountInString(ExecPath)
lastChar := ExecPath[length-1:]
if lastChar != sep {ExecPath = ExecPath + sep}
}
func initJSON() {rawConfig, err := ioutil.ReadFile(fmt.Sprintf("%sconfig.json", ExecPath))
if err != nil {
// 未初始化
fmt.Println("Invalid Config:", err.Error())
os.Exit(-1)
}
if err := json.Unmarshal(rawConfig, &JsonData); err != nil {fmt.Println("Invalid Config:", err.Error())
os.Exit(-1)
}
}
func InitDB(setting *mysqlConfig) error {
var db *gorm.DB
var err error
url := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
setting.User, setting.Password, setting.Host, setting.Port, setting.Database)
setting.Url = url
db, err = gorm.Open(mysql.Open(url), &gorm.Config{})
if err != nil {return err}
sqlDB, err := db.DB()
if err != nil {return err}
sqlDB.SetMaxIdleConns(1000)
sqlDB.SetMaxOpenConns(100000)
sqlDB.SetConnMaxLifetime(-1)
DB = db
return nil
}
func initServer() {ServerConfig = JsonData.Server}
var ExecPath string
var JsonData configData
var ServerConfig serverConfig
var DB *gorm.DB
func init() {initPath()
// 读取 json
initJSON()
// 读取 server
initServer()
// 初始化数据库
err := InitDB(&JsonData.DB)
if err != nil {fmt.Println("Failed To Connect Database:", err.Error())
os.Exit(-1)
}
}
测试后果
config 写完了,咱们还须要测试一下。
在根目录执行 go mod 命令来将包下载下来
go mod tidy
go mod vendor
残缺的我的项目示例代码托管在 GitHub 上,须要查看残缺的我的项目代码能够到 github.com/fesiong/goblog 上查看,也能够间接 fork 一份来在下面做批改。