[golang]读取常见配置文件

前言

主要介绍 yaml、toml、json、ini格式文件的配置读取。

除了以下方式,更方便的做法是用viper,不过配置结构可能不会很清晰。

YAML

假设yaml文件内容如下

# 基本键值对
string_key: "这是一个字符串"
integer_key: 42
float_key: 3.14
boolean_key: true
null_key: null

# 列表(数组)
simple_list:
  - item1
  - item2
  - item3

nested_list:
  - 
    - sub_item1
    - sub_item2
  - 
    - sub_item3
    - sub_item4

# 字典(映射)
simple_dict:
  key1: value1
  key2: value2

nested_dict:
  outer_key1:
    inner_key1: inner_value1
    inner_key2: inner_value2
  outer_key2:
    inner_key3: inner_value3

# 引用 & 锚点
defaults: &default_settings
  version: 1.0
  enabled: true

service1:
  <<: *default_settings
  name: "Service One"

service2:
  <<: *default_settings
  name: "Service Two"
  enabled: false  # 覆盖默认值

# 多行字符串
multiline_string: |
  这是一个多行字符串。
  第二行。
  第三行。

folded_string: >
  这是一个折叠字符串,
  换行会被转换为一个空格。

# 混合数据结构
complex_structure:
  - name: "Item1"
    attributes:
      color: "red"
      size: "L"
  - name: "Item2"
    attributes:
      color: "blue"
      size: "M"

# 带注释的值
annotated_key: "值 # 这是注释"

# 日期和时间
date_key: 2024-12-18
datetime_key: 2024-12-18T12:34:56Z

# 特殊类型
binary_data: !!binary |
  VGhpcyBpcyBhIGJpbmFyeSBkYXRhLg==
custom_type: !!map
  key1: value1
  key2: value2

读取的go示例代码

package main

import (
	"fmt"
	"log"
	"os"

	"gopkg.in/yaml.v3"
)

type Config struct {
	StringKey        string                       `yaml:"string_key"`
	IntegerKey       int                          `yaml:"integer_key"`
	FloatKey         float64                      `yaml:"float_key"`
	BooleanKey       bool                         `yaml:"boolean_key"`
	NullKey          interface{}                  `yaml:"null_key"`
	SimpleList       []string                     `yaml:"simple_list"`
	NestedList       [][]string                   `yaml:"nested_list"`
	SimpleDict       map[string]string            `yaml:"simple_dict"`
	NestedDict       map[string]map[string]string `yaml:"nested_dict"`
	Defaults         Defaults                     `yaml:"defaults"`
	Service1         Service                      `yaml:"service1"`
	Service2         Service                      `yaml:"service2"`
	MultilineString  string                       `yaml:"multiline_string"`
	FoldedString     string                       `yaml:"folded_string"`
	ComplexStructure []Item                       `yaml:"complex_structure"`
	AnnotatedKey     string                       `yaml:"annotated_key"`
	DateKey          string                       `yaml:"date_key"`
	DatetimeKey      string                       `yaml:"datetime_key"`
	BinaryData       string                       `yaml:"binary_data"`
	CustomType       map[string]string            `yaml:"custom_type"`
}

type Defaults struct {
	Version string `yaml:"version"`
	Enabled bool   `yaml:"enabled"`
}

type Service struct {
	Defaults
	Name string `yaml:"name"`
}

type Item struct {
	Name       string            `yaml:"name"`
	Attributes map[string]string `yaml:"attributes"`
}

func ReadYaml(filepath string) {
	file, err := os.ReadFile(filepath)
	if err != nil {
		log.Fatalf("Error reading config file, %s\n", err)
	}

	var cfg Config
	err = yaml.Unmarshal(file, &cfg)
	if err != nil {
		log.Fatalf("Error parsing config file, %s\n", err)
	}

	fmt.Printf("%+v\n", cfg)
}

toml

假设toml文件内容如下

# 基本键值对
string_key = "这是一个字符串"
integer_key = 42
float_key = 3.14
boolean_key = true

# TOML 不支持 null,可以用空字符串或省略键值表示 null
null_key = ""

# 列表(数组)
simple_list = ["item1", "item2", "item3"]

nested_list = [
  ["sub_item1", "sub_item2"],
  ["sub_item3", "sub_item4"]
]

# 字典(表)
[simple_dict]
key1 = "value1"
key2 = "value2"

[nested_dict.outer_key1]
inner_key1 = "inner_value1"
inner_key2 = "inner_value2"

[nested_dict.outer_key2]
inner_key3 = "inner_value3"

# 多行字符串
multiline_string = """
这是一个多行字符串。
第二行。
第三行。
"""

folded_string = """这是一个折叠字符串,换行会被转换为一个空格。"""

# 混合数据结构
[[complex_structure]]
name = "Item1"
[complex_structure.attributes]
color = "red"
size = "L"

[[complex_structure]]
name = "Item2"
[complex_structure.attributes]
color = "blue"
size = "M"

示例代码

package main

import (
	"fmt"
	"log"
	"os"

	"github.com/pelletier/go-toml/v2"
)

