Go 练习题 序列化和反序列化

1、day1

1.1、使用结构体统计文件内字符个数

go 复制代码
func main() {
	fileName := "/Users/zld/goproject/abc.txt"
	file, err := os.Open(fileName)
	if err != nil {
		fmt.Printf("open file err %v\n", err)
		return

	}
	defer file.Close()
	var count CharCount
	reader := bufio.NewReader(file)
	for {
		str, err := reader.ReadString('\n')
		if err == io.EOF {
			break
		}

		for _, v := range str {
			switch {
			case v >= 'a' && v <= 'z':
				fallthrough
			case v >= 'A' && v <= 'Z':
				count.ChCount++
			case v == ' ' || v == '\t':
				count.SpaceCount++
			case v >= '0' && v <= '9':
				count.NumCount++
			default:
				count.OtherCount++
			}
		}

		fmt.Printf("字符的个数为=%v,\n数字的个数=%v,\n空格的个数为=%v,\n其他字符的个数为=%v", count.ChCount, count.NumCount, count.SpaceCount, count.OtherCount)

	}
}
bash 复制代码
cat /Users/zld/goproject/abc.txt 
    da klk;lkl;kl;klkek ``                              123  lkal;ekldk                         `` ``
bash 复制代码
go build count.go 
bash 复制代码
go run count.go 
字符的个数为=24,
数字的个数=3,
空格的个数为=21,
其他字符的个数为=11

1.2、获取命令行所有参数

go 复制代码
package main

import (
	"fmt"
	"os"
)

func main() {
	fmt.Println("命令行的参数有", len(os.Args))
	for i, v := range os.Args {
		fmt.Printf("args[%v]=%v\n", i, v)
	}
}
bash 复制代码
go run args.go ddd bb dad -a ad
命令行的参数有 6
args[0]=/var/folders/1t/6cgnk_j12h9fmvb8_xgs2ych0000gn/T/go-build513664270/b001/exe/args
args[1]=ddd
args[2]=bb
args[3]=dad
args[4]=-a
args[5]=ad

1.3、flag 包解析命令行参数

go 复制代码
package main

import (
	"flag"
	"fmt"
)

func main() {
	var user string
	var host string
	var port int
	var pwd string
	flag.StringVar(&user, "u", "", "用户名,默认为空")
	flag.StringVar(&host, "h", "", "主机,默认为空")
	flag.StringVar(&pwd, "pwd", "localhost", "密码,默认为 localhost")
	flag.IntVar(&port, "port", 3306, "端口号,默认为 3306")
	//必须调用这个方法,具体使用方法参考文档 https://studygolang.com/pkgdoc
	flag.Parse()
	fmt.Printf("user=%v,\nhost=%v,\npwd=%v,\nport=%v", user, host, port, pwd)
}
bash 复制代码
go run flag.go -u=test -h=172.18.0.1 -port 990 -pwd 123456
user=test,
host=172.18.0.1,
pwd=990,
port=123456

1.4、 对数据类型进行序列化

go 复制代码
package main

import (
	"encoding/json"
	"fmt"
)

type Monster struct {
	Name     string
	Age      int
	Birthday string
	Sal      float64
	Skill    string
}

func testStruct() {
	monster := Monster{
		Name:     "牛魔王",
		Age:      500,
		Birthday: "2011-10-10",
		Sal:      8000.0,
		Skill:    "牛魔拳",
	}
	//将 monster 序列化
	data, err := json.Marshal(&monster)
	if err != nil {
		fmt.Printf("序列化失败 error%v", err)
	}
	fmt.Printf("monster 序列化后%v\n", string(data))

}

// 将 map 序列化
func testMap() {
	//定义一个 map
	var a map[string]interface{}
	//使用map之前需要 make
	a = make(map[string]interface{})
	a["name"] = "红孩儿"
	a["age"] = 30
	a["address"] = "洪崖洞"
	//map 是引用类型,不需要传入指针,直接传入 a 即可
	data, err := json.Marshal(&a)
	if err != nil {
		fmt.Printf("序列化失败 error%v", err)
	}
	fmt.Printf("a 序列化后%v\n", string(data))

}

// 演示对切片进行序列化

