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

Go語(yǔ)言七篇入門教程五文件及包

 更新時(shí)間:2021年11月09日 16:48:18   作者:小生凡一  
本章節(jié)主要介紹go語(yǔ)言的文件處理與包管理,本文是Go語(yǔ)言七篇入門教程系列篇,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步

1. 文件處理

1.1 JSON文件

什么是json?

JSON(JavaScript Object Notation) 是一種輕量級(jí)的數(shù)據(jù)交換格式。
也是在web開發(fā)中的前后端交互的格式。

encoding/json是官方提供的標(biāo)準(zhǔn) json, 實(shí)現(xiàn) RFC 7159 中定義的 JSON 編碼和解碼。
使用的時(shí)候需要預(yù)定義 struct,原理是通過(guò) reflection 和 interface 來(lái)完成工作。

常用的接口:

func Marshal(v interface{}) ([]byte, error) 	  // 生成 JSON
func Unmarshal(data []byte, v interface{}) error  // 解析 JSON 到 struct

1.1.1 已知JSON結(jié)構(gòu)

先看例子

package main
import (
	"encoding/json"
	"fmt"
)
type Person struct {
	Name string
	Age   string
}
type PersonSlice struct {
	Persons []Person
}
func main() {
	var s PersonSlice
	str := `{"persons":[{"Name":"FanOne","Age":"17"},{"Name":"FanOne2","Age":"18"},{"Name":"FanOne3","Age":"19"}]}`
	_ = json.Unmarshal([]byte(str), &s) 
	// Golang中提供軟件包"encoding/json"可以直接用來(lái)處理JSON文件,此包中解析JSON的函數(shù)為Unmarshal
	// 使用此函數(shù)可以將JSON文件解析到結(jié)構(gòu)體中
	fmt.Println(s.Persons)//[{FanOne 17} {FanOne2 18} {FanOne3 19}]
	for _,item:=range s.Persons{
		fmt.Println("Name",item.Name,"Age",item.Age)
		//Name FanOne Age 17
		//Name FanOne2 Age 18
		//Name FanOne3 Age 19
	}
}

上例中,首先定義了與json數(shù)據(jù)對(duì)應(yīng)的結(jié)構(gòu)體,數(shù)組對(duì)應(yīng)slice,字段名對(duì)應(yīng)JSON里面的KEY,

在解析的時(shí)候,如何將json數(shù)據(jù)與struct字段相匹配呢?例如JSON的key是Name,那么怎么找對(duì)應(yīng)的字段呢?

  • 首先查找tag含有Name的可導(dǎo)出的struct字段(首字母大寫)
  • 其次查找字段名是Name的導(dǎo)出字段
  • 最后查找類似NAME或者NaMe這樣的除了首字母之外其他大小寫不敏感的導(dǎo)出字段

其中需要注意一點(diǎn):能夠被賦值的字段必須是可導(dǎo)出字段(即首字母大寫)。因?yàn)橹挥惺鬃帜复髮懖拍鼙煌饷鎽?yīng)用,同時(shí)JSON解析的時(shí)候只會(huì)解析能找得到的字段,找不到的字段會(huì)被忽略。

這樣的一個(gè)好處是:當(dāng)你接收到一個(gè)很大的JSON數(shù)據(jù)結(jié)構(gòu)而你卻只想獲取其中的部分?jǐn)?shù)據(jù)的時(shí)候,你只需將你想要的數(shù)據(jù)對(duì)應(yīng)的字段名大寫,即可輕松解決這個(gè)問(wèn)題。

雖然沒(méi)有python直接.json那么方便,但是也還是算不錯(cuò)的。

1.1.2 未知JSON結(jié)構(gòu)

眾所周知,在Go語(yǔ)言中,interface{}可以用來(lái)存儲(chǔ)任意數(shù)據(jù)類型的對(duì)象,此數(shù)據(jù)結(jié)構(gòu)正好用于存儲(chǔ)解析的未知結(jié)構(gòu)的json數(shù)據(jù)的結(jié)果。

JSON包中采用map[string]interface{}[]interface{}結(jié)構(gòu)來(lái)存儲(chǔ)任意的JSON對(duì)象和數(shù)組。

Go類型和JSON類型的對(duì)應(yīng)關(guān)系如下:

bool 代表 JSON booleans,

float64 代表 JSON numbers,

string 代表 JSON strings,

nil 代表 JSON null.

b := []byte(`{
		"Name": "FanOne",
		"School": ["FZU", "XCZX", "UUUU", "GuaguaSong", "HanTuo",
		"City", "FuZhou"],
		"Major": "BigData",
		"IsPublished": true,
		"Price": 9.99,
		"Sales": 1000000
}`)
var r interface{}
err := json.Unmarshal(b, &r)

