Go语言常用标准库 | 青训营笔记

88 阅读6分钟

这是我参与「第五届青训营 」笔记创作活动的第1天。由于整理笔记花费比较多的时间,今天整理完一篇。

error 错误处理

import "errors"

由于函数的返回值天然可以有多个,所以在业务处理的过程中,通常都会在返回值中添加一个错误值。

  • 当一切正常时,返回正确的返回值和nil(null),表示没有错误信息
  • 若发生错误时,则错误信息的返回值不为空,其业务返回值为空 error 库可以用来创建一个错误信息 error.New("...")
func findUser(users []user, name string) (v *user, err error) {
	for _, u := range users {
		if u.name == name {
		    // error为空,未发生错误
			return &u, nil
		}
	}
	// 返回nil值,与错误信息
	return nil, errors.New("not found")
}

在调用某一个业务函数后,需要对其返回值进行判断,如果第二个参数 err 为空,则直接处理业务返回值;如果不为空,则需要打印错误日志。

u, err := findUser([]user{{"wang", "1024"}}, "wang")
if err != nil {
	fmt.Println(err)
	return
}
fmt.Println(u.name) // wang

string库

import "string"

  • string初始化:a := "hello" ,使用 len(a) 查看字符串的长度(对于中文字符来说,一个中文字符所对应的字符长度>1)
b := "你好"
fmt.Println(len(b)) // 6

// 当字符串中需要有 "" 则需要使用 `` 来包装
s = `{"key": "value"}`
  • 判断是否包含另外一个字符串:
strings.Contains(a, "ll")  // true
  • 对字符串内字符串计数
strings.Count(a, "ll")   // 2
  • 是否有前缀
strings.HasPrefix(a, "he")   //true
  • 是否有后缀
strings.HasSuffix(a, "llo")  // true
  • 寻找指定字符串的开始位置,若不存在,则返回-1
strings.Index(a, "x")
  • 字符串拼接,第二个参数表示字符串之间的分隔符
strings.Join([]string{"he", "llo"}, "-")
  • 重复字符串
strings.Repeat(a, 2)
  • 替换字符串中的子字符串,第四个参数为替换的个数限制,如果该参数小于0,则对替换的个数没有限制
strings.Replace(a, "l", "L", 1)  // heLlo
  • 根据对应分隔符将字符串转换为字符串数组
strings.Split("a-b-c", "-")   // [a b c]
  • 转大/小写
strings.ToLower(a) // 小写 hello
strings.ToUpper(a) // 小写 HELLO

fmt 输入输出库

import "fmt"

输出

  • %v 对任何变量值进行输出
  • %+v 针对结构体,其输出结构体内字段的名称
  • %#v 针对结构体,其输出结构体的名称及其内部字段的名称
type point struct {
    x, y int
}

p := point{1, 2}
fmt.Printf("p=%v\n", p)  // p={1 2}
fmt.Printf("p=%+v\n", p) // p={x:1 y:2}
fmt.Printf("p=%#v\n", p) // p=main.point{x:1, y:2}

输出浮点数时,使用 %.nf 来格式化为保留n为小数的浮点数

输入

go中的 Scanf 函数与C中的scanf用法是相似的,第一个参数为需要传入的格式,第二个参数为需要输入的变量的地址。 由于最后键入的是回车,所以在第一个参数中添加 \n 符,以读入回车符。

fmt.Scanf("%s\n", &s)

json库

import "encoding/json"

json 常用于记录结构体数据,在结构体字段中,必须保证字段的开头为大写,才能被序列化。如果需要在输出时使用别于字段本身的名字,则需要添加 tag 。

type userInfo struct {
	Name  string
	Age   int `json:"age"` //添加json的tag别名,则输出的时候会使用该别名
	Hobby []string
}
  • 结构体的序列化:将结构体转化为字节数组(其中都是字符所对应的ASCII码或Unicode),该字节数组需要转化为 string 才能正常输出。在输出时,添加了 tag 的字段将输出别名(age)
