最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

go解析YAML文件(多文檔解析)

 更新時間:2024年10月21日 11:47:07   作者:SRExianxian  
本文介紹了如何使用GO語言和client-go庫處理YAML文件,特別是在Kubernetes環(huán)境下,分析了YAML的特點,如簡潔性、易讀性、可嵌套性等,并展示了相關代碼實現(xiàn),包括單文檔和多文檔的處理方法,感興趣的可以了解一下

概述

摘要: 在kubernetes二次開發(fā)中,常用yaml文件來創(chuàng)建資源,比如Pod,deployment。在使用client-go創(chuàng)建資源之前,需要將yaml文件轉換為資源對象obj。本文介紹yaml文件的編碼和解碼的使用。

正文

yaml文檔介紹

YAML 是一種輕量級的數(shù)據(jù)序列化格式,用于在不同平臺間傳輸數(shù)據(jù),也用于配置文件等場景。在 YAML 中,整個數(shù)據(jù)文件稱為“文檔”,而一般情況下,每個 YAML 文件只包含一個文檔。而在kubernetes使用中,kubectl為了創(chuàng)建資源方便性,常用的YAML文件確包括多個文檔。
文檔可以包含一個或多個“節(jié)點”,每個節(jié)點包含一個或多個鍵值對。鍵值對之間的關系使用冒號(:)表示,鍵值對的鍵和值之間使用空格隔開,同時整個鍵、值對的行末不能有多余的空格。一個節(jié)點可以用減號(-)開頭表示它是一個序列,即列表。

# 這是一個 YAML 文檔
name:  Tom
age: 30
hobbies: 
  - reading
  - running
  - swimming

在這個文檔中,使用“#”符號表示注釋,每個節(jié)點的鍵和值之間用冒號分隔,節(jié)點之間使用換行符分隔。在“hobbies”節(jié)點中,使用“-”符號表示這是一個序列(即一個列表),列表中的項目用“-”符號開始表示

YAML 文檔特點包括

  • 易讀性:YAML 使用縮進和結構化的格式,使得它非常易讀。它使用空格而不是特殊符號來表示層級關系,使得文檔具有良好的可讀性。

  • 簡潔性:YAML 使用簡潔的語法來表示數(shù)據(jù)結構,避免了冗余和重復。它支持使用引用和折疊塊等特性來簡化文檔的編寫。

  • 可嵌套性:YAML 支持嵌套結構,可以在一個節(jié)點中包含其他節(jié)點,從而表示更復雜的數(shù)據(jù)結構。這種嵌套結構使得數(shù)據(jù)的組織更加靈活和清晰。

  • 跨平臺:YAML 是一種與編程語言無關的數(shù)據(jù)格式,可以輕松地在不同的編程語言和平臺之間進行交換和共享。

  • 強大的數(shù)據(jù)表達能力:YAML 支持表示各種數(shù)據(jù)類型,包括字符串、整數(shù)、浮點數(shù)、布爾值、日期、時間、正則表達式等。它還支持列表、哈希表等數(shù)據(jù)結構。

  • 注釋:YAML 允許在文檔中包含注釋,注釋以“#”符號開頭,可以用于提供有關數(shù)據(jù)的額外說明或注解。

  • 可擴展性:YAML 允許用戶通過自定義標簽和類型的方式擴展其功能,使其適應更多的應用場景和需求。

  • 與配置文件的兼容性:由于其易讀性和簡潔性,YAML 在配置文件方面非常流行。它被廣泛用于各種軟件和框架的配置文件中,如 Kubernetes、Docker ComposeAnsible 等。

    總的來說,YAML 是一種簡單、可讀性強且功能豐富的數(shù)據(jù)序列化格式,非常適合在配置文件和數(shù)據(jù)交換方面使用

對YAML文檔的處理常用三方庫 "gopkg.in/yaml.v2"

常用方法包括

  • Yaml.Marshal() 將結構體對象 轉換為YAML字符串

  • yaml.Unmarshal() 將YAML字符串轉換為結構體對象

