Go语言七篇入门教程五文件及包
目录
- 1. 文件处理
- 1.1 JSON文件
- 1.1.1 已知JSON结构
- 1.1.2 未知JSON结构
- 1.1.3 Encoder & Decoder
- 1.2 XML文件
- 1.3 二进制文件
- 1.4 zip文件
- 1.4.1 创建zip
- 1.4.2 读取zip文件
- 2. 包管理
- 2.1 包路径
- 2.2 包声明
- 如何学习Go
1. 文件处理
1.1 JSON文件
什么是
json
?JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。
也是在web开发中的前后端交互的格式。
encoding/json
是官方提供的标准 json, 实现 RFC 7159 中定义的 JSON 编码和解码。使用的时候需要预定义 struct,原理是通过 reflection 和 interface 来完成工作。
常用的接口:
func Marshal(v interface{}) ([]byte, error)// 生成 JSONfunc Unmarshal(data []byte, v interface{}) error// 解析 JSON 到 struct
1.1.1 已知JSON结构 先看例子
package mainimport ( "encoding/json" "fmt")type Person struct { Name string Agestring}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"可以直接用来处理JSON文件,此包中解析JSON的函数为Unmarshal // 使用此函数可以将JSON文件解析到结构体中 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数据对应的结构体,数组对应slice,字段名对应JSON里面的KEY,
在解析的时候,如何将json数据与struct字段相匹配呢?例如JSON的key是Name,那么怎么找对应的字段呢?
- 首先查找tag含有Name的可导出的struct字段(首字母大写)
- 其次查找字段名是Name的导出字段
- 最后查找类似NAME或者NaMe这样的除了首字母之外其他大小写不敏感的导出字段
这样的一个好处是:当你接收到一个很大的JSON数据结构而你却只想获取其中的部分数据的时候,你只需将你想要的数据对应的字段名大写,即可轻松解决这个问题。
虽然没有python直接.json那么方便,但是也还是算不错的。
1.1.2 未知JSON结构 众所周知,在Go语言中,
interface{}
可以用来存储任意数据类型的对象,此数据结构正好用于存储解析的未知结构的json数据的结果。JSON包中采用
map[string]interface{}
和[]interface{}
结构来存储任意的JSON对象和数组。Go类型和JSON类型的对应关系如下:
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 被定义为一个空接口。
json.Unmarshal()
函数将一个 JSON 对象解码到空接口 r 中,最终 r 将会是一个键值对的
map[string]interface{}
结构:map[string]interface{}{ "Name": "FanOne","School": ["FZU", "XCZX", "UUUU", "GuaguaSong", "HanTuo","City", "FuZhou"],"Major": "BigData","IsPublished": true,"Price": 9.99,"Sales": 1000000 }
要访问解码后的数据结构,需要先判断目标结构是否为预期的数据类型:
gobook, ok := r.(map[string]interface{})然后,我们可以通过 for 循环搭配 range 语句一一访问解码后的目标数据:
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")}} }
虽然有些烦琐,但的确是一种解码未知结构的 JSON 数据的安全方式。
1.1.3 Encoder & Decoder Go 内建的 encoding/json 包还提供 Decoder 和 Encoder 两个类型,用于支持 JSON 数据的流式读写,并提供 NewDecoder()和 NewEncoder()两个函数来便于具体实现:
func NewDecoder(r io.Reader) *Decoderfunc 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 对数据流进行处理可以应用得更为广泛些,比如读写 HTTP 连接、WebSocket 或文件等,Go 的标准库 net/rpc/jsonrpc 就是一个应用了 Decoder 和 Encoder的实际例子。
1.2 XML文件
XML 数据格式
对于如下的XML:
Fan One
和 JSON 的方式一样,XML 数据可以序列化为结构,或者从结构反序列化为 XML 数据;
encoding/xml
包实现了一个简单的 XML 解析器(SAX),用来解析 XML 数据内容。下面的例子说明如何使用解析器:复制代码// xml.gopackage mainimport ("encoding/xml""fmt""strings")var t, token xml.Tokenvar err errorfunc main() {input := "Fan One "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.Localfmt.Printf("Token name: %s\n", name)for _, attr := range token.Attr {attrName := attr.Name.LocalattrValue := attr.Valuefmt.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: PersonToken name: FirstNameThis is the content: FanEnd of tokenToken name: LastNameThis is the content: OneEnd of tokenEnd of token
包中定义了若干
XML
标签类型:StartElement,Chardata(这是从开始标签到结束标签之间的实际文本)EndElement,Comment,Directive 或 ProcInst。包中同样定义了一个结构解析器:
NewParser
方法持有一个 io.Reader
(这里具体类型是strings.NewReader
)并生成一个解析器类型的对象。还有一个
Token()
方法返回输入流里的下一个 XML token
。在输入流的结尾处,会返回(nil,io.EOF)
XML 文本被循环处理直到
Token()
返回一个错误,因为已经到达文件尾部,再没有内容可供处理了。通过一个
type-switch
可以根据一些 XML 标签进一步处理。Chardata
中的内容只是一个 []byte
,通过字符串转换让其变得可读性强一些。1.3 二进制文件
go语言可以在win下进行如下的设置将go程序build成二进制文件
文章图片
set CGO_ENABLED=0set GOOS=linuxset GOARCH=amd64go build main.go
1.4 zip文件
1.4.1 创建zip Go语言提供了
archive/zip
包来处理zip压缩文件func createZip(filename string) { // 缓存压缩文件内容 buf := new(bytes.Buffer) // 创建zip writer := zip.NewWriter(buf) defer writer.Close() // 读取文件内容 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文档过程与创建zip文档过程类似,需要解压后的文档目录结构创建:
func readZip(filename string) {zipFile, err := zip.OpenReader(filename)// 打开zip文件if err != nil {panic(err.Error())}defer zipFile.Close()for _, f := range zipFile.File {// 循环读取zip中的内容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 包路径
每一个包都通过一个唯一的字符串进行标识,它称为导入路径,他们用在
import
声明当中。对于准备共享或公开的包需要全局唯一。当然也要保证没有循环的导包,循环的导包会引起报错,而这也就涉及到了程序项目的整体层次结构上了,这点以后再说。
2.2 包声明
在每一个Go源文件的路径的最后一段,需要进行声明。主要目的是当该包被其他包引入的时候作为默认的标识符。
例如在引入
"fmt"
之后,可以访问到它的成员,fmt.Println()
,可以注意到这个P
是大写的,说明了,要大写才能跨包引用。当我们导用的包的名字没有在文件中引用的时候,就会有一个编译错误。我们可以使用
_
来代表表示导入的内容为空白标识符。
文章图片
以上就是Go语言七篇入门教程五文件及包的详细内容,更多关于Go语言文件及包的资料请关注脚本之家其它相关文章!
如何学习Go 如果你是小白,你可以这样学习Go语言~
七篇入门Go语言
第一篇:Go简介初识
第二篇:程序结构&&数据类型的介绍
第三篇:函数方法接口的介绍
第四篇:通道与Goroutine的并发编程
第六篇:网络编程
【Go语言七篇入门教程五文件及包】第七篇:GC垃圾回收三色标记
推荐阅读
- 【生信技能树】R语言练习题|【生信技能树】R语言练习题 - 中级
- 一起来学习C语言的字符串转换函数
- C语言字符函数中的isalnum()和iscntrl()你都知道吗
- C语言浮点函数中的modf和fmod详解
- C语言中的时间函数clock()和time()你都了解吗
- C语言学习|第十一届蓝桥杯省赛 大学B组 C/C++ 第一场
- C语言解方程的根和判断是否是闰年
- C语言的版本比较
- 【C】题目|【C语言】题集 of ⑥
- echart|echart 双轴图开发