a := userInfo{Name: "wang", Age: 18, Hobby: []string{"Golang", "TypeScript"}}
// 序列化,第二个参数是错误信息
buf, err := json.Marshal(a)
if err != nil {
	panic(err)
}
fmt.Println(buf)         // [123 34 78 97...] 字节数组
// {"Name":"wang","age":18,"Hobby":["Golang","TypeScript"]}
fmt.Println(string(buf)) 

buf, err = json.MarshalIndent(a, "", "\t")
if err != nil {
	panic(err)
}
fmt.Println(string(buf))
  • 序列化字符串的格式化:使用 MarshalIndent 函数将字符串进行format操作。其内部会根据变量的层次关系将结构体换行,并添加缩进,函数的参数列表如下,其中 indent 表示每次缩进使用的字符串,prefix 每一行前加上的字符 MarshalIndent(v any, prefix string, indent string)
buf, err = json.MarshalIndent(a, "x", "\t")
if err != nil {
	panic(err)
}
fmt.Println(string(buf))
//  {
//  "Name": "wang",
//      "age": 18,
//      "Hobby": [
//  		"Golang",
//  	    "TypeScript"
//      ]
//  }
  • 结构体的反序列化:使用字节数组将其值赋值到结构体中。需要注意的是,由于需要对结构体进行修改,所以需要传入结构体的地址(加上地址符)
var b userInfo
// 反序列化到一个空的变量中
err = json.Unmarshal(buf, &b)
if err != nil {
	panic(err)
}
// main.userInfo{Name:"wang", Age:18, Hobby:[]string{"Golang", "TypeScript"}}
fmt.Printf("%#v\n", b) 

time 时间库

import "time"

  • 获取当前时间,可以通过 Unix() 获取时间戳
now := time.Now()
now.Unix()   // 获取时间戳
  • 构建一个带市区的时间
// Date(year int, month time.Month, day int, hour int, min int, sec int, nsec int, loc *time.Location)
t := time.Date(2022, 3, 27, 1, 25, 36, 0, time.UTC)
  • 根据时间的一些方法获取其属性
// 2022 March 27 1 25
fmt.Println(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute()) 
  • 时间的格式化:使用传入 Format 函数中的参数的时间的格式对给定的时间格式化,即传入的时间为一种样例
// 2022/03/27 01:25:36
fmt.Println(time.Now().Format("2006/01/02 15:04"))
  • 时间差
t2 := time.Date(2022, 3, 27, 2, 30, 36, 0, time.UTC)
diff := t2.Sub(t)
fmt.Println(diff)                           // 1h5m0s
fmt.Println(diff.Minutes(), diff.Seconds()) // 65 3900
  • 由字符串转为 time 类型变量:第一个参数为解析的字符串所依据的时间格式,第二个参数为需要解析的时间字符串
t3, err := time.Parse("2006-01-02 15:04:05", "2022-03-27 01:25:36")

strconv 字符串转换

import "strconv"

  • 解析 float 浮点数
f, err := strconv.ParseFloat("1.234", 64)
  • 解析 int 整数:第二个参数表示解析使用的进制数,第三个参数表示存储的位数(精度)。如果说进制的参数为0,则系统自动检测。
n, err := strconv.ParseInt("111", 10, 64)
n, _ = strconv.ParseInt("0x1000", 0, 64)
  • 字符串和int互相转换
n2, err := strconv.Atoi("123") // 字符串转int
// 如果传入的是非数字的字符串,则会产生错误。
n3 := strconv.Itoa(123)      // int转字符串

获取进程信息

import ( "os" "os/exec" )

  • 获取命令行中的参数,第一个参数为执行的程序的名称,用户在命令行中输入的其他参数从第二个开始(得到的是一个字符串数字)
os.Args
  • 环境变量的读取和修改
os.Getenv("PATH")
os.Setenv("AA", "BB")
  • 执行命令行命令,CombinedOutput 用于执行命令且返回对应的错误信息
buf, err := exec.Command("CommandName","param1","param2",...).CombinedOutput()