func testSlice() {
	var slice []map[string]interface{}
	var m1 map[string]interface{}
	m1 = make(map[string]interface{})
	m1["name"] = "jack"
	m1["age"] = 7
	m1["address"] = "北京"
	slice = append(slice, m1)
	var m2 map[string]interface{}
	m2 = make(map[string]interface{})
	m2["name"] = "tom"
	m2["age"] = 9
	m2["address"] = [2]string{"墨西哥", "夏威夷"}
	slice = append(slice, m2)
	//将切片进行序列化操作
	data, err := json.Marshal(&slice)
	if err != nil {
		fmt.Printf("序列化失败 error%v", err)
	}
	fmt.Printf("slice 序列化后%v\n", string(data))

}

// 对基本(普通)数据类型序列化
func testFloat64() {
	var num1 float64 = 2345.67
	data, err := json.Marshal(&num1)
	if err != nil {
		fmt.Printf("序列化失败 error%v", num1)
	}
	fmt.Printf("num1 序列化后%v", string(data))
}
func main() {
	// 可以验证数据类型是否符合 json 格式的网站 https://www.json.cn/
	// 演示将结构体/map/切片 序列化
	testStruct()
	// map 序列化后是无序的
	testMap()
	// 切片序列化
	testSlice()
	// 基本(普通)数据类型序列化
	testFloat64()

}
bash 复制代码
go run serialization.go 
monster 序列化后{"Name":"牛魔王","Age":500,"Birthday":"2011-10-10","Sal":8000,"Skill":"牛魔拳"}
a 序列化后{"address":"洪崖洞","age":30,"name":"红孩儿"}
slice 序列化后[{"address":"北京","age":7,"name":"jack"},{"address":["墨西哥","夏威夷"],"age":9,"name":"tom"}]
num1 序列化后2345.67

1.5、序列化 struct 时 tag 使用

当希望指定 struct 被序列化后的 key 时候,使用 struct tag 的方式(反射机制)。

go 复制代码
package main

import (
	"encoding/json"
	"fmt"
)

type Monster struct {
	Name     string `json:"monster_name"`
	Age      int    `json:"monster_age"`
	Birthday string
	Sal      float64
	Skill    string
}

func testStruct() {
	monster := Monster{
		Name:     "牛魔王",
		Age:      500,
		Birthday: "2011-10-10",
		Sal:      8000.0,
		Skill:    "牛魔拳",
	}
	//将 monster 序列化
	data, err := json.Marshal(&monster)
	if err != nil {
		fmt.Printf("序列化失败 error%v", err)
	}
	fmt.Printf("monster 序列化后%v\n", string(data))

}

// // 将 map 序列化
// func testMap() {
// 	//定义一个 map
// 	var a map[string]interface{}
// 	//使用map之前需要 make
// 	a = make(map[string]interface{})
// 	a["name"] = "红孩儿"
// 	a["age"] = 30
// 	a["address"] = "洪崖洞"
// 	//map 是引用类型,不需要传入指针,直接传入 a 即可
// 	data, err := json.Marshal(&a)
// 	if err != nil {
// 		fmt.Printf("序列化失败 error%v", err)
// 	}
// 	fmt.Printf("a 序列化后%v\n", string(data))

// }

// // 演示对切片进行序列化

// func testSlice() {
// 	var slice []map[string]interface{}
// 	var m1 map[string]interface{}
// 	m1 = make(map[string]interface{})
// 	m1["name"] = "jack"
// 	m1["age"] = 7
// 	m1["address"] = "北京"
// 	slice = append(slice, m1)
// 	var m2 map[string]interface{}
// 	m2 = make(map[string]interface{})
// 	m2["name"] = "tom"
// 	m2["age"] = 9
// 	m2["address"] = [2]string{"墨西哥", "夏威夷"}
// 	slice = append(slice, m2)
// 	//将切片进行序列化操作
// 	data, err := json.Marshal(&slice)
// 	if err != nil {
// 		fmt.Printf("序列化失败 error%v", err)
// 	}
// 	fmt.Printf("slice 序列化后%v\n", string(data))

// }

