Go解析yaml和yml文件

本文介绍了YAML,一种用于配置文件的简洁语言,强调数据而非标记。内容包括yaml和yml的区别、示例、语言构成元素以及Go语言中解析yaml的库。通过示例展示了如何使用go-yaml库加载和解析yaml配置文件。
摘要由CSDN通过智能技术生成

Go解析yaml和yml文件


1、yaml概述

yaml一般作为配置文件的语言,类似json、xml等,但和Windows中init配置文件的功能较为相似,但更好理解,我第一次接触是在clash软件中,通过yaml文件导入相关网络数据。

以下来自维基百科的基础介绍:

YAML(/ˈjæməl/,尾音类似camel骆驼)是一个可读性高,用来表达资料序列化的格式。YAML参考了其他多种语言,包括:C语言、Python、Perl,并从XML、电子邮件的数据格式(RFC 2822)中获得灵感。Clark Evans在2001年首次发表了这种语言[1],另外Ingy döt Net与Oren Ben-Kiki也是这语言的共同设计者[2]。目前已经有数种编程语言或脚本语言支持(或者说解析)这种语言。

YAML是"YAML Ain’t a Markup Language"(YAML不是一种标记语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是:“Yet Another Markup Language”(仍是一种标记语言)[3],但为了强调这种语言以数据做为中心,而不是以标记语言为重点,而用反向缩略语重命名。(这让我想起了Linux is not Unix)

2、功能

YAML的语法和其他高级语言类似,并且可以简单表达清单、散列表,标量等资料形态。[4]它使用空白符号缩进和大量依赖外观的特色,特别适合用来表达或编辑数据结构、各种配置文件、倾印调试内容、文件大纲(例如:许多电子邮件标题格式和YAML非常接近)。尽管它比较适合用来表达层次结构式(hierarchical model)的数据结构,不过也有精致的语法可以表示关系性(relational model)的资料。[5]由于YAML使用空白字符和分行来分隔资料,使得它特别适合用grep/Python/Perl/Ruby操作。其让人最容易上手的特色是巧妙避开各种封闭符号,如:引号、各种括号等,这些符号在嵌套结构时会变得复杂而难以辨认。

3、示例

简单的文件:

---
receipt:     Oz-Ware Purchase Invoice
date:        2012-08-06
customer:
    given:   Dorothy
    family:  Gale
   
items:
    - part_no:   A4786
      descrip:   Water Bucket (Filled)
      price:     1.47
      quantity:  4

    - part_no:   E1628
      descrip:   High Heeled "Ruby" Slippers
      size:      8
      price:     133.7
      quantity:  1

bill-to:  &id001
    street: | 
            123 Tornado Alley
            Suite 16
    city:   East Centerville
    state:  KS

ship-to:  *id001   

specialDelivery:  >
    Follow the Yellow Brick
    Road to the Emerald City.
    Pay no attention to the
    man behind the curtain.
...

注意在YAML中,字符串不一定要用双引号标示。另外,在缩进中空白字符的数目并不是非常重要,只要相同层次结构的元素左侧对齐就可以了(不过不能使用TAB字符)。这个文件的顶层由七个键值组成:其中一个键值"items",是两个元素构成的数组(或称清单),这清单中的两个元素同时也是包含了四个键值的散列表。文件中重复的部分用这个方法处理:使用锚点(&)和引用(*)标签将"bill-to"散列表的内容复制到"ship-to"散列表。也可以在文件中加入选择性的空行,以增加可读性。在一个文件中,可同时包含多个文件,并用"—“分隔。选择性的符号”…"可以用来表示文件结尾(在利用流的通信中,这非常有用,可以在不关闭流的情况下,发送结束信号)。

4、语言的构成元素

YAML提供缩进/区块以及内置(inline)两种格式,来表示清单和散列表。以下展示几种YAML的基本原件。

(1)、清单(数组)

习惯上清单比较常用区块格式(block format)表示,也就是用短杠+空白字符作为起始。

 --- # 最喜愛的電影
 - Casablanca
 - North by Northwest
 - Notorious

另外还有一种内置格式(inline format)可以选择──用方括号围住,并用逗号+空白区隔(类似JSON的语法)。

 --- # 購物清單 
 [milk, pumpkin pie, eggs, juice]
(2)、关系数组

键值和资料由冒号及空白字符分开。区块形式(常使用于YAML数据文档中)使用缩进和换行符分隔key: value对。内置形式(常使用于YAML数据流中)在大括号中使用逗号+空白字符分隔key: value对。

 --- # 區塊形式
   name: John Smith
   age: 33
 --- # 內置形式
 {name: John Smith, age: 33}
(3)、区块的字符

再次强调,字符串不需要包在引号之内。

有两种语法可以书写多行文字(multi-line strings),一种为保留换行(使用|字符),另一种为折叠换行(使用>字符)。两种语法在其特殊字符之后都必须接着换行。

(4)、保留换行(Newlines preserved)
data: |                                     # 譯者注:這是一首著名的五行民謠(limerick)
   There once was a man from Darjeeling     # 這裡曾有一個人來自大吉嶺
   Who got on a bus bound for Ealing        # 他搭上一班往伊靈的公車
       It said on the door                  # 門上這麼說的
       "Please don't spit on the floor"     # "請勿在地上吐痰"
   So he carefully spat on the ceiling      # 所以他小心翼翼的吐在天花板上

根据默认,每行开头的缩进(以首行为基准)和行末空白会被去除,而不同的缩进会保留差异。

(5)、折叠换行(Newlines folded)

data: >
   Wrapped text         # 摺疊的文字
   will be folded       # 將會被收
   into a single        # 進單一一個
   paragraph            # 段落
   
   Blank lines denote   # 空白的行代表
   paragraph breaks     # 段落之間的區隔

和保留换行不同的是,只有空白行才视为换行,原本的换行字符会被转换成空白字符,而行首缩进会被去除。

(6)、层次结构化的元素

于清单中使用散列表

- {name: John Smith, age: 33}
- name: Mary Smith
  age: 27

于散列表中使用清单

men: [John Smith, Bill Jones]
women:
  - Mary Smith
  - Susan Williams

5、yml和yaml

文件扩展名对文件内容没有任何影响。您可以将YAML内容保存在具有任何扩展名的文件中:.yml,.yaml或其他任何扩展名。

YAML FAQ建议您优先使用.yaml而不是.yml,但是由于历史原因,许多Windows程序员仍然害怕使用具有三个以上字符的扩展名,因此选择使用.yml。

因此,真正重要的是文件内部的内容,而不是文件扩展名。

6、常见解析库

可以查看Wiki的推荐:https://zh.wikipedia.org/wiki/YAML

7、Go解析库使用示例

如果你是纯yaml的解析可以使用推荐较多的yaml.v2:https://github.com/go-yaml/yaml

如果可能还有json等格式文件的话则可以使用:https://github.com/jinzhu/configor

我们项目上目前是使用的下面这个,这里也以该库做一个简单的示例。

package main

import (
	"fmt"
	"github.com/jinzhu/configor"
)

var Config = struct {
	AppName string `default:"app name"`

	DB struct {
		Name     string
		User     string `default:"root"`
		Password string `required:"true" env:"DBPassword"`
		Port     uint   `default:"3306"`
	}

	Contacts []struct {
		Name  string
		Email string `required:"true"`
	}
}{}

func main() {
	configor.Load(&Config, "config.yaml")
	fmt.Printf("config: %#v\n", Config)
	fmt.Println("config: ", Config)
}

结果:

config: struct { AppName string "default:\"app name\""; DB struct { Name string; User string "default:\"root\""; Password string "required:\"true\" env:\"DBPassword\""; Port uint "default:\"3306\"" }; Contacts []struct { Name string; Email string "required:\"true\"" } }{AppName:"test", DB:struct { Name string; User string "default:\"root\""; Password string "required:\"true\" env:\"DBPassword\""; Port uint "default:\"3306\"" }{Name:"test", User:"test", Password:"test", Port:0x4d2}, Contacts:[]struct { Name string; Email string "required:\"true\"" }{struct { Name string; Email string "required:\"true\"" }{Name:"i test", Email:"test@test.com"}}}
config:  {test {test test test 1234} [{i test test@test.com}]}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

昵称系统有问题

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值