代碼示例

yaml文件與結構體之間的轉換

創(chuàng)建一個用于測試YAML文件fakePersonStruct.yaml

---
name: xianwei
age: 18
city: shenzhen

編寫測試代碼

// go test -run="^TestPersonStruct$"  -v
func TestPersonStruct(t *testing.T) {
  // 定義一個結構體
	type Person struct {
		Name string `yaml:"name"`
		Age  int    `yaml:"int"`
		City string `yaml:"city"`
	}
	byteStream, err := ioutil.ReadFile("yamldir/fakePersonStruct.yaml")
	if err != nil {
		t.Errorf("cann not open file.err=%v\n", err)
		return
	}

	// yaml字符串轉換為person對象
	p := new(Person)
	if err := yaml.Unmarshal(byteStream, p); err != nil {
		t.Errorf("yaml.Unmarshal.err=%v\n", err)
		return
	}
	fmt.Printf("person= %+v\n", p)

	// Person對象轉換為yaml字符串
	yamlstr, err := yaml.Marshal(p)
	if err != nil {
		t.Errorf("yaml.Marshal.err=%v\n", err)
		return
	}
	fmt.Printf("yamlstr= %+v\n", string(yamlstr))
}

上面代碼實現(xiàn)了:

  • yaml字符串轉換為person對象
  • Person對象轉換為yaml字符串

代碼輸出

=== RUN   TestPersonStruct
person= &{Name:xianwei Age:0 City:shenzhen}
yamlstr= name: xianwei
int: 0
city: shenzhen

--- PASS: TestPersonStruct (0.00s)
PASS

解析yaml文件并創(chuàng)建pod

使用yaml創(chuàng)建pod時,需要注意的是,需要先將yaml串轉換為json串,再由json串Unmarshal成一個pod對象。原因是v1.pod類型定義中(源碼如下所示),只指定定義字符串的轉換。

type Pod struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
	Spec PodSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
	Status PodStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}

創(chuàng)建一個用于測試YAML文件pod-nginx.yaml

---
apiVersion: v1
kind: Pod
metadata:
  name: mynginx
spec:
  containers:
    - name: nginx
      image: nginx:1.14.2

編寫測試代碼

// go test -run="^TestYamlfilePod$"  -v
func TestYamlfilePod(t *testing.T) {
	// 將yaml文件轉換為pod對象
	byteStream, err := ioutil.ReadFile("yamldir/pod-nginx.yaml")
	if err != nil {
		t.Errorf("cann not open file.err=%v\n", err)
		return
	}

	// yaml串轉換為json串
	pod := new(v1.Pod)
	// yaml2 表示 三方庫"k8s.io/apimachinery/pkg/util/yaml"
	jsonstr, err := yaml2.ToJSON(byteStream)
	if err != nil {
		t.Errorf("yaml2.ToJSON.err=%v\n", err)
		return
	}
	fmt.Printf("jsonstr= %v\n", string(jsonstr))

	// json串轉換為pod結構體
	err = json.Unmarshal(jsonstr, &pod)
	if err != nil {
		t.Errorf("json.Unmarshal.err=%v\n", err)
		return
	}
	fmt.Printf("pod= %v\n", pod)

	// clientset獲取
	restConfig, err := clientcmd.BuildConfigFromFlags("", "/Users/80280051/.kube/dg11test/config")
	if err != nil {
		panic(err)
	}
	K8sClientSet, err := kubernetes.NewForConfig(restConfig)
	if err != nil {
		panic(err)
	}

	// 創(chuàng)建pod
	_, err = K8sClientSet.CoreV1().Pods("default").Create(pod)
	if err != nil {
		t.Errorf("cann not create pod.err=%v\n", err)
		return
	}
	
}

上面代碼實現(xiàn)了:

  • yaml字符串轉換為json字符串
  • 再由json字符串轉換pod對象
  • 最后使用clientset創(chuàng)建pod

代碼輸出

