基礎(chǔ)配置篇:我的博客項目配置文件數(shù)據(jù)和配置的讀寫處理

上一節(jié)柳骄,我們已經(jīng)定義和創(chuàng)建了我們需要的目錄团赏,和項目初始化。這一節(jié)我們就可以開始編寫博客配置功能了耐薯。

上面我們提到舔清,我們的配置處理函數(shù)將存放在config目錄中。我們的項目還需要配置文件曲初。配置文件我們就命名為config.json体谒。它是一個json文件,里面將包含了博客網(wǎng)站的基本信息臼婆、數(shù)據(jù)庫配置信息等抒痒。

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數(shù)據(jù)庫的信息评汰。database 為數(shù)據(jù)庫名稱;user 為數(shù)據(jù)庫用戶名痢虹;password 為數(shù)據(jù)庫密碼被去;host 為數(shù)據(jù)庫域名或ip地址;port 為數(shù)據(jù)庫端口奖唯。
  • server 字段包含了博客網(wǎng)站的基本信息惨缆。site_name 為網(wǎng)站名稱,網(wǎng)站頁面會調(diào)用到;env 為博客網(wǎng)站的開發(fā)環(huán)境坯墨,值為development時寂汇,表示開發(fā)中,將會輸出一些開發(fā)信息供參考捣染,值為production表示部署在生產(chǎn)環(huán)境中骄瓣,程序?qū)⒉惠敵鰀ebug信息;port 為博客網(wǎng)站golang運行的端口耍攘,通過這個端口可以訪問到網(wǎng)站頁面榕栏;log_level 表示日志的記錄級別,值為debug的時候蕾各,表示記錄debug級別的信息扒磁。

讀取json文件

上面的配置文件config.json定義好并放到config目錄后,我們還需要編寫代碼式曲,讓golang可以讀取它妨托,才能在項目中調(diào)用配置文件中的信息。這些文件我們都放置在config文件夾中吝羞。

