欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

概述

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

正文

yaml文檔介紹

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

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

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

YAML 文檔特點(diǎn)包括

  • 易讀性:YAML 使用縮進(jìn)和結(jié)構(gòu)化的格式,使得它非常易讀。它使用空格而不是特殊符號(hào)來表示層級(jí)關(guān)系,使得文檔具有良好的可讀性。

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

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

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

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

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

  • 可擴(kuò)展性:YAML 允許用戶通過自定義標(biāo)簽和類型的方式擴(kuò)展其功能,使其適應(yīng)更多的應(yīng)用場(chǎng)景和需求。

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

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

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

常用方法包括

  • Yaml.Marshal() 將結(jié)構(gòu)體對(duì)象 轉(zhuǎn)換為YAML字符串

  • yaml.Unmarshal() 將YAML字符串轉(zhuǎn)換為結(jié)構(gòu)體對(duì)象

代碼示例

yaml文件與結(jié)構(gòu)體之間的轉(zhuǎn)換

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

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

編寫測(cè)試代碼

// go test -run="^TestPersonStruct$"  -v
func TestPersonStruct(t *testing.T) {
  // 定義一個(gè)結(jié)構(gòu)體
	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字符串轉(zhuǎn)換為person對(duì)象
	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對(duì)象轉(zhuǎn)換為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))
}

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

  • yaml字符串轉(zhuǎn)換為person對(duì)象
  • Person對(duì)象轉(zhuǎn)換為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時(shí),需要注意的是,需要先將yaml串轉(zhuǎn)換為json串,再由json串Unmarshal成一個(gè)pod對(duì)象。原因是v1.pod類型定義中(源碼如下所示),只指定定義字符串的轉(zhuǎn)換。

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)建一個(gè)用于測(cè)試YAML文件pod-nginx.yaml

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

編寫測(cè)試代碼

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

	// yaml串轉(zhuǎn)換為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串轉(zhuǎn)換為pod結(jié)構(gòu)體
	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
	}
	
}

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

  • yaml字符串轉(zhuǎn)換為json字符串
  • 再由json字符串轉(zhuǎn)換pod對(duì)象
  • 最后使用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時(shí),經(jīng)常會(huì)將多個(gè)YAML文檔寫到一個(gè)YAML文件。此種情況下,可以通過按字符串"\n—"進(jìn)行分割,分別處理。

創(chuàng)建一個(gè)用于測(cè)試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

編寫測(cè)試代碼

// go test -run="^TestYamlfileMultiDocument" -mod=vendor -v
func TestYamlfileMultiDocument(t *testing.T) {
	// 將yaml文件轉(zhuǎn)換為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 {
		// 處理第一個(gè)yaml文檔,轉(zhuǎn)換為 pod 對(duì)象
		if index == 0 {
			// 轉(zhuǎn)換為對(duì)象
			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)
		}
		// 處理第二個(gè)yaml文檔,轉(zhuǎn)換為secret對(duì)象
		if index == 1 {
			fmt.Println("obj=", yamlObj)
			// 轉(zhuǎn)換為對(duì)象
			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)
		}

	}

}

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

  • 對(duì)yaml字符串按"\n—"進(jìn)行分割
  • 對(duì)分割后的第一個(gè)yaml文檔,轉(zhuǎn)換為 pod 對(duì)象
  • 對(duì)分割后的第二個(gè)yaml文檔,轉(zhuǎn)換為secret對(duì)象

代碼輸出

=== 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

總結(jié)

本文介紹了YAML文檔的特點(diǎn),并用代碼演示了GO語言對(duì)YAML文檔的處理,特別是描述了當(dāng)YAML文件中存在多個(gè)YAML文檔時(shí)如何處理的方法。

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

相關(guān)文章

  • golang函數(shù)的返回值實(shí)現(xiàn)

    golang函數(shù)的返回值實(shí)現(xiàn)

    本文主要介紹了golang函數(shù)的返回值實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • Go語言實(shí)現(xiàn)彩色輸出示例詳解

    Go語言實(shí)現(xiàn)彩色輸出示例詳解

    這篇文章主要為大家介紹了Go語言實(shí)現(xiàn)彩色輸出示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • GOLang?IO接口與工具使用方法講解

    GOLang?IO接口與工具使用方法講解

    這篇文章主要介紹了GOLang?IO接口與工具使用方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2023-03-03
  • Golang并發(fā)之RWMutex的用法詳解

    Golang并發(fā)之RWMutex的用法詳解

    在?Go?語言中,RWMutex?是一種讀寫互斥鎖的實(shí)現(xiàn),它提供了一種簡(jiǎn)單有效的方式來管理對(duì)共享資源的并發(fā)訪問。本文就來和大家詳細(xì)聊聊RWMutex的用法吧
    2023-04-04
  • golang使用信號(hào)量熱更新的實(shí)現(xiàn)示例

    golang使用信號(hào)量熱更新的實(shí)現(xiàn)示例

    這篇文章主要介紹了golang使用信號(hào)量熱更新的實(shí)現(xiàn)示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-04-04
  • Golang使用Token來驗(yàn)證

    Golang使用Token來驗(yàn)證

    token指的是一種用于驗(yàn)證用戶身份或授權(quán)訪問的憑證,本文主要介紹了Golang使用Token來驗(yàn)證,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-08-08
  • 關(guān)于Golang獲取當(dāng)前項(xiàng)目絕對(duì)路徑的問題

    關(guān)于Golang獲取當(dāng)前項(xiàng)目絕對(duì)路徑的問題

    這篇文章主要介紹了Golang獲取當(dāng)前項(xiàng)目絕對(duì)路徑的問題,通常的做法是go run用于本地開發(fā),用一個(gè)命令中快速測(cè)試代碼確實(shí)非常方便;在部署生產(chǎn)環(huán)境時(shí),我們會(huì)通過go build構(gòu)建出二進(jìn)制文件然后上傳到服務(wù)器再去執(zhí)行,那么會(huì)產(chǎn)生什么問題呢?感興趣的朋友一起看看吧
    2022-04-04
  • GO使用Mutex確保并發(fā)程序正確性詳解

    GO使用Mutex確保并發(fā)程序正確性詳解

    這篇文章主要為大家介紹了GO使用Mutex確保并發(fā)程序正確性詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • Go語言Handler詳細(xì)說明

    Go語言Handler詳細(xì)說明

    這篇文章主要介紹了Go語言Handler詳細(xì)說明,Handler用于處理請(qǐng)求并給予響應(yīng)。更嚴(yán)格地說,用來讀取請(qǐng)求體、并將請(qǐng)求對(duì)應(yīng)的響應(yīng)字段(respones header)寫入ResponseWriter中,需要的朋友可以參考下
    2022-04-04
  • Go基礎(chǔ)語法的使用

    Go基礎(chǔ)語法的使用

    本文主要介紹了Go基礎(chǔ)語法的使用,包括標(biāo)識(shí)符、關(guān)鍵字、行分隔符、var關(guān)鍵字、:=運(yùn)算符、空格、注釋、package、import、輸入輸出、運(yùn)算符、條件控制、循環(huán)等,感興趣的可以了解一下
    2023-11-11

最新評(píng)論