// 定义与 TOML 结构对应的 Go 数据结构
type TomlConfig struct {
	StringKey        string                       `toml:"string_key"`
	IntegerKey       int                          `toml:"integer_key"`
	FloatKey         float64                      `toml:"float_key"`
	BooleanKey       bool                         `toml:"boolean_key"`
	NullKey          string                       `toml:"null_key"`
	SimpleList       []string                     `toml:"simple_list"`
	NestedList       [][]string                   `toml:"nested_list"`
	SimpleDict       map[string]string            `toml:"simple_dict"`
	NestedDict       map[string]map[string]string `toml:"nested_dict"`
	MultilineString  string                       `toml:"multiline_string"`
	FoldedString     string                       `toml:"folded_string"`
	ComplexStructure []ComplexItem                `toml:"complex_structure"`
}

type ComplexItem struct {
	Name       string            `toml:"name"`
	Attributes map[string]string `toml:"attributes"`
}

func ReadToml(filepath string) {
	file, err := os.ReadFile(filepath)
	if err != nil {
		log.Fatalf("读取文件失败: %v", err)
	}
	// 定义存储解析数据的变量
	var config TomlConfig

	// 解析 TOML 文件
	if err := toml.Unmarshal(file, &config); err != nil {
		log.Fatalf("解析 TOML 文件失败: %v", err)
	}

	// 打印解析结果
	fmt.Printf("读取的配置:\n%+v\n", config)
}

json

json文件内容如下,是从上面toml文件转换而来

{
    "string_key": "这是一个字符串",
    "integer_key": 42,
    "float_key": 3.14,
    "boolean_key": true,
    "null_key": null,
    "simple_list": [
        "item1",
        "item2",
        "item3"
    ],
    "nested_list": [
        [
            "sub_item1",
            "sub_item2"
        ],
        [
            "sub_item3",
            "sub_item4"
        ]
    ],
    "simple_dict": {
        "key1": "value1",
        "key2": "value2"
    },
    "nested_dict": {
        "outer_key1": {
            "inner_key1": "inner_value1",
            "inner_key2": "inner_value2"
        },
        "outer_key2": {
            "inner_key3": "inner_value3"
        }
    },
    "multiline_string": "这是一个多行字符串。\n第二行。\n第三行。\n",
    "folded_string": "这是一个折叠字符串, 换行会被转换为一个空格。\n",
    "complex_structure": [
        {
            "name": "Item1",
            "attributes": {
                "color": "red",
                "size": "L"
            }
        },
        {
            "name": "Item2",
            "attributes": {
                "color": "blue",
                "size": "M"
            }
        }
    ]
}

Go示例代码,结构体定义复用上面toml的

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"os"
)

type TomlConfig struct {
	StringKey        string                       `toml:"string_key" json:"string_key"`
	IntegerKey       int                          `toml:"integer_key" json:"integer_key"`
	FloatKey         float64                      `toml:"float_key" json:"float_key"`
	BooleanKey       bool                         `toml:"boolean_key" json:"boolean_key"`
	NullKey          string                       `toml:"null_key" json:"null_key"`
	SimpleList       []string                     `toml:"simple_list" json:"simple_list"`
	NestedList       [][]string                   `toml:"nested_list" json:"nested_list"`
	SimpleDict       map[string]string            `toml:"simple_dict" json:"simple_dict"`
	NestedDict       map[string]map[string]string `toml:"nested_dict" json:"nested_dict"`
	MultilineString  string                       `toml:"multiline_string" json:"multiline_string"`
	FoldedString     string                       `toml:"folded_string" json:"folded_string"`
	ComplexStructure []ComplexItem                `toml:"complex_structure" json:"complex_structure"`
}

type ComplexItem struct {
	Name       string            `toml:"name" json:"name"`
	Attributes map[string]string `toml:"attributes" json:"attributes"`
}

func ReadJson(filepath string) {
	file, err := os.Open(filepath)
	if err != nil {
		log.Fatalf("Error reading config file, %s\n", err)
	}
	defer file.Close()

	var cfg TomlConfig
	
	decoder := json.NewDecoder(file)
	err = decoder.Decode(&cfg)
	if err != nil {
		log.Fatalf("Error parsing config file, %s\n", err)
	}
	fmt.Printf("%+v\n", cfg)
}

ini

ini文件内容如下

[database]
dbtype: "postgres"
dbname: "test"
dbhost: "localhost"
dbport: "5432"
dbuser: "postgres"
dbpass: "postgres"

[log]
logdir: "/var/log/goapp"
days: 7

go示例代码

package main

import (
	"fmt"
	"log"

	"gopkg.in/ini.v1"
)

type IniConfig struct {
	Database DatabaseConfig `ini:"database"`
	Log      LogConfig      `ini:"log"`
}

type DatabaseConfig struct {
	DBType string `ini:"dbtype"`
	DBName string `ini:"dbname"`
	DBHost string `ini:"dbhost"`
	DBPort string `ini:"dbport"`
	DBUser string `ini:"dbuser"`
	DBPass string `ini:"dbpass"`
}

type LogConfig struct {
	LogDir string `ini:"logdir"`
	Days   int    `ini:"days"`
}

func ReadIni(filepath string) {
	cfg, err := ini.Load(filepath)
	if err != nil {
		log.Fatalf("Error reading config file, %s\n", err)
	}

	var config IniConfig
	err = cfg.MapTo(&config)
	if err != nil {
		log.Fatalf("Error parsing config file, %s\n", err)
	}

	fmt.Printf("%+v\n", config)
}
posted @ 2024-12-18 23:12  花酒锄作田  阅读(11)  评论(0编辑  收藏  举报