在上述代碼中,r 被定義為一個(gè)空接口。
json.Unmarshal()函數(shù)將一個(gè) JSON 對(duì)象解碼
到空接口 r 中,最終 r 將會(huì)是一個(gè)鍵值對(duì)的map[string]interface{}結(jié)構(gòu):

	map[string]interface{}{ 
		"Name": "FanOne",
		"School": ["FZU", "XCZX", "UUUU", "GuaguaSong", "HanTuo",
		"City", "FuZhou"],
		"Major": "BigData",
		"IsPublished": true,
		"Price": 9.99,
		"Sales": 1000000
	}

要訪問(wèn)解碼后的數(shù)據(jù)結(jié)構(gòu),需要先判斷目標(biāo)結(jié)構(gòu)是否為預(yù)期的數(shù)據(jù)類型:

gobook, ok := r.(map[string]interface{})

然后,我們可以通過(guò) for 循環(huán)搭配 range 語(yǔ)句一一訪問(wèn)解碼后的目標(biāo)數(shù)據(jù):

	if ok {
		for k, v := range gobook
		{
			switch v2 := v.(type)
			{
			case string:
				fmt.Println(k, "is string", v2)
			case int:
				fmt.Println(k, "is int", v2)
			case bool:
				fmt.Println(k, "is bool", v2)
			case []interface{}:
				fmt.Println(k, "is an array:")
				for i, iv := range v2 {
					fmt.Println(i, iv)
				}
			default:
				fmt.Println(k, "is another type not handle yet")
			}
		}
	}

雖然有些煩瑣,但的確是一種解碼未知結(jié)構(gòu)的 JSON 數(shù)據(jù)的安全方式。

1.1.3 Encoder & Decoder

Go 內(nèi)建的 encoding/json 包還提供 Decoder 和 Encoder 兩個(gè)類型,用于支持 JSON 數(shù)據(jù)的流式讀寫,并提供 NewDecoder()和 NewEncoder()兩個(gè)函數(shù)來(lái)便于具體實(shí)現(xiàn):

func NewDecoder(r io.Reader) *Decoder
func NewEncoder(w io.Writer) *Encoder
func main() {
	dec := json.NewDecoder(os.Stdin)
	enc := json.NewEncoder(os.Stdout)
	for {
		var v map[string]interface{}
		if err := dec.Decode(&v); err != nil{
			log.Println(err)
			return
		}
		for k := range v {
			if k != "Name" {
				v[k] = nil,false
			}
		}
		if err := enc.Encode(&v); err != nil{
			log.Println(err)
		}
	}
}

使用 Decoder 和 Encoder 對(duì)數(shù)據(jù)流進(jìn)行處理可以應(yīng)用得更為廣泛些,比如讀寫 HTTP 連接、WebSocket 或文件等,Go 的標(biāo)準(zhǔn)庫(kù) net/rpc/jsonrpc 就是一個(gè)應(yīng)用了 Decoder 和 Encoder的實(shí)際例子。

1.2 XML文件

XML 數(shù)據(jù)格式
對(duì)于如下的XML:

<Person>
    <FirstName>Fan</FirstName>
    <LastName>One</LastName>
</Person>

和 JSON 的方式一樣,XML 數(shù)據(jù)可以序列化為結(jié)構(gòu),或者從結(jié)構(gòu)反序列化為 XML 數(shù)據(jù);

encoding/xml包實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的 XML 解析器(SAX),用來(lái)解析 XML 數(shù)據(jù)內(nèi)容。下面的例子說(shuō)明如何使用解析器:

復(fù)制代碼
// xml.go
package main
import (
    "encoding/xml"
    "fmt"
    "strings"
)
var t, token xml.Token
var err error
func main() {
    input := "<Person><FirstName>Fan</FirstName><LastName>One</LastName></Person>"
    inputReader := strings.NewReader(input)
    p := xml.NewDecoder(inputReader)
    for t, err = p.Token(); err == nil; t, err = p.Token() {
        switch token := t.(type) {
        case xml.StartElement:
            name := token.Name.Local
            fmt.Printf("Token name: %s\n", name)
            for _, attr := range token.Attr {
                attrName := attr.Name.Local
                attrValue := attr.Value
                fmt.Printf("An attribute is: %s %s\n", attrName, attrValue)
            }
        case xml.EndElement:
            fmt.Println("End of token")
        case xml.CharData:
            content := string([]byte(token))
            fmt.Printf("This is the content: %v\n", content)
            // ...
        default:
            // ...
        }
    }
}

