0
点赞
收藏
分享

微信扫一扫

Go解析yaml和yml文件


Go解析yaml和yml文件

文章目录

  • ​​Go解析yaml和yml文件​​
  • ​​1、yaml概述​​
  • ​​2、功能​​
  • ​​3、示例​​
  • ​​4、语言的构成元素​​
  • ​​(1)、清单(数组)​​
  • ​​(2)、关系数组​​
  • ​​(3)、区块的字符​​
  • ​​(4)、保留换行(Newlines preserved)​​
  • ​​(5)、折叠换行(Newlines folded)​​
  • ​​(6)、层次结构化的元素​​
  • ​​5、yml和yaml​​
  • ​​6、常见解析库​​
  • ​​7、Go解析库使用示例​​

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
-

另外还有一种内置格式(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
-

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 条评论