=== RUN   TestYamlfilePod
jsonstr= {"apiVersion":"v1","kind":"Pod","metadata":{"name":"mynginx"},"spec":{"containers":[{"image":"nginx:1.14.2","name":"nginx"}]}}
pod= &Pod{ObjectMeta:{mynginx      0 0001-01-01 00:00:00 +0000 UTC <nil> <nil> map[] map[] [] []  []},Spec:PodSpec{Volumes:[]Volume{},Containers:[]Container{Container{Name:nginx,Image:nginx:1.14.2,Command:[],Args:[],WorkingDir:,Ports:[]ContainerPort{},Env:[]EnvVar{},Resources:ResourceRequirements{Limits:ResourceList{},Requests:ResourceList{},},VolumeMounts:[]VolumeMount{},LivenessProbe:nil,ReadinessProbe:nil,Lifecycle:nil,TerminationMessagePath:,ImagePullPolicy:,SecurityContext:nil,Stdin:false,StdinOnce:false,TTY:false,EnvFrom:[]EnvFromSource{},TerminationMessagePolicy:,VolumeDevices:[]VolumeDevice{},StartupProbe:nil,},},RestartPolicy:,TerminationGracePeriodSeconds:nil,ActiveDeadlineSeconds:nil,DNSPolicy:,NodeSelector:map[string]string{},ServiceAccountName:,DeprecatedServiceAccount:,NodeName:,HostNetwork:false,HostPID:false,HostIPC:false,SecurityContext:nil,ImagePullSecrets:[]LocalObjectReference{},Hostname:,Subdomain:,Affinity:nil,SchedulerName:,InitContainers:[]Container{},AutomountServiceAccountToken:nil,Tolerations:[]Toleration{},HostAliases:[]HostAlias{},PriorityClassName:,Priority:nil,DNSConfig:nil,ShareProcessNamespace:nil,ReadinessGates:[]PodReadinessGate{},RuntimeClassName:nil,EnableServiceLinks:nil,PreemptionPolicy:nil,Overhead:ResourceList{},TopologySpreadConstraints:[]TopologySpreadConstraint{},EphemeralContainers:[]EphemeralContainer{},},Status:PodStatus{Phase:,Conditions:[]PodCondition{},Message:,Reason:,HostIP:,PodIP:,StartTime:<nil>,ContainerStatuses:[]ContainerStatus{},QOSClass:,InitContainerStatuses:[]ContainerStatus{},NominatedNodeName:,PodIPs:[]PodIP{},EphemeralContainerStatuses:[]ContainerStatus{},},}
--- PASS: TestYamlfilePod (0.05s)
PASS

yaml文件中多文檔的處理

在使用kubectl或client-go創(chuàng)建Pod時,經(jīng)常會將多個YAML文檔寫到一個YAML文件。此種情況下,可以通過按字符串"\n—"進行分割,分別處理。

創(chuàng)建一個用于測試YAML文件pod-nginx-secret.yaml

---
apiVersion: v1
kind: Pod
metadata:
  name: mynginx
spec:
  containers:
    - name: nginx
      image: nginx:1.14.2
---
apiVersion: v1
type: Opaque
stringData:
  userdata: "eGlhbndlaTExMQo="
kind: Secret
metadata:
  name: mySecret

編寫測試代碼

// go test -run="^TestYamlfileMultiDocument" -mod=vendor -v
func TestYamlfileMultiDocument(t *testing.T) {
	// 將yaml文件轉換為yaml串
	fp, err := ioutil.ReadFile("yamldir/pod-nginx-secret.yaml")
	if err != nil {
		t.Errorf("cann not open file.err=%v\n", err)
		return
	}
	// 定義分隔符
	const yamlSeparator = "\n---"

	pod := new(v1.Pod)
	secret := new(v1.Secret)
	yamlsplit := strings.Split(string(fp), yamlSeparator)
	fmt.Println("len of yamlsplit = ", len(yamlsplit))
	for index, yamlObj := range yamlsplit {
		// 處理第一個yaml文檔,轉換為 pod 對象
		if index == 0 {
			// 轉換為對象
			fmt.Println("obj=", yamlObj)
			if err = yaml.Unmarshal([]byte(yamlObj), pod); err != nil {
				t.Errorf("yaml unmarshal error of pod.err = %v\n", err)
				return
			}
			fmt.Printf("pod obj =%+v\n", pod)
		}
		// 處理第二個yaml文檔,轉換為secret對象
		if index == 1 {
			fmt.Println("obj=", yamlObj)
			// 轉換為對象
			if err = yaml.Unmarshal([]byte(yamlObj), secret); err != nil {
				t.Errorf("yaml unmarshal error of secret.err = %v\n", err)
				return
			}
			fmt.Printf("secret obj =%+v\n", secret)
		}

	}

}