輸出:

Token name: Person
Token name: FirstName
This is the content: Fan
End of token
Token name: LastName
This is the content: One
End of token
End of token

包中定義了若干XML 標(biāo)簽類型:StartElement,Chardata(這是從開始標(biāo)簽到結(jié)束標(biāo)簽之間的實(shí)際文本)EndElement,Comment,Directive 或 ProcInst。

包中同樣定義了一個(gè)結(jié)構(gòu)解析器:
NewParser 方法持有一個(gè) io.Reader(這里具體類型是strings.NewReader)并生成一個(gè)解析器類型的對(duì)象。
還有一個(gè) Token() 方法返回輸入流里的下一個(gè) XML token。在輸入流的結(jié)尾處,會(huì)返回(nil,io.EOF)
XML 文本被循環(huán)處理直到 Token() 返回一個(gè)錯(cuò)誤,因?yàn)橐呀?jīng)到達(dá)文件尾部,再?zèng)]有內(nèi)容可供處理了。
通過(guò)一個(gè) type-switch 可以根據(jù)一些 XML 標(biāo)簽進(jìn)一步處理。Chardata中的內(nèi)容只是一個(gè) []byte,通過(guò)字符串轉(zhuǎn)換讓其變得可讀性強(qiáng)一些。

1.3 二進(jìn)制文件

go語(yǔ)言可以在win下進(jìn)行如下的設(shè)置將go程序build成二進(jìn)制文件

請(qǐng)?zhí)砑訄D片描述

set CGO_ENABLED=0
set GOOS=linux
set GOARCH=amd64
go build main.go

1.4 zip文件

1.4.1 創(chuàng)建zip

Go語(yǔ)言提供了archive/zip包來(lái)處理zip壓縮文件

func createZip(filename string) {
	// 緩存壓縮文件內(nèi)容
	buf := new(bytes.Buffer)
	// 創(chuàng)建zip
	writer := zip.NewWriter(buf)
	defer writer.Close()
	// 讀取文件內(nèi)容
	content, _ := ioutil.ReadFile(filepath.Clean(filename))
	// 接收
	f, _ := writer.Create(filename)
	f.Write(content)
	filename = strings.TrimSuffix(filename, path.Ext(filename)) + ".zip"
	ioutil.WriteFile(filename, buf.Bytes(), 0644)
}

1.4.2 讀取zip文件

讀取zip文檔過(guò)程與創(chuàng)建zip文檔過(guò)程類似,需要解壓后的文檔目錄結(jié)構(gòu)創(chuàng)建:

func readZip(filename string) {
      zipFile, err := zip.OpenReader(filename)  // 打開zip文件
		if err != nil {
			panic(err.Error())
		}
		defer zipFile.Close()
		for _, f := range zipFile.File {  // 循環(huán)讀取zip中的內(nèi)容
			info := f.FileInfo()
			if info.IsDir() { 
				err = os.MkdirAll(f.Name, os.ModePerm)
				if err != nil {
					panic(err.Error())
				}
				continue
			}
			srcFile, err := f.Open()  // 打開文件
			if err != nil {
				panic(err.Error())
			}
			defer srcFile.Close()
			newFile, err := os.Create(f.Name)
			if err != nil {
				panic(err.Error())
			}
			defer newFile.Close()
			io.Copy(newFile, srcFile)
		}
}

2. 包管理

2.1 包路徑

每一個(gè)包都通過(guò)一個(gè)唯一的字符串進(jìn)行標(biāo)識(shí),它稱為導(dǎo)入路徑,他們用在import聲明當(dāng)中。
對(duì)于準(zhǔn)備共享或公開的包需要全局唯一。當(dāng)然也要保證沒(méi)有循環(huán)的導(dǎo)包,循環(huán)的導(dǎo)包會(huì)引起報(bào)錯(cuò),而這也就涉及到了程序項(xiàng)目的整體層次結(jié)構(gòu)上了,這點(diǎn)以后再說(shuō)。

2.2 包聲明

在每一個(gè)Go源文件的路徑的最后一段,需要進(jìn)行聲明。主要目的是當(dāng)該包被其他包引入的時(shí)候作為默認(rèn)的標(biāo)識(shí)符。

例如在引入 "fmt"之后,可以訪問(wèn)到它的成員,fmt.Println(),可以注意到這個(gè)P是大寫的,說(shuō)明了,要大寫才能跨包引用。

