实际项目中,要读取一些json等配置文件。今天就来说一说,Golang 是如何读取YAML,JSON,INI等配置文件的。
JSON 应该比较熟悉,它是一种轻量级的数据交换格式。层次结构简洁清晰 ,易于阅读和编写,同时也易于机器解析和生成。
- {
- "enabled": true,
- "path": "/usr/local"
- }
- package main
-
- import (
- "encoding/json"
- "fmt"
- "os"
- )
-
- type configuration struct {
- Enabled bool
- Path string
- }
-
- func main() {
- // 打开文件
- file, _ := os.Open("conf.json")
-
- // 关闭文件
- defer file.Close()
-
- //NewDecoder创建一个从file读取并解码json对象的*Decoder,解码器有自己的缓冲,并可能超前读取部分json数据。
- decoder := json.NewDecoder(file)
-
- conf := configuration{}
- //Decode从输入流读取下一个json编码值并保存在v指向的值里
- err := decoder.Decode(&conf)
- if err != nil {
- fmt.Println("Error:", err)
- }
- fmt.Println("path:" + conf.Path)
- }
启动运行后,输出如下:
- D:\Go_Path\go\src\configmgr>go run config_json.go
- path:/usr/local
假设test.json内容如下,如何解析?
- {
- "pids":{
- "default":{
- "pid":"1844_71935560",
- "desc":"app1"
- },
- "shehui":{
- "pid":"1844_101751664",
- "desc":"app2"
- }
- },
- "top_words":[
- "邓紫棋",
- "沈腾",
- "关晓彤",
- "鹿晗"
- ]
- }
通过json转struct工具转换:
Golang: Convert JSON to Struct
JSON-to-Go: Convert JSON to Go instantly
转化后的struct
- type configuration struct {
- Pids struct {
- Default struct {
- Pid string `json:"pid"`
- Desc string `json:"desc"`
- } `json:"default"`
- Shehui struct {
- Pid string `json:"pid"`
- Desc string `json:"desc"`
- } `json:"shehui"`
- } `json:"pids"`
- TopWords []string `json:"top_words"`
- }
demo实现:
- package main
-
- import (
- "encoding/json"
- "fmt"
- "os"
- )
-
- type configuration struct {
- Pids struct {
- Default struct {
- Pid string `json:"pid"`
- Desc string `json:"desc"`
- } `json:"default"`
- Shehui struct {
- Pid string `json:"pid"`
- Desc string `json:"desc"`
- } `json:"shehui"`
- } `json:"pids"`
- TopWords []string `json:"top_words"`
- }
-
- func parseJsonConfig(filepath string) (conf configuration) {
- // 打开文件
- file, _ := os.Open(filepath)
-
- // 关闭文件
- defer file.Close()
-
- conf = configuration{}
- //NewDecoder创建一个从file读取并解码json对象的*Decoder,解码器有自己的缓冲,并可能超前读取部分json数据。
- //Decode从输入流读取下一个json编码值并保存在v指向的值里
- err := json.NewDecoder(file).Decode(&conf)
- if err != nil {
- fmt.Println("Error:", err)
- }
- return
- }
-
- func main() {
- pdd := parseJsonConfig("D:\\LearnGo\\FirstGo\\10-文件操作\\test3.json")
- fmt.Println(pdd)
- fmt.Println(pdd.Pids.Shehui.Pid)
-
- }
再继续来个案例:
假设json文件内容如下,想读取top_words中name的值,要怎么解析获取?
- {
- "pids":{
- "default":{
- "pid":"1844_71935560",
- "desc":"app1"
- },
- "shehui":{
- "pid":"1844_101751664",
- "desc":"app2"
- }
- },
- "top_words":[
- {
- "name": "cc",
- "age": 18
- },
- {
- "name": "test",
- "age": 20
- }
- ]
- }
demo实现
- package main
-
- import (
- "encoding/json"
- "fmt"
- "os"
- )
-
- type configuration1 struct {
- Pids struct {
- Default struct {
- Desc string `json:"desc"`
- Pid string `json:"pid"`
- } `json:"default"`
- Shehui struct {
- Desc string `json:"desc"`
- Pid string `json:"pid"`
- } `json:"shehui"`
- } `json:"pids"`
- TopWords []struct {
- Age int64 `json:"age"`
- Name string `json:"name"`
- } `json:"top_words"`
- }
-
- func parseJsonConfig1(filepath string) (conf configuration1) {
- // 打开文件
- file, _ := os.Open(filepath)
-
- // 关闭文件
- defer file.Close()
-
- conf = configuration1{}
- //NewDecoder创建一个从file读取并解码json对象的*Decoder,解码器有自己的缓冲,并可能超前读取部分json数据。
- //Decode从输入流读取下一个json编码值并保存在v指向的值里
- err := json.NewDecoder(file).Decode(&conf)
- if err != nil {
- fmt.Println("Error:", err)
- }
- return
- }
-
- func main() {
- pdd := parseJsonConfig1("D:\\LearnGo\\FirstGo\\10-文件操作\\test4.json")
- fmt.Println(pdd)
- //遍历string切片获取name的值
- for _, i := range pdd.TopWords {
- name := i.Name
- fmt.Println(name)
- }
-
- }
运行结果:
- {{{app1 1844_71935560} {app2 1844_101751664}} [{18 cc} {20 test}]}
- cc
- test
最后一个工作用到的案例:读取json文件中的规则,做正则匹配,这里没有进行匹配操作,后续用到加上
- {
- "reverse_shell_rule":[
- {
- "id":"R10000",
- "regex":"socat\\s+TCP4:\\w+\\.\\w+\\.\\w+\\.\\w+:(\\w+)\\s+.*"
- },
- {
- "id":"R10001",
- "regex":"exec\\s+\\d+\\<\\>\/\\w+\/.*"
- }
- ]
- }
- // 读取JSON文件 将内容转为结构对象 然后更改数据
-
- package main
-
- import (
- "encoding/json"
- "fmt"
- "io/ioutil"
- )
-
- type ReverseJson struct {
- ReverseShellRule []struct {
- ID string `json:"id"`
- Regex string `json:"regex"`
- } `json:"reverse_shell_rule"`
- }
-
- func main() {
- var data ReverseJson
-
- // 读取JSON文件内容 返回字节切片
- bytes, _ := ioutil.ReadFile("D:\\LearnGo\\FirstGo\\10-文件操作\\test.json")
-
- // 打印时需要转为字符串
- fmt.Println(string(bytes))
-
- // 将字节切片映射到指定结构上
- json.Unmarshal(bytes, &data)
- //fmt.Println("*** unmarshal result: ***")
-
- // 打印对象结构
- for _, reg := range data.ReverseShellRule {
- rule := reg.Regex
- fmt.Println(rule)
- }
-
- }
INI文件格式是某些平台或软件上的配置文件的非正式标准,由节(section)和键(key)构成,比较常用于微软Windows操作系统中。这种配置文件的文件扩展名为INI。
- [Section]
- enabled = true
- path = /usr/local # another comment
- package main
-
- import (
- "fmt"
- gcfg "gopkg.in/gcfg.v1"
- )
-
- func main() {
- config := struct {
- Section struct {
- Enabled bool
- Path string
- }
- }{}
-
- err := gcfg.ReadFileInto(&config, "conf.ini")
-
- if err != nil {
- fmt.Println("Failed to parse config file: %s", err)
- }
- fmt.Println(config.Section.Enabled)
- fmt.Println(config.Section.Path)
- }
启动运行后,输出如下:
- D:\Go_Path\go\src\configmgr>go run config_ini.go
- true
- /usr/local
yaml 可能比较陌生一点,但是最近却越来越流行,尤其在SpringBoot中的application.yml或者application.yaml中使用非常广泛。也就是一种标记语言。层次结构也特别简洁清晰 ,易于阅读和编写,同时也易于机器解析和生成。
golang的标准库中暂时没有给我们提供操作yaml的标准库,但是github上有很多优秀的第三方库开源给我们使用。
- enabled: true
- path: /usr/local
- package main
-
- import (
- "fmt"
- "io/ioutil"
- "log"
-
- "gopkg.in/yaml.v2"
- )
-
- type conf struct {
- Enabled bool `yaml:"enabled"` //yaml:yaml格式 enabled:属性的为enabled
- Path string `yaml:"path"`
- }
-
- func (c *conf) getConf() *conf {
- yamlFile, err := ioutil.ReadFile("conf.yaml")
- if err != nil {
- log.Printf("yamlFile.Get err #%v ", err)
- }
-
- err = yaml.Unmarshal(yamlFile, c)
- if err != nil {
- log.Fatalf("Unmarshal: %v", err)
- }
- return c
- }
-
- func main() {
- var c conf
- c.getConf()
- fmt.Println("path:" + c.Path)
- }
启动运行后,输出如下:
- D:\Go_Path\go\src\configmgr>go run config_yaml.go
- path:/usr/local
最后 以上,就把golang 读取配置文件的方法,都介绍完了。大家可以拿着代码运行起来看看。
参考资料:
Go 语言解析 JSON 文件 - 知乎 Go 语言解析 JSON 文件(推荐)