Go语言之开发常用知识点


一、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}

}