golang 读取 YAML

1. 从配置文件中获取

  • ./config/query-ip.yaml
influxdb: 
  server: <Your_Influxdb_Host>
  port: 8086
1
2
3
  • 代表示例

从配置文件中读取 influxdb 的 IP 和端口,然后将访问日志写入 DB

func initConfig() {

	viper.SetConfigName("query-ip") // YAML 文件名 (不带后缀)
	viper.AddConfigPath("./conf/")  //添加配置文件所在的路径
	// viper.SetConfigType("yaml")          //设置配置文件类型
	err3 := viper.ReadInConfig()
	if err3 != nil {
		fmt.Printf("config file error: %s\n", err3)
		os.Exit(1)
	}

	influxdbServer := viper.Get("influxdb.server")
	influxdbPort := viper.Get("influxdb.port")

	writeInfludbURL = fmt.Sprintf("http://%s:%d/write?db=<your_database>", influxdbServer, influxdbPort)

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

2. 从 HTTP Response 中获取 YAML

解析 cURL 命令获取本机外网 IP 中返回的 YAML 格式数据。

curl ipw.cn/locate?format=yaml

IP: 106.224.145.147
Address:
  Country: 中国
  Province: 江西省
  City: 南昌市
ISP: 电信
1
2
3
4
5
6
7
8

代码示例

package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"

	"github.com/spf13/viper"
)

func getIP(w http.ResponseWriter, req *http.Request) {

	queryURL := "https://ipw.cn/api/ip/locate?format=yaml"

	responseClient, errClient := http.Get(queryURL) // 获取外网 IP
	if errClient != nil {
		fmt.Printf("获取外网 IP 失败,请检查网络\n")
		panic(errClient)
	}
	// 程序在使用完 response 后必须关闭 response 的主体。
	defer responseClient.Body.Close()

	IPBody, _ := ioutil.ReadAll(responseClient.Body)

	fmt.Fprintf(w, "%s", string(IPBody))

	// 从 []byte 中解析 YAML
	viper.SetConfigType("yaml")
	viper.ReadConfig(bytes.NewBuffer(IPBody))

	IP := fmt.Sprintf("%s", viper.Get("IP"))
	Country := fmt.Sprintf("%s", viper.Get("Address.Country"))
	Province := fmt.Sprintf("%s", viper.Get("Address.Province"))
	City := fmt.Sprintf("%s", viper.Get("Address.City"))
	ISP := fmt.Sprintf("%s", viper.Get("ISP"))

	fmt.Printf("IP: %s\n", IP)
	fmt.Printf("Country: %s\n", Country)
	fmt.Printf("Province: %s\n", Province)
	fmt.Printf("City: %s\n", City)
	fmt.Printf("ISP: %s\n", ISP)

}

func main() {

	http.HandleFunc("/", getIP)
	log.Println("Starting server ...")
	log.Fatal(http.ListenAndServe(":80", nil))

}
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

运行程序 go run parse-yaml.gocurl localhost,可以看到后台输出日志。

2021/07/23 19:57:05 Starting server ...
IP: 106.224.145.147
Address:
  Country: 中国
  Province: 江西省
  City: 南昌市
ISP: 电信
1
2
3
4
5
6
7

FAQ

cannot find package "github.com/hashicorp/hcl/hcl/printer" in any of

github.com/spf13/viper 引用了 github.com/hashicorp/hcl/ 1.0 的包,如果 不启用 go modopen in new window ,将无法 go get github.com/spf13/viper

    cannot find package "github.com/hashicorp/hcl/hcl/printer" in any of:
        /usr/local/go/src/github.com/hashicorp/hcl/hcl/printer (from $GOROOT)
        /go/src/github.com/hashicorp/hcl/hcl/printer (from $GOPATH)
1
2
3

关于这一点,直接看 HCL Member 的解释 cannot find package hcl/hcl/printeropen in new window

I'm sorry you've encountered this problem.

Based on your error messages, it seems like you are using Go 1.16 in the legacy GOPATH mode rather than in the current Go Modules mode. Because GOPATH mode doesn't understand versioning, it's unable to distinguish between HCL version 1 and HCL version 2, and so it's failing to access what looks to be a HCL version 1 dependency.

There's some more details on what's going on here in the [Version Selection](https://github.com/hashicorp/hcl/wiki/Version-Selection) wiki page, but I think a shorter answer to this is that if you [migrate your project to use Go Modules](https://blog.golang.org/migrating-to-go-modules) instead of the legacy GOPATH mode then installing those HCL version 1 packages should work.

Due to technical constraints of the modern Go toolchain, we can no longer support the legacy GOPATH mode for HCL 1 without continuing the high-friction workarounds we employed for the first year after publishing major version 2, which have been a significant cause of confusion for contributors. For that reason, I'm going to close this issue.

I understand that some are getting HCL 1 as a dependency only indirectly via Viper (possibly Viper also indirectly via Cobra); unfortunately various parts of the Go ecosystem are moving gradually and independently to the modules system and so for some people HCL is the first thing in their dependency tree to begin requiring Go Modules, and I understand that is inconvenient but sadly if it were not this codebase then before too long it would be some other codebase because GOPATH mode is being phased out. 😖 The Viper team has also produced [a troubleshooting guide](https://github.com/spf13/viper/blob/master/TROUBLESHOOTING.md#cannot-find-package) which includes this problem at the time of writing, and they are echoing my suggestion to upgrade to Go Modules.
1
2
3
4
5
6
7
8
9

reference