一、flag包之命令行解析
1、os.Args
os.Args是一个string切片,用来存储所有的命令行参数。
var Args []string
案例演示:
package main import ( "fmt" "os" ) func main() { // 获取命令行参数 fmt.Printf("命令行参数个数为:%v \n", len(os.Args)) // 打印每一个参数 for i, v := range os.Args { fmt.Printf("第%v个参数是:%v \n", i, v) } }
对上述文件进行编译:
go build .\main.go
执行编译程序,带上参数:
.\main.exe 123 a
输出:
命令行参数个数为:3 第0个参数是:D:\go_project\src\go_tutorial\day17\flagDemo01\main.exe 第1个参数是:123 第2个参数是:a
可以看到我输入的是2个参数,但是默认的总会有第一个参数,就是程序名称。
2、命令行解析
上述方式是比较原生的方式,它存在的比较明显的缺点就是参数位置需要按照指定的进行接收,否则就会出现问题,flag包可以很容易的解决这个问题。
package main import ( "flag" "fmt" ) func main() { // 定义用于接收命令行指定变量 var user string var pwd string var host string var port int // &user用来接收命令行输入的参数值, 即-u 后的值 // "u" 就是 -u 参数 // "" 默认值 // "用户名默认为空" 用于说明 flag.StringVar(&user, "u", "", "用户名默认为空") flag.StringVar(&pwd, "p", "", "密码默认为空") flag.StringVar(&host, "h", "localhost", "主机名默认为localhost") flag.IntVar(&port, "P", 3306, "端口号默认为3306") // 接收值后需要进行解析 flag.Parse() // 输出 fmt.Printf("user=%v, pwd=%v, host=%v, port=%v", user, pwd, host, port) }
对上述文件进行编译:
go build .\main.go
执行编译程序,带上参数:
.\main.exe -u root -p 123456
输出:
user=root, pwd=123456, host=localhost, port=3306
如果执行的命令有误就会出现说明:
Usage of D:\go_project\src\go_tutorial\day17\flagDemo02\main.exe: -P int 端口号默认为3306 (default 3306) -h string 主机名默认为localhost (default "localhost") -p string 密码默认为空 -u string 用户名默认为空
二、序列化与反序列化
(一)基本操作
JSON是一种轻量级的语言交换格式,可以使不同编程语言具有同一种标准的数据交换 格式。而序列化就是将数据对象(数组、结构体、map等)转成json字符串以便接收者接收,而反序列化就是将json字符串转成数据对象(数组、结构体、map等)的过程。
下面三种对象用的比较广泛,其余基本数据类型类似。
- 结构体
- 切片
- map
序列化需要借助于encoding/json包:
func Marshal(v interface{}) ([]byte, error) //Marshal函数返回v的json编码
反序列化需要借助于encoding/json包:
func Unmarshal(data []byte, v interface{}) error // Unmarshal函数解析json编码的数据并将结果存入v指向的值
1、结构体
package main import ( "encoding/json" "fmt" ) // 定义一个结构体 type User struct { Name string Age int } func main() { // 创建结构体变量 user := User{ Name: "lily", Age: 20, } // 1、对结构体变量进行序列化 data, err := json.Marshal(user) if err != nil { fmt.Printf("序列化错误 %v", err) return } // data是字节切片需要转成字符串 str := string(data) fmt.Println(str) // 2、反序列化 // 声明一个User结构体变量 var user1 User err = json.Unmarshal([]byte(str), &user1) if err != nil { fmt.Printf("反序列化错误 %v", err) } fmt.Println(user1) }
2、切片
package main import ( "encoding/json" "fmt" ) // 定义一个结构体 type User struct { Name string Age int } func main() { // 创建结构体变量 user := User{ Name: "lily", Age: 20, } // 定义一个切片 var userSlice []User // 将结构体变量加入到切片中 userSlice = append(userSlice, user) // 1、对切片进行序列化 data, err := json.Marshal(userSlice) if err != nil { fmt.Printf("序列化错误 %v", err) return } // data是字节切片需要转成字符串 str := string(data) fmt.Println(str) // 2、反序列化 // 声明一个待反序列化的切片 var userSlice1 []User err = json.Unmarshal([]byte(str), &userSlice1) if err != nil { fmt.Printf("反序列化错误 %v", err) } fmt.Println(userSlice1) }
3、map
package main import ( "encoding/json" "fmt" ) func main() { // 定义一个map类型 var userMap map[string]interface{} //map使用前需要进行make userMap = make(map[string]interface{}, 5) userMap["UserName"] = "Alice" userMap["Age"] = 18 // 1、对切片进行序列化 data, err := json.Marshal(userMap) if err != nil { fmt.Printf("序列化错误 %v", err) return } // data是字节切片需要转成字符串 str := string(data) fmt.Println(str) // 2、反序列化 // 声明一个待反序列化的map,反序列化map不需要make,因为已经被封装到内部了 var userMap1 map[string]interface{} err = json.Unmarshal([]byte(str), &userMap1) if err != nil { fmt.Printf("反序列化错误 %v", err) } fmt.Println(userMap1) }
(二)tag标签
tag标签相当于给字段别名,它可以解决以下问题:
- 私有变量跨包
- 返回给前端数据字段名自定义
package main import ( "encoding/json" "fmt" ) // 定义一个结构体 type User struct { Name string `json:"name"` // tag别名 name Age int `json:"age"` // tag别名 age } func main() { // 创建结构体变量 user := User{ Name: "lily", Age: 20, } // 对结构体变量进行序列化,可以看到输出的字段名是tag别名 data, err := json.Marshal(user) if err != nil { fmt.Printf("序列化错误 %v", err) return } // data是字节切片需要转成字符串 str := string(data) fmt.Println(str) // {"name":"lily","age":20} }