• [go]配置文件(CSV与YAML)读写


    CSV文件

    CSV文件(Comma-Separated Values,也称为字符分隔值),是以纯文本形式存储表格数据(数字和文本)的文件;由任意条记录组成:

    • 记录间以换行符分隔;
    • 每条记录由多个字段组成,字段由分隔符(最常见的是逗号制表符)分割;
    • 字段包含特殊字符(逗号,换行符,或双引号),必须以双引号括住;

    通常,所有记录都有完全相同的字段序列。

    go读写

    go中通过包"encoding/csv"可方便读写CSV文件

    通过csv.NewReader可创建Reader,然后从文件中读取:

    • Read:读取一行,返回包含一行内容的切片[]string
    • ReadAll:读取全部内容,返回包含所有行的切片[][]string
    func readCsv(fileName string) {
        csvFile, err := os.Open(fileName)
        if err != nil {
            log.Println("Open CSV fail:", err)
        }
        defer csvFile.Close()
    
        csvReader := csv.NewReader(csvFile)
        for {
            row, err := csvReader.Read()
            if err != nil {
                if err != io.EOF {
                    log.Println("Read CSV fail:", err)
                }
                break
            }
    
            log.Println("ROW: ", row)
        }
    
        //all, err := csvReader.ReadAll()
        //if err != nil {
        //	if err != io.EOF {
        //		log.Println("Read CSV fail:", err)
        //	}
        //}
        //log.Println("ALL:", all)    
    }    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    通过NewWriter写入(内容放在切片中)

    func writeCSV(name string, contents [][]string) error {
        file, err := os.OpenFile(name, os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0666)
        if err != nil {
            log.Printf("Create CSV %v fail: %v", name, err)
            return err
        }
        defer file.Close()
    
        writer := csv.NewWriter(file)
        for _, line := range contents {
            writer.Write(line)
        }
        writer.Flush()
    
        return nil
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    YAML文件

    YAML是一种数据序列化格式,方便人类阅读,且容易和脚本语言交互;格式与规则参见《[Python]读写YAML文件

    go中通过"gopkg.in/yaml.v3"可方便地进行YAML文件的读写。

    读写接口

    读取文件内容后,通过yaml.Unmarshal反序列化即可:

    func readYaml[T any](fileName string) (*T, error) {
        data, err := ioutil.ReadFile(fileName)
        if err != nil {
            log.Printf("Read yaml fail: %v", err)
            return nil, err
        }
    
        conf := new(T)
        err = yaml.Unmarshal(data, conf)
        if err != nil {
            log.Printf("Unmarsh file %v to %T fail: %v", fileName, conf, err)
            return nil, err
        }
        return conf, nil
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    通过yaml.Marshal把结构序列化为YAML格式后,直接写入到文件即可:

    func writeYaml[T any](fileName string, conf *T) error {
        data, err := yaml.Marshal(conf)
        if err != nil {
            log.Printf("Marshal conf %v fail: %v", conf, err)
            return err
        }
    
        err = ioutil.WriteFile(fileName, data, 0666)
        if err != nil {
            log.Printf("Write yaml fail: %v", err)
            return err
        }
    
        return nil
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    映射示例

    以下YAML为例,在go中如何映射?

    students:
      - mike:
          courses:
            - math
            - english
          class: 二年级一班
      - tom:
          courses:
            - math
            - history
          class: 二年级二班
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    students的子节点是学生(数组),而各个学生与其对应信息可用map存储;所以students就是一个map数组:

    type studentData struct {
        Courses []string `yaml:"courses"`
        Class   string   `yaml:"class"`
    }
    
    type studentAll struct {
        Students []map[string]*studentData `yaml:"students"`
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • 相关阅读:
    java毕业设计广告投放mybatis+源码+调试部署+系统+数据库+lw
    Python基础之dict和set的使用
    Leetcode算法入门与数组丨5. 数组二分查找
    后台可视化布局打印设计
    贪心算法-----------------装箱问题
    代码(Python、Java)实现分组求和
    Spring Cloud 之 GateWay简介及简单DEMO的搭建
    野兔在线工具系统V2.7.1中文版更新
    BlockCanary原理解析
    攻防世界web篇-PHP2
  • 原文地址:https://blog.csdn.net/alwaysrun/article/details/128055427