如何申请免费的网站,设计上海展会2023,怎么给网站加外链,网站关键词选取文章目录 一、json以及序列化1.概述2.json应用场景图3.json数据格式说明4.json的序列化1#xff09;介绍2#xff09;应用案例 5.json的反序列化1#xff09;介绍2#xff09;应用案例 二、单元测试1.引子2.单元测试-基本介绍3.代码实现4.单元测试的细节说明5.单元测试的综… 文章目录 一、json以及序列化1.概述2.json应用场景图3.json数据格式说明4.json的序列化1介绍2应用案例 5.json的反序列化1介绍2应用案例 二、单元测试1.引子2.单元测试-基本介绍3.代码实现4.单元测试的细节说明5.单元测试的综合案例 一、json以及序列化
1.概述
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式易于人阅读和编写同时也易于机器解析和生成。key-val
JSON是2001年开始推广使用的数据格式目前已成为主流的数据格式
JSON易于机器解析和生成并有效地提升网络传输效率通常程序在网络传输时会先将数据结构体、map等序列化成json字符串时在反序列化恢复成原来的数据类型结构体、map等。这种方式已然成为各个语言的标准 2.json应用场景图 3.json数据格式说明
在JS语言中一切都是对象。因此任何支持的类型都可以通过JSON来表示例如字符串、数字、对象、数组等
JSON键值对是用来保存 数据的一种方式
键/值对组合中的键名写在前面并引用双引号“”包裹使用冒号:分隔然后紧接着值
[{“key1”:val1,“key2”:val2,“key3”:val3,“key4”:[val4,val5]},
{“key1”:val1,“key2”:val2,“key3”:val3,“key4”:[val4,val5]}]
比如
{firstName: Json}
比如
{name:tom,age:18,address:[北京,上海]}
比如
[{name:tom,age:18,address:[北京,上海]},
{name:tom,age:18,address:[北京,上海]}]任何数据类型都可以转换为json格式
json在线验证网站www.json.cn
4.json的序列化
1介绍
json序列化是指将有key-value结构的数据类型比如结构体、map、切片序列化成json字符串的操作
2应用案例
这里我们介绍一下结构体、map和切片的序列化其他数据类型的序列化类似
package main
import (fmtencoding/json
)//定义一个结构体
type Monster struct {Name stringAge intBirthday stringSal float64Skill string
}//将结构体序列化的演示
func testStruct() {//演示var monster Monster{Name : 牛魔王,Age : 500,Birthday : 2011-11-11,Sal : 8000.0,Skill : 牛魔拳,}//将moster进行序列化data, err : json.Marshal(monster)if err ! nil {fmt.Printf(序列化错误 err%v\n,err)}//输出序列化后的结果fmt.Printf(monster序列化后%v\n,string(data))
}//将Map序列化的演示
func testMap(){//定义一个Mapvar a map[string]interface{}//使用map需要makea make(map[string]interface{})a[name] 红孩儿a[age] 30a[address] 洪崖洞//将a这个map进行序列化data, err : json.Marshal(a)if err ! nil {fmt.Printf(序列化错误 err%v\n,err)}//输出序列化后的结果fmt.Printf(a map序列化后%v\n,string(data))
}//演示对切片进行序列化
func testSlice() {var slice []map[string]interface{}var m1 map[string]interface{}//使用map前需要先makem1 make(map[string]interface{})m1[name] jackm1[age] 30m1[address] 北京slice append(slice,m1)var m2 map[string]interface{}//使用map前需要先makem2 make(map[string]interface{})m2[name] tomm2[age] 20m2[address] [2]string{墨西哥,夏威夷}slice append(slice,m2)//将切片进行序列化操作data, err : json.Marshal(slice)if err ! nil {fmt.Printf(序列化错误 err%v\n,err)}//输出序列化后的结果fmt.Printf(slice序列化后%v\n,string(data))}//对基本数据类型进行序列化操作
func testFloat64() {var num1 float64 2345.67//对num1进行序列化data, err : json.Marshal(num1)if err ! nil {fmt.Printf(序列化错误 err%v\n,err)}//输出序列化后的结果fmt.Printf(num1序列化后%v\n,string(data))
}
func main() {//演示将结构体map,切片进行序列化testStruct()
//输出结果如下monster序列化后{Name:牛魔王,Age:500,Birthday:2011-11-11,Sal:8000,Skill:牛魔拳} testMap()
//输出结果如下a map序列化后{address:洪崖洞,age:30,name:红孩儿}testSlice()
//输出结果如下slice序列化后[{address:北京,age:30,name:jack},{address:墨西哥,age:20,name:tom}]testFloat64() //num1序列化后2345.67,将它变为字符串//将基本数据类型进行序列化意义不大
}注意事项对于结构体的序列化如果我们希望序列化后的key的名字由我们自己重新制定那么可以给struct指定一个tag标签
//定义一个结构体
type Monster struct {Name string json:monster_name//运用反射机制Age int json:monster_ageBirthday stringSal float64Skill string
}
//这样做可以指定key值序列化后monster序列化后{“monster_name”:“牛魔王”,“monster_age”:500,“Birthday”:“2011-11-11”,“Sal”:8000,“Skill”:“牛魔拳”}
5.json的反序列化
1介绍
json反序列化是指将json字符串反序列化成对应的数据类型比如结构体、map、切片的操作
2应用案例
这里我们介绍一下将jason字符串反序列化成结构体、map和切片
代码演示
package main
import (fmtencoding/json
)//定义一个结构体
type Monster struct {Name string Age intBirthday stringSal float64Skill string
}
//演示将json字符串。反序列化成struct
func umarshalstruct() {//说明str 在项目开发中是通过网络传输获取到的...或者通过读取文件得到str : {\Name\:\牛魔王\,\Age\:500,\Birthday\:\2011-11-11\,\Sal\:8000,\Skill\:\牛魔拳\}//定义一个Monster实例var monster Monstererr : json.Unmarshal([]byte(str),monster)if err ! nil {fmt.Printf(unmarshal err%v\n,err)}fmt.Printf(反序列化后 monster%v\n,monster)//单独取出结构体中的一个字段fmt.Printf(反序列化后 monster.Name%v\n,monster.Name)
}//演示将jason字符串反射成map
func unmarshalMap() {str : {\address\:\洪崖洞\,\age\:30,\name\:\红孩儿\}//定义一个mapvar a map[string]interface{}//反序列化就不需要进行make了因为他会自动进行make操作//反序列化err : json.Unmarshal([]byte(str),a)if err ! nil {fmt.Printf(unmarshal err%v\n,err)}fmt.Printf(反序列化后 a%v\n,a)//单独取出结构体中的一个字段// fmt.Printf(反序列化后 monster.Name%v\n,monster.Name)}
//演示将json串反序列化文slice
func unmarshalSlice() {str : [{\address\:\北京\,\age\:30,\name\:\jack\}, {\address\:[\墨西哥\,\夏威夷\],\age\:20,\name\:\tom\}]//定义一个切片var slice []map[string]interface{}//反序列化err : json.Unmarshal([]byte(str),slice)if err ! nil {fmt.Printf(unmarshal err%v\n,err)}fmt.Printf(反序列化后 slice%v\n,slice)}func main() {umarshalstruct()
//输出的结果为反序列化后 monster{牛魔王 500 2011-11-11 8000 牛魔拳}unmarshalMap()
//输出结果为反序列化后 amap[address:洪崖洞 age:30 name:红孩儿]unmarshalSlice()
//反序列化后 slice[map[address:北京 age:30 name:jack] map[address:[墨西哥 夏威夷] age:20 name:tom]] }对上面代码的注意事项 在反序列化一个json字符串时要确保反序列化后的数据类型和原来序列化前的数据类型一致 如果json字符串是通过程序获取获取到的则不需要对 “”进行转义处理因为转义处理已经包含在内部了
二、单元测试
1.引子
先看一个需求怎样确定他运行的结果是正确的
func addUpper (n int) int {res : 0for i :1;i n;i {res i}return res
}传统的方法解决
在main函数中调用addUpper函数看看实际输出的结果是否与你预期的结果一致如果一致则说明函数正确。否则函数有错误然后修改错误
package main
import (fmt
)
//一个被测试函数
func addUpper (n int) int {res : 0for i :1;i n;i {res i}return res
}
func main() {//传统的测试方法就是在main函数中使用看看结果是否正确res :addUpper(10)if res ! 55 {fmt.Printf(adUpper错误返回值%v 期望值%v\n,res,55)} else {fmt.Printf(adUpper正确返回值%v 期望值%v\n,res,55)}}传统方法的缺点分析
不方便我们需要在main函数中去调用这样就需要去修改main函数如果现在项目正在运行就可能去停止项目。不利于管理因为当我们测试多个函数或者多个模块时都需要写在main函数中不利于我们的管理和清晰我们的思路引出单元测试。-testing测试框架可以很好的解决问题
2.单元测试-基本介绍
go语言中自带一个轻量记得测试框架testing和自带的go test命令来完成单元测试和性能测试testing框架和其他语言中的测试框架类似可以基于该框架写相应的压力测试用例。通过单元测试可以解决以下问题
1确保每个函数是可运行的并且运行结果是正确的
2确保写出来的代码性能是好的
3单元测试及时的发现程序设计或实现的逻辑错误使问题及早暴露便于问题的定位解决而性能测试的重点在于发现程序设计上的一些问题让程序能够在高并发的情况下还能保持稳定
使用go的单元测试对addUpper和sub函数进行测试
注意测试时可能需要暂时退出360因为360可能认为生成的测试用例的程序是木马
3.代码实现
package main//一个被测试函数
func AddUpper (n int) int {res : 0for i :1;i n;i {res i}return res
}//求两个数的差
func getSub(n1 int,n2 int) int {return n1 - n2
}
cal_test.go
package main
import (_fmttesting //引入go的testing框架包
)//编写测试用例去测试去测试addUpper函数是否正确 、
func TestAddUpper(t *testing.T) {//调用res : AddUpper(10)if res ! 55 {//fmt.Println(AddUpper(10)执行错误期望值%v实际值%v\n,55,res)t.Fatalf(AddUpper(10)执行错误期望值%v实际值%v\n,55,res)}//如果正确输出日志t.Logf(AddUpper(10)执行正确...)
} sub_test.go
package main
import (_fmttesting //引入go的testing框架包
)//编写测试用例去测试去测试sub函数是否正确 、
func TestGetSub(t *testing.T) {//调用res : getSub(10,3)if res ! 7 {t.Fatalf(getSub(10)执行错误期望值%v实际值%v\n,7,res)}//如果正确输出日志t.Logf(getSub(10)执行正确...)
} 在cmd中执行go test -v就可以对此函数进行测试操作了 单元测试的运行原理 4.单元测试的细节说明 测试用例文件名必须以_test.go结尾比如cal_test.gocal不是固定的 测试用例函数必须以Test开头一般来说就是Test_被测试的函数名比如TestAddUpper. TestAddUpper(t testing.T)的形参类型必须是testing.T 一个测试用例文件中可以有多个测试用例函数比如TestUpper.TestSub 运行测试用例的指令为 cmd go test [如果运行正确无日志错误时会输出日志]cmdgo test -v [运行正确或者错误都输出日志] 当出现错误时可以用t.Fatalf来格式化输出错误信息并退出程序 t.Logf“”方法可以输出相应的日志 测试用例函数并没有放在main函数中也执行了这就是测试用例的方便之处 PASS表示测试用例运行成功FAIL表示测试用例运行失败 测试单个文件一定要带上被测试的源文件 go test -v cal.test,go cal.go 测试单个方法 go test -v -test.run TestAddUpper sd
5.单元测试的综合案例
1编写一个Monter结构体字段Name,Age,Skill
2给Monster绑定方法Store可以将一个Monster变量(对象)序列化后保存到文件中
3给Monster绑定方法ReStore可以将一个序列化的Monster,从文件中读取并反序列化为Monster对象
4编程测试用例文件store_go编写测试用例函数TestStore和TestRestore进行测试
monster.go
package monster
import (encoding/jsonio/ioutilfmt
)
type Monster struct {Name stringAge intSkill string
}//给Monster绑定方法Store可以将一个Monster变量(对象)序列化后保存到文件中
func (this *Monster) Store() bool{//先序列化data, err : json.Marshal(this)if err ! nil {fmt.Println(marshal err , err)return false}//保存到文件filePath : D:/test/test02/monster.sererr ioutil.WriteFile(filePath, data,0666)if err ! nil {fmt.Println(write file err , err)return false}return true//保存到文件中
}//给Monster绑定方法ReStore可以将一个序列化的Monster,从文件中读取
// 并反序列化为Monster对象
func (this *Monster) ReStore() bool {//1.先从文件中读取序列化字符串filePath : D:/test/test02/monster.serdata, err : ioutil.ReadFile(filePath)if err ! nil {fmt.Println(Read file err , err)return false}//2.使用读取到的data []byte对反序列化err json.Unmarshal(data,this)if err ! nil {fmt.Println(Unmarshal err , err)return false}return true
}monster_test.go
package monster
import (testing
)
//测试用例测试Store方法
func TestStore(t *testing.T) {//先创建一个Monster实例monster : Monster {Name : 红孩儿,Age : 10,Skill : 吐火,}res : monster.Store()if !res {t.Fatalf(monster.Store()错误希望为%v 实际为%v,true,res)}t.Logf(monster.Store()测试成功)}func TestReStore(t *testing.T) {//创建一个Monster实例不需要指定字段的值var monster Monster{}res : monster.ReStore()if !res {t.Fatalf(monster.ReStore()错误希望为%v 实际为%v,true,res)}//进一步判断if monster.Name ! 红孩儿 {t.Fatalf(monster.ReStore()错误希望为%v 实际为%v,true,monster.Name)}t.Logf(monster.ReStore()测试成功)}
cmd运行
D:\myfile\GO\project\src\go_code\TestUnit\demo2go test -v -test.run TestReStoreRUN TestReStore
--- PASS: TestReStore (0.00s)moster_test.go:35: monster.ReStore()测试成功
PASS
ok go_code/TestUnit/demo2 0.191s将测试文件中改一下
D:\myfile\GO\project\src\go_code\TestUnit\demo2go test -v -test.run TestReStoreRUN TestReStore
--- FAIL: TestReStore (0.00s)moster_test.go:32: monster.ReStore()错误希望为true 实际为红孩儿~
FAIL
exit status 1
FAIL go_code/TestUnit/demo2 0.181s
t.Logf(monster.ReStore()测试成功)}