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) 	  // 生成 JSON
func Unmarshal(data []byte, v interface{}) error  // 解析 JSON 到 struct

1.1.1 已知JSON结构

先看例子

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"可以直接用来处理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解析的时候只会解析能找得到的字段,找不到的字段会被忽略。

这样的一个好处是:当你接收到一个很大的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) *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 对数据流进行处理可以应用得更为广泛些,比如读写 HTTP 连接、WebSocket 或文件等,Go 的标准库 net/rpc/jsonrpc 就是一个应用了 Decoder 和 Encoder的实际例子。

1.2 XML文件

XML 数据格式
对于如下的XML:

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

和 JSON 的方式一样,XML 数据可以序列化为结构,或者从结构反序列化为 XML 数据;

encoding/xml包实现了一个简单的 XML 解析器(SAX),用来解析 XML 数据内容。下面的例子说明如何使用解析器:

复制代码
// 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 标签类型: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=0
set GOOS=linux
set GOARCH=amd64
go 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的并发编程

第六篇:网络编程

第七篇:GC垃圾回收三色标记

(0)

相关推荐

  • 谈论Go 什么时候会触发 GC问题

    目录 1.什么是 GC 2.为什么要 GC 3.GC 触发场景 3.1系统触发 3.2手动触发 3.3 基本流程 3.4 在哪触发 4.监控线程 5.堆内存申请 在早期经常遭到唾弃的就是在垃圾回收(下称:GC)机制中 STW(Stop-The-World)的时间过长.那么这个时候,我们又会好奇一点,作为 STW 的起始,Go 语言中什么时候才会触发 GC 呢? 1.什么是 GC 在计算机科学中,垃圾回收(GC)是一种自动管理内存的机制,垃圾回收器会去尝试回收程序不再使用的对象及其占用的内存. 最

  • 图解Golang的GC垃圾回收算法

    虽然Golang的GC自打一开始,就被人所诟病,但是经过这么多年的发展,Golang的GC已经改善了非常多,变得非常优秀了. 以下是Golang GC算法的里程碑: v1.1 STW v1.3 Mark STW, Sweep 并行 v1.5 三色标记法 v1.8 hybrid write barrier 经典的GC算法有三种: 引用计数(reference counting) . 标记-清扫(mark & sweep) . 复制收集(Copy and Collection) . Golang的G

  • go:垃圾回收GC触发条件详解

    版本: go version go1.13 darwin/amd64 在go源码runtime目录中找到gcTrigger结构体,就能看出大致调用的位置 GC调用方式 所在位置 代码 定时调用 runtime/proc.go:forcegchelper() gcStart(gcTrigger{kind: gcTriggerTime, now: nanotime()}) 分配内存时调用 runtime/malloc.go:mallocgc() gcTrigger{kind: gcTriggerHe

  • Go语言七篇入门教程七GC垃圾回收三色标记

    目录 GC 如何判断一个对象是否可达 三色标记法 原理如下 GC GC全称Garbage Collection 目前主流的垃圾回收算法有两类,分别是追踪式垃圾回收算法(Tracing garbage collection)和引用计数法( Reference counting ). 而三色标记法是属于追踪式垃圾回收算法的一种. 追踪式算法的核心思想是判断一个对象是否可达,因为一旦这个对象不可达就可以立刻被 GC 回收了. 如何判断一个对象是否可达 分为两步: 第一步找出所有的全局变量和当前函数栈里

  • Go语言七篇入门教程六网络编程

    目录 1. Socket 编程 1.1 Dial()函数 2. HTTP 编程 2.1 HTTP 客户端 2.2 HTTP 服务端 2.2.1 处理 HTTP 请求 3. RPC 编程 3.1 Go 语言中的 RPC 支持与处理 3.2 Gob 简介 3.3 设计优雅的 RPC 接口 1. Socket 编程 在 Go 语言中编写网络程序时,我们将看不到传统的编码形式.以前我们使用 Socket 编程时,会按照如下步骤展开. 建立 Socket:使用 socket()函数. 绑定 Socket:

  • Go语言七篇入门教程四通道及Goroutine

    目录 1. 前言 2. 通道简介 2.1 声明 2.1 读写 2.3 通道详解 2.3.1 例子 2.3.2 死锁 2.3.3 关闭通道 2.3.4 缓冲区 2.3.5 通道的长度和容量 2.3.6 单向通道 2.3.7 Select 2.3.8 default case 块 2.3.9 空 select 2.3.10 Deadlock 2.3.11 nil通道 2.4 多协程协同工作 2.5 WaitGroup 2.5.1 简介 2.5.2工作池 2.5.3 Mutex 3. 结语 如何学习G

  • 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开发中的前后

  • Go语言七篇入门教程三函数方法及接口

    目录 1. 函数 2. 方法 3. 接口 如何学习Go 参考书籍: <go语言程序设计> 1. 函数 每个函数声明都包含一个名字,一个形参列表,一个可选的返回列表以及函数体: func name(parameter-list)(result-list){ body } 形参列表:指定另一组变量的参数名和参数类型,这些局部变量都由调用者提供的提供的实参传递而来的. 返回列表:指定了函数返回值的类型.当函数返回一个未命名的返回值或者没有返回值的时候,返回列表的圆括号可以忽略. func FanOn

  • Go语言七篇入门教程一简介初识

    目录 简介 为什么是Go Go应用 Web Cloud 云 BlockChain 区块链 如何学习Go 其实我自己接触Go语言也还不到一年,20年的10月我才开始学Go的. 我自己也并不是很懂,但是我希望我能帮助到你学习Go语言,我们可以一起学习交流~ Go语言的吉祥物-金花鼠我一直以为是土拨鼠 在某搜索引擎上一搜golang一堆表情包. 简介 Go语言亦叫Golong语言,是由谷歌Goggle公司推出.Go语言的主要开发者有:肯.汤姆逊(Ken Thompson).罗布.派克(Rob Pike

  • Go语言七篇入门教程二程序结构与数据类型

    目录 1. 程序结构 1.1 名称 1.2 声明 1.3 注释 1.4 单双引号 1.5 输出 2. 数据类型 2.1 整型 2.2 浮点型 2.3 复数 2.4 布尔型 2.5 字符串 2.6 常量 2.7 数组 2.8 切片 2.9 map 2.10 结构体 2.11 JSON 3. 流程控制 3.1 条件语句 3.2 选择语句 3.3 循环语句 如何学习Go 1. 程序结构 1.1 名称 如果一个实体名称在函数中声明,它只在函数局部有效.如果声明在函数外,它将对包里面的所有源文件可见. 实

  • 零基础易语言入门教程(五)之逻辑型数据类型

    在上篇文章给大家介绍了零基础易语言入门教程(四)之数据类型,上篇针对数值到文本类型知识,今天给大家介绍下逻辑型数据. 具体方法和步骤如下所示: 1.逻辑型数据非真即假: 首先申请一个局部变量(A)类型为:逻辑型,编写代码为:A=1>2,那么输出的结果应为假,因等于1是赋值与1,然后代码中写道1大于2,所以这是假的,见下图所示: 2.关系运算符: 在上图大家需注意的是,A后面的等于号是赋值符号,而后面的≥,≠,<一些符号则是关系运算符. 关系运算符不是非要设置变量给其赋值才可以使用的,同样他可以

  • nodejs入门教程五:连接数据库的方法分析

    本文实例讲述了nodejs入门教程之连接数据库的方法.分享给大家供大家参考,具体如下: 参考文章链接:  nodejs连接mysql 1.准备工作 在nodejs中没有mysql模块,但npm中提供了mysql,所以可以使用npm安装mysql 命令:npm install mysql, 会生成 node_modules 文件夹 ,如图 执行后发现报了一个警告,说没有package.json 这个文件,只需要执行 npm init -f 的命令就会生成一个这个文件 2.直接连接数据库 mysql

  • Lua语言新手简单入门教程

    一.前言 Lua 是一种轻量小巧的脚本语言,用标准 C 语言编写并以源代码形式开放,其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能. Lua 可以应用在游戏开发.独立应用脚本.Web 应用脚本.扩展和数据库插件.安全系统等场景. 笔者学习的目的主要是为了能在 Web 应用(Nginx.Redis)中使用到 Lua 脚本. 特点 Lua脚本可以很容易的被C/C++ 代码调用,也可以反过来调用C/C++的函数. Lua由标准C编写而成,代码简洁优美,几乎在所有操作系统和平台上

随机推荐