上面代碼實現(xiàn)了:

  • 對yaml字符串按"\n—"進行分割
  • 對分割后的第一個yaml文檔,轉換為 pod 對象
  • 對分割后的第二個yaml文檔,轉換為secret對象

代碼輸出

=== RUN   TestYamlfileMultiDocument
len of yamlsplit =  2
obj= ---
apiVersion: v1
kind: Pod
metadata:
  name: mynginx
spec:
  containers:
    - name: nginx
      image: nginx:1.14.2
pod obj =&Pod{ObjectMeta:{      0 0001-01-01 00:00:00 +0000 UTC <nil> <nil> map[] map[] [] []  []},Spec:PodSpec{Volumes:[]Volume{},Containers:[]Container{Container{Name:nginx,Image:nginx:1.14.2,Command:[],Args:[],WorkingDir:,Ports:[]ContainerPort{},Env:[]EnvVar{},Resources:ResourceRequirements{Limits:ResourceList{},Requests:ResourceList{},},VolumeMounts:[]VolumeMount{},LivenessProbe:nil,ReadinessProbe:nil,Lifecycle:nil,TerminationMessagePath:,ImagePullPolicy:,SecurityContext:nil,Stdin:false,StdinOnce:false,TTY:false,EnvFrom:[]EnvFromSource{},TerminationMessagePolicy:,VolumeDevices:[]VolumeDevice{},StartupProbe:nil,},},RestartPolicy:,TerminationGracePeriodSeconds:nil,ActiveDeadlineSeconds:nil,DNSPolicy:,NodeSelector:map[string]string{},ServiceAccountName:,DeprecatedServiceAccount:,NodeName:,HostNetwork:false,HostPID:false,HostIPC:false,SecurityContext:nil,ImagePullSecrets:[]LocalObjectReference{},Hostname:,Subdomain:,Affinity:nil,SchedulerName:,InitContainers:[]Container{},AutomountServiceAccountToken:nil,Tolerations:[]Toleration{},HostAliases:[]HostAlias{},PriorityClassName:,Priority:nil,DNSConfig:nil,ShareProcessNamespace:nil,ReadinessGates:[]PodReadinessGate{},RuntimeClassName:nil,EnableServiceLinks:nil,PreemptionPolicy:nil,Overhead:ResourceList{},TopologySpreadConstraints:[]TopologySpreadConstraint{},EphemeralContainers:[]EphemeralContainer{},},Status:PodStatus{Phase:,Conditions:[]PodCondition{},Message:,Reason:,HostIP:,PodIP:,StartTime:<nil>,ContainerStatuses:[]ContainerStatus{},QOSClass:,InitContainerStatuses:[]ContainerStatus{},NominatedNodeName:,PodIPs:[]PodIP{},EphemeralContainerStatuses:[]ContainerStatus{},},}
obj= 
apiVersion: v1
type: Opaque
stringData:
  userdata: "eGlhbndlaTExMQo="
kind: Secret
metadata:
  name: mySecret
secret obj =&Secret{ObjectMeta:{      0 0001-01-01 00:00:00 +0000 UTC <nil> <nil> map[] map[] [] []  []},Data:map[string][]byte{},Type:Opaque,StringData:map[string]string{},}
--- PASS: TestYamlfileMultiDocument (0.00s)
PASS