為了方便程序讀取兰伤,我們先給上面兩個字段創(chuàng)建兩個承載這些具體字段的結(jié)構(gòu)體:

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:"-"`
}

它對應(yīng)的是剛才我們定義的json文件中的mysql字段。

結(jié)構(gòu)體的定義是使用關(guān)鍵字 type 和 struct 來聲明一個結(jié)構(gòu)體钧排,以關(guān)鍵字 type 開始医清,之后是新類型的名字,最后是關(guān)鍵字 struct卖氨。

結(jié)構(gòu)體里的字段都有名字,比如上面例子中的 Database 和 User 等等负懦。如果一個字段在代碼中從來不會被用到筒捺,那可以把它命名為 _,即空標識符纸厉。

結(jié)構(gòu)體變量采用大寫可以從外部訪問到系吭,中間的string、int為這個字段的字段類型颗品,``包含的內(nèi)容為結(jié)構(gòu)體字段指定一個標記信息肯尺,上面的標記表示是json字段的對應(yīng)字段名稱。

結(jié)構(gòu)體中的字段可以是任何類型躯枢,甚至是結(jié)構(gòu)體本身则吟,也可以是函數(shù)或者接口〕澹可以聲明結(jié)構(gòu)體類型的一個變量氓仲。

同一個包中,不能出現(xiàn)同名的結(jié)構(gòu)體,不同包不受限制敬扛。

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對應(yīng)的的是json文件的server字段晰洒。

config.go

package config

type configData struct {
    DB     mysqlConfig  `json:"mysql"`
    Server serverConfig `json:"server"`
}

這個表示config.json的整體結(jié)構(gòu)。

用結(jié)構(gòu)體解析json

解析json需要一些函數(shù)來支持啥箭,我們將這些函數(shù)都寫在config.go 里面谍珊。

定義變量

var ExecPath string
var JsonData configData
var ServerConfig serverConfig
var DB *gorm.DB

定義的這四個變量,將是后面我們博客項目中需要使用的變量急侥。

定義執(zhí)行目錄

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
    }
}

上面主要是獲取運行環(huán)境的目錄砌滞,來確定項目目錄,它有2種處理方法缆巧,一種是使用執(zhí)行文件所在的目錄布持,另一種是使用執(zhí)行命令時所在的目錄。

執(zhí)行文件所在目錄的獲取方式是:

root := filepath.Dir(os.Args[0])
ExecPath, _ := filepath.Abs(root)

執(zhí)行命令時所在目錄的獲取方式是:

ExecPath, _ := os.Getwd()

他們的應(yīng)用場景有所不同陕悬,根據(jù)實際選擇使用题暖。
為了開發(fā)中測試方便,本項目暫時使用執(zhí)行時目錄捉超。

讀取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函數(shù)胧卤,我們使用ioutil包來將json文件讀取到字節(jié)變量中。這里增加了判斷拼岳,如果文件不存在枝誊,則返回錯誤。接著將內(nèi)容解析到結(jié)構(gòu)體中惜纸,如果是一個標準的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功能了。

在連接完了之后亭引,我們還需要做一些檢測绎速,比如,是否連接成功痛侍。
連接成功后朝氓,嘗試選擇獲取到連接對象魔市,給連接對象設(shè)置空閑時的最大連接數(shù)、設(shè)置與數(shù)據(jù)庫的最大打開連接數(shù)赵哲,每一個連接的生命周期等信息待德。

在開始的時候執(zhí)行

func init() {
  initPath()
    //讀取json
    initJSON()
    //讀取server
    initServer()
    //初始化數(shù)據(jù)庫
    err := InitDB(&JsonData.DB)
    if err != nil {
        fmt.Println("Failed To Connect Database: ", err.Error())
        os.Exit(-1)
    }
}

golang中的init函數(shù)是golang的一個特殊函數(shù),它優(yōu)先于golang的main函數(shù)執(zhí)行枫夺,實現(xiàn)包級別的一些初始化操作将宪。

所以,我們可以在這里初始化項目的基本信息橡庞,讓后續(xù)程序跑起來的時候可以得到設(shè)置好的配置信息较坛。

完整的config.go

上面分步解釋了配置文件和配置文件的各個函數(shù),這里將它組合起來成一個完整的文件扒最。

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()
    //初始化數(shù)據(jù)庫
    err := InitDB(&JsonData.DB)
    if err != nil {
        fmt.Println("Failed To Connect Database: ", err.Error())
        os.Exit(-1)
    }
}

測試結(jié)果

config寫完了丑勤,我們還需要測試一下。
在根目錄執(zhí)行g(shù)o mod命令來將包下載下來

go mod tidy
go mod vendor

完整的項目示例代碼托管在GitHub上吧趣,需要查看完整的項目代碼可以到github.com/fesiong/goblog 上查看法竞,也可以直接fork一份來在上面做修改。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末强挫,一起剝皮案震驚了整個濱河市岔霸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌俯渤,老刑警劉巖呆细,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異八匠,居然都是意外死亡絮爷,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進店門梨树,熙熙樓的掌柜王于貴愁眉苦臉地迎上來略水,“玉大人,你說我怎么就攤上這事劝萤。” “怎么了慎璧?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵床嫌,是天一觀的道長。 經(jīng)常有香客問我胸私,道長厌处,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任岁疼,我火速辦了婚禮阔涉,結(jié)果婚禮上缆娃,老公的妹妹穿的比我還像新娘。我一直安慰自己瑰排,他們只是感情好贯要,可當我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著椭住,像睡著了一般崇渗。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上京郑,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天宅广,我揣著相機與錄音,去河邊找鬼些举。 笑死跟狱,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的户魏。 我是一名探鬼主播驶臊,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼绪抛!你這毒婦竟也來了资铡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤幢码,失蹤者是張志新(化名)和其女友劉穎笤休,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體症副,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡店雅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了贞铣。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片闹啦。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖辕坝,靈堂內(nèi)的尸體忽然破棺而出窍奋,到底是詐尸還是另有隱情,我是刑警寧澤酱畅,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布琳袄,位于F島的核電站,受9級特大地震影響纺酸,放射性物質(zhì)發(fā)生泄漏窖逗。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一餐蔬、第九天 我趴在偏房一處隱蔽的房頂上張望碎紊。 院中可真熱鬧佑附,春花似錦、人聲如沸仗考。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽痴鳄。三九已至瘟斜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間痪寻,已是汗流浹背螺句。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留橡类,地道東北人蛇尚。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像顾画,于是被迫代替她去往敵國和親取劫。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內(nèi)容