// // 对基本(普通)数据类型序列化
//
//	func testFloat64() {
//		var num1 float64 = 2345.67
//		data, err := json.Marshal(&num1)
//		if err != nil {
//			fmt.Printf("序列化失败 error%v", num1)
//		}
//		fmt.Printf("num1 序列化后%v", string(data))
//	}
func main() {
	// 可以验证数据类型是否符合 json 格式的网站 https://www.json.cn/
	// 演示将结构体/map/切片 序列化
	testStruct()
	// map 序列化后是无序的
	// testMap()
	// // 切片序列化
	// testSlice()
	// // 基本(普通)数据类型序列化
	// testFloat64()

}
bash 复制代码
go run serialization.go 
monster 序列化后{"monster_name":"牛魔王","monster_age":500,"Birthday":"2011-10-10","Sal":8000,"Skill":"牛魔拳"}

1.5、对json进行反序列化

go 复制代码
package main

import (
	"encoding/json"
	"fmt"
)

// 将json反序列化成结构体
// 定义一个结构体
type Monster struct {
	Name     string `json:"monster_name"`
	Age      int    `json:"monster_age"`
	Birthday string
	Sal      int
	Skill    string
}

func unmarshalStruct() {
	str := "{\"monster_name\":\"牛魔王\",\"monster_age\":500,\"Birthday\":\"2011-10-10\",\"Sal\":8000,\"Skill\":\"牛魔拳\"}"
	//定义一个 monster实例
	var monster Monster
	err := json.Unmarshal([]byte(str), &monster)
	if err != nil {
		fmt.Printf("unmarshal err=%v\n", err)
	}
	fmt.Printf("反序列化后 monster=%v\n", monster)
}

// 将json反序列化成map
var a map[string]interface{}

// 注意:反序列化map 不需要make,因为make操作被封装到 json.Unmarshal 函数
func unmarshalMap() {
	str := "{\"address\":\"洪崖洞\",\"age\":30,\"name\":\"红孩儿\"}"
	//定义一个map
	//var a map[string]interface{}
	//反序列化
	err := json.Unmarshal([]byte(str), &a)
	if err != nil {
		fmt.Printf("unmalshal err=%v\n", err)
	}
	fmt.Printf("反序列化后 a=%v\n", a)
}

// 将 json 反序列化成 slice
func unmarshalSlice() {
	str := "[{\"address\":\"北京\",\"age\":7,\"name\":\"jack\"}," +
		"{\"address\":[\"墨西哥\",\"夏威夷\"],\"age\":9,\"name\":\"tom\"}]"
		//定义一个 slice
	var slice []map[string]interface{}
	//反序列化,不需要make,因为make操作被封装到 json.Unmarshal 函数
	err := json.Unmarshal([]byte(str), &slice)
	if err != nil {
		fmt.Printf("unmarshal err=%v\n", err)
	}
	fmt.Printf("反序列化后 slice=%v\n", slice)

}
func main() {
	unmarshalStruct()
	unmarshalMap()
	unmarshalSlice()

}

运行结果

go 复制代码
go run unmarshal.go 
反序列化后 monster={牛魔王 500 2011-10-10 8000 牛魔拳}
反序列化后 a=map[address:洪崖洞 age:30 name:红孩儿]
反序列化后 slice=[map[address:北京 age:7 name:jack] map[address:[墨西哥 夏威夷] age:9 name:tom]]
相关推荐
Narutolxy4 分钟前
深入探讨 Go 中的高级表单验证与翻译:Gin 与 Validator 的实践之道20241223
开发语言·golang·gin
Hello.Reader12 分钟前
全面解析 Golang Gin 框架
开发语言·golang·gin
hkNaruto21 小时前
【P2P】【Go】采用go语言实现udp hole punching 打洞 传输速度测试 ping测试
golang·udp·p2p
入 梦皆星河21 小时前
go中常用的处理json的库
golang
海绵波波1071 天前
Gin-vue-admin(2):项目初始化
vue.js·golang·gin
每天写点bug1 天前
【go每日一题】:并发任务调度器
开发语言·后端·golang
一个不秃头的 程序员1 天前
代码加入SFTP Go ---(小白篇5)
开发语言·后端·golang
基哥的奋斗历程1 天前
初识Go语言
开发语言·后端·golang
ZVAyIVqt0UFji1 天前
go-zero负载均衡实现原理
运维·开发语言·后端·golang·负载均衡
唐墨1231 天前
golang自定义MarshalJSON、UnmarshalJSON 原理和技巧
开发语言·后端·golang