總結

本文介紹了YAML文檔的特點,并用代碼演示了GO語言對YAML文檔的處理,特別是描述了當YAML文件中存在多個YAML文檔時如何處理的方法。

到此這篇關于go解析YAML文件(多文檔解析)的文章就介紹到這了,更多相關go解析YAML文件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Golang中的sync.WaitGroup用法實例

    Golang中的sync.WaitGroup用法實例

    這篇文章主要介紹了Golang中的sync.WaitGroup用法實例,WaitGroup的用途,它能夠一直等到所有的goroutine執(zhí)行完成,并且阻塞主線程的執(zhí)行,直到所有的goroutine執(zhí)行完成,需要的朋友可以參考下
    2015-07-07
  • golang使用swagger的過程詳解

    golang使用swagger的過程詳解

    這篇文章主要介紹了golang使用swagger的過程詳解,本文給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧
    2024-06-06
  • Go語言實現(xiàn)UDP版聊天小工具的示例詳解

    Go語言實現(xiàn)UDP版聊天小工具的示例詳解

    這篇文章主要為大家詳細介紹了如何利用Go語言實現(xiàn)聊天小工具(UDP版),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-03-03
  • Go語言學習筆記之文件讀寫操作詳解

    Go語言學習筆記之文件讀寫操作詳解

    這篇文章主要為大家詳細介紹了Go語言對文件進行讀寫操作的方法,文中的示例代碼講解詳細,對我們學習Go語言有一定的幫助,需要的可以參考一下
    2022-05-05
  • Go語言rune與字符串轉換的密切關系解析

    Go語言rune與字符串轉換的密切關系解析

    這篇文章主要為大家介紹了Go語言rune與字符串轉換的密切關系示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12
  • 詳解Golang并發(fā)操作中常見的死鎖情形

    詳解Golang并發(fā)操作中常見的死鎖情形

    在Go的協(xié)程里面死鎖通常就是永久阻塞了,本文主要介紹了Golang并發(fā)操作中常見的死鎖情形,具有一定的參考價值,感興趣的可以了解一下
    2021-09-09
  • Golang時間比較的幾種方法小結

    Golang時間比較的幾種方法小結

    本文主要介紹了Golang時間比較的幾種方法小結,包括Before、 After、 Equal, 但是都需要轉成time類型來比較,下面就一起來了解一下,感興趣的可以了解游戲
    2025-06-06
  • Go語言的連接池管理的具體使用

    Go語言的連接池管理的具體使用

    這篇文章主要介紹了Go語言的連接池管理的具體使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2026-05-05
  • Go語言基礎反射示例詳解

    Go語言基礎反射示例詳解

    這篇文章主要為大家介紹了Go語言基礎關于反射示例的內(nèi)容詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪
    2021-11-11
  • 基于Golang協(xié)程機制實現(xiàn)高并發(fā)場景下的流量統(tǒng)計分析

    基于Golang協(xié)程機制實現(xiàn)高并發(fā)場景下的流量統(tǒng)計分析

    Go 語言(Golang)之所以在云原生和高并發(fā)領域獨樹一幟,核心在于其輕量級的協(xié)程和強大的通道機制,下面我們就來看看Golang如何基于協(xié)程機制實現(xiàn)高并發(fā)場景下的流量統(tǒng)計吧
    2026-01-01

最新評論

德格县| 嘉定区| 利辛县| 贵定县| 腾冲县| 太原市| 花莲市| 息烽县| 开原市| 英德市| 新密市| 原平市| 肥东县| 基隆市| 万源市| 迭部县| 古丈县| 尉犁县| 班戈县| 六枝特区| 偏关县| 伊春市| 都安| 安义县| 平阴县| 大余县| 锡林浩特市| 克什克腾旗| 柞水县| 澄城县| 三原县| 宁国市| 江孜县| 张家港市| 靖安县| 都兰县| 旬阳县| 秦皇岛市| 安塞县| 台北市| 太谷县|