當(dāng)我們導(dǎo)用的包的名字沒(méi)有在文件中引用的時(shí)候,就會(huì)有一個(gè)編譯錯(cuò)誤。我們可以使用_來(lái)代表

表示導(dǎo)入的內(nèi)容為空白標(biāo)識(shí)符。

在這里插入圖片描述

以上就是Go語(yǔ)言七篇入門教程五文件及包的詳細(xì)內(nèi)容,更多關(guān)于Go語(yǔ)言文件及包的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

如何學(xué)習(xí)Go

如果你是小白,你可以這樣學(xué)習(xí)Go語(yǔ)言~

七篇入門Go語(yǔ)言

第一篇:Go簡(jiǎn)介初識(shí)

第二篇:程序結(jié)構(gòu)&&數(shù)據(jù)類型的介紹

第三篇:函數(shù)方法接口的介紹

第四篇:通道與Goroutine的并發(fā)編程

第六篇:網(wǎng)絡(luò)編程

第七篇:GC垃圾回收三色標(biāo)記

相關(guān)文章

  • 理解Go流程控制與快樂(lè)路徑原則

    理解Go流程控制與快樂(lè)路徑原則

    這篇文章主要為大家介紹了Go流程控制與快樂(lè)路徑原則的原理解析,
    有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-10-10
  • Go時(shí)間操作常用方法(推薦!)

    Go時(shí)間操作常用方法(推薦!)

    平時(shí)開發(fā)過(guò)程中,時(shí)間相關(guān)的操作用的還是很多的,下面這篇文章主要給大家介紹了關(guān)于Go時(shí)間操作常用方法的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-06-06
  • Golang通過(guò)包長(zhǎng)協(xié)議處理TCP粘包的問(wèn)題解決

    Golang通過(guò)包長(zhǎng)協(xié)議處理TCP粘包的問(wèn)題解決

    本文主要介紹了Golang通過(guò)包長(zhǎng)協(xié)議處理TCP粘包的問(wèn)題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • 詳解如何在Go中使用Zap管理日志

    詳解如何在Go中使用Zap管理日志

    Zap提供了兩種類型的日志記錄器—Sugared?Logger和Logger,可以更好的管理日志,這篇文章主要為大家介紹了使用Zap管理日志的具體方法,需要的可以了解一下
    2023-07-07
  • go select的用法

    go select的用法

    本文主要介紹了go select的用法,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • Go泛型實(shí)戰(zhàn)教程之如何在結(jié)構(gòu)體中使用泛型

    Go泛型實(shí)戰(zhàn)教程之如何在結(jié)構(gòu)體中使用泛型

    這篇文章主要介紹了Go泛型實(shí)戰(zhàn)教程之如何在結(jié)構(gòu)體中使用泛型,根據(jù)Go泛型使用的三步曲提到的:類型參數(shù)化、定義類型約束、類型實(shí)例化我們一步步來(lái)定義我們的緩存結(jié)構(gòu)體,需要的朋友可以參考下
    2022-07-07
  • Golang負(fù)載均衡和?;钤O(shè)計(jì)原理示例探究

    Golang負(fù)載均衡和?;钤O(shè)計(jì)原理示例探究

    這篇文章主要為大家介紹了Golang負(fù)載均衡和保活設(shè)計(jì)原理示例探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-01-01
  • golang解析網(wǎng)頁(yè)利器goquery的使用方法

    golang解析網(wǎng)頁(yè)利器goquery的使用方法

    這篇文章主要給大家介紹了關(guān)于golang解析網(wǎng)頁(yè)利器goquery的使用方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考借鑒,下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-09-09
  • go web 預(yù)防跨站腳本的實(shí)現(xiàn)方式

    go web 預(yù)防跨站腳本的實(shí)現(xiàn)方式

    這篇文章主要介紹了go web 預(yù)防跨站腳本的實(shí)現(xiàn)方式,文中給大家介紹XSS最佳的防護(hù)應(yīng)該注意哪些問(wèn)題,本文通過(guò)實(shí)例代碼講解的非常詳細(xì),需要的朋友可以參考下
    2021-06-06
  • Golang 性能基準(zhǔn)測(cè)試(benchmark)詳解

    Golang 性能基準(zhǔn)測(cè)試(benchmark)詳解

    Golang性能基準(zhǔn)測(cè)試可以幫助開發(fā)人員比較不同的實(shí)現(xiàn)方式對(duì)性能的影響,以便優(yōu)化程序,本文就來(lái)講解一下如何使用Golang的性能基準(zhǔn)測(cè)試功能,需要的朋友可以參考下
    2023-06-06

最新評(píng)論