目录
一、概述
1、命令行参数
os.Args是一个string的切片,用来存储所有的命令行参数
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)
}
}
===============================
运行结果如下:
D:\GO_WORKSPACE\src\go_code\project03\day03>go build main.go
D:\GO_WORKSPACE\src\go_code\project03\day03>main.exe 1 2 3 4 5
命令行参数有 6
args[0]=main.exe
args[1]=1
args[2]=2
args[3]=3
args[4]=4
args[5]=5
D:\GO_WORKSPACE\src\go_code\project03\day03>
1.1、flag包用来解析命令行参数
带有指定命令行参数形式的命令行,参数位置可以随意
import "flag"
func StringVar(p *string, name string, value string, usage string):
StringVar用指定的名称、默认值、使用信息注册一个string类型flag,并将flag的值保存到p指向的变量。
func IntVar(p *int, name string, value int, usage string):
IntVar用指定的名称、默认值、使用信息注册一个int类型flag,并将flag的值保存到p指向的变量。
=================================================
package main
import (
"fmt"
"flag"
)
func main(){
var user string
var pwd string
var host string
var port int
flag.StringVar(&user,"u","","用户名,默认为空")
flag.StringVar(&pwd,"pwd","","密码,默认为空")
flag.StringVar(&host,"h","localhost","主机名,默认为localhost")
flag.IntVar(&port,"port",3306,"端口号,默认为3306")
flag.Parse()//转换,必须调用
fmt.Printf("user=%v\npwd=%v\nhost=%v\nport=%v\n",user,pwd,host,port)
}
==============================
运行结果如下:
D:\GO_WORKSPACE\src\go_code\project03\day03\01>main.exe -u root -pwd 123456 -h 127.0.0.1 -port 3306
user=root
pwd=123456
host=127.0.0.1
port=3306
2、Json
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。
JSON是在2001年开始推广使用的数据格式,目前已经成为主流的数据格式。
JSON易于机器解析和生成,并有效地提升网络传输效率,通常程序在网络传输时先将数据(结构体、map等)序列化成json字符串,到接收方得到json字符串时,在反序列化恢复成原来的数据类型(结构体、map等)。这种方式已然成为各个语言的标准。
在JS语言中,一切都是对象。因此,任何的数据类型都可以通过JSON来表示,例如字符串、数字、对象、数组等。
JSON转换网站验证一个json格式的数据是否正确。
2.1、Json的序列化
json序列化是指:将有key-value结构的数据类型(比如结构体、map、切片)序列化成json字符串的操作。
import "encoding/json"
func Marshal(v interface{}) ([]byte, error):Marshal函数返回v的json编码。
=========================================
package main
import (
"fmt"
"encoding/json"
)
type Monster struct{
Name string
Age int
Sal float64
Skill string
}
func structSerial(){
monster := Monster{
Name :"牛魔王",
Age :500,
Sal :8000.0,
Skill :"牛魔拳",
}
//将结构体序列化
data,err := json.Marshal(&monster)
if err != nil {
fmt.Printf("序列化错误 err=%v\n",err)
}
//输出序列化后的结果
fmt.Printf("moster序列化后=%v\n",string(data))
}
func main(){
structSerial()
}
//moster序列化后={"Name":"牛魔王","Age":500,"Sal":8000,"Skill":"牛魔拳"}
对于结构体的序列化,如果我们希望序列化后的key的名字,由我们自己重新指定,那么可以给结构体指定一个tag标签
type Monster struct{
Name string `json:"name"`
Age int `json:"age"`
Sal float64
Skill string
}
//上面的序列化代码改完之后执行结果
//moster序列化后={"name":"牛魔王","age":500,"Sal":8000,"Skill":"牛魔拳"}
2.2、Json的反序列化
json反序列化是指:将json字符串反序列化成对应的数据类型(比如结构体、map、切片)的操作。
import "encoding/json"
func Unmarshal(data []byte, v interface{}) error:Unmarshal函数解析json编码的数据并将结果存入v指向的值。
==================================================
package main
import (
"fmt"
"encoding/json"
)
type Monster struct{
Name string `json:"name"`
Age int `json:"age"`
Sal float64
Skill string
}
func unMarshalStruct(){
str :="{\"name\":\"牛魔王\",\"age\":500,\"Sal\":8000,\"Skill\":\"牛魔拳\"}"
var monster Monster
err := json.Unmarshal([]byte(str),&monster)
if err != nil {
fmt.Printf("反序列化错误 err=%v\n",err)
}
//输出序列化后的结果
fmt.Printf("反序列化后 monster=%v\n",monster)
}
func main(){
unMarshalStruct()
unMarshalMap()
unMarshalSlice()
}
func unMarshalMap(){
str := "{\"name\":\"小明\",\"age\":30}"
//反序列化时map不需要make,因为make操作被封装到Unmarshal函数中
var aMap map[string]interface{}
err := json.Unmarshal([]byte(str),&aMap)
if err != nil {
fmt.Printf("反序列化错误 err=%v\n",err)
}
//输出序列化后的结果
fmt.Printf("反序列化后 aMap=%v\n",aMap)
}
func unMarshalSlice(){
str := "[{\"name\":\"小明\",\"age\":\"30\"}," +
"{\"name\":\"小王\",\"age\":\"31\"}]"
var slice []map[string]interface{}
err := json.Unmarshal([]byte(str),&slice)
if err != nil {
fmt.Printf("反序列化错误 err=%v\n",err)
}
//输出序列化后的结果
fmt.Printf("反序列化后 slice=%v\n",slice)
}
- 在反序列化一个json字符串,要确保反序列化后的数据类型和原来序列化前的数据类型一致。
- 如果json字符串是通过程序获取到的,则不需要再对"转义处理。
3、单元测试
Go语言中自带一个轻量级的测试框架testing和自带的go test命令来实现单元测试和性能测试。
import "testing"
func TestXxx(*testing.T):其中 Xxx 可以是任何字母数字字符串(但第一个字母不能是 [a-z])
func (c *T) Fatalf(format string, args ...interface{}):调用 Fatalf 相当于在调用 Logf 之后调用 FailNow 。
同文件夹下创建2个文件
cal.go文件
package main
func Add(n int) int{
res := 0
for i :=1; i<= n-1;i++{
res +=1
}
return res
}
cal_test.go文件
package main
import (
"testing"
)
func TestAdd(t *testing.T){
res:=Add(10)
if res != 55 {
t.Fatalf("Add(10) 执行错误,期望值=%v 实际值=%v",55,res)
}
t.Logf("Add(10) 执行正确..")
}
====
执行报错:
D:\GO_WORKSPACE\src\go_code\project03\day05>go test -v
go: go.mod file not found in current directory or any parent directory; see 'go help modules'
解决方案:cmd
go env -w GO111MODULE=auto
==================================
D:\GO_WORKSPACE\src\go_code\project03\day05>go env -w GO111MODULE=auto
D:\GO_WORKSPACE\src\go_code\project03\day05>go test -v
=== RUN TestAdd
cal_test.go:9: Add(10) 执行错误,期望值=55 实际值=9
--- FAIL: TestAdd (0.00s)
FAIL
exit status 1
FAIL _/D_/GO_WORKSPACE/src/go_code/project03/day05 0.443s
D:\GO_WORKSPACE\src\go_code\project03\day05>
==================================
解释:
GO111MODULE 是 Go 1.11 引入的新版模块管理方式。
GO111MODULE 环境变量用于开启或关闭 Go 语言中的模块支持,它有 off、on、auto 三个可选值,默认为 auto。
GO111MODULE=off
无模块支持,go 会从 $GOPATH 文件夹和 vendor 目录中寻找依赖项。
GO111MODULE=on
模块支持,go 忽略 $GOPATH 文件夹,只根据 go.mod 下载依赖。
GO111MODULE=auto
在 $GOPATH/src 外层且根目录有 go.mod 文件时,开启模块支持;否者无模块支持。
testing框架原理
将xxx_test.go的文件引入 import ...
main(){
//2.调用TestXxx()函数
}
- 测试用例文件名必须以_test.go结尾
- 测试用例函数必须以Test开头
- TestXxx(t testing.T)的形参类型必须是testing.T
- 一个测试用例文件中,可以有多个测试用例函数
- 运行测试用例指令
- cmd>go test [如果运行正确,无日志,错误时,会输出日志]
- cmd>go test -v [运行正确或错误,都输出日志]
- 当出现错误时,可以使用t.Fatalf来格式化输出错误信息,并退出程序
- t.Logf方法可以输出相应的日志
- 测试用例函数,并没有放在main函数中,也执行了,这就是测试用例的方便之处
- PASS表示测试用例运行成功,FAIL表示测试用例运行失败
- 测试单个文件,一定要带上被测试的原文件
cmd>go test -v cal_test.go cal.go
- 测试单个方法
cmd>go test -v -test.run TestAdd
Golang学习+深入(十三)-goroutine/channal
干我们这行,啥时候懈怠,就意味着长进的停止,长进的停止就意味着被淘汰,只能往前冲,直到凤凰涅槃的一天!