Go 语言实战

学习

go 语言实战

1. 介绍


2. Go 包执行顺序

  • 获取数据 -> 一组等待搜索的数据源
  • 执行搜索 -> 使用接口进行匹配-发送结果-报告任务完成
  • 跟踪结果 -> 停止结果
  • 显示结果

main search feed match RSS 匹配器


3. 打包和工具链

  • 导入包查找顺序 /usr/local/go/src/pkg /home/myproject/src /home/mylibraries/s

  • 更改包导入名 myfmt "mylib/fmt" 导入的包一定要被使用,否则需要用 “_”

  • 函数 init 会在开始时被调用

  • go 命令

go run 运行 go 程序

go build 构建包打包成 exe,"…“代表所有字符串

go get 导入网络包的时候会出错,需要使用 get 来获取,如果仍失败,需要下载到本地,并且将路径名改成和包名一致,本地导入

go get -u golang.org/x/tools/cmd/godoc import "./model"

go clean 删除编译生成的可执行文件

go doc 可查看本地文档,变成网页模式查看 go doc tar godoc -http=:6060 安装 创建目录下载包 如果创建在 program 目录下没有权限执行,因此创建在 gopath 下的 src

1
2
3
4
cd $GOPATH/src/golang.org/x/tools/cmd/
go install ...
go get -u golang.org/x/tools/cmd/godoc
go install golang.org/x/tools/cmd/godoc

go env 修改配置环境

1
2
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct

go vet 检查常见错误

介绍 godep/gb/vender


4. 数组/切片/映射

如果定义全局变量需要用 var 来声明,不能用:=

  • 数组 数组赋值的时候应该注意长度一致,否则报错 如果数组长度不确定,可以使用 … 代替数组的长度 var balance = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}balance := [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}

  • 切片 参数包含容量和长度 slice := make([]string, 3, 5)

创建 nil 切片 var slice []int

声明空切片 slice := make{[int, 0]}slice := [] int {}

切片在赋值的时候只写长度,重新 append 时会开辟新空间,如果赋值时加上容量,append 会在原位置上修改值,影响原始数据

  • 映射

创建和初始化映射 dict := make(map[string]int) dict := map[string]string{"A":"a"}

使用映射字面量声明空映射 dict := map[[] string] int{} 报错 创建一个映射,使用字符串切片做为值 dict := map[int][]string{}

关于 map

  1. 变量名以小写开头不公开,其他包可以间接调用,一个函数可以返回一个未公开类型的值

  2. map 需要先用 make 构造,否则会报错,因为 map 变量默认零值 nil


5. 类型

1
2
3
4
type user struct{

}
var bill user

方法

1
2
3
func (u user) notify(){

}

传值,传指针,传地址

切片/映射/通道/接口/函数

方法传值与传指地址区别 直接传是传递副本,*表示传引用,&表示传地址 方法是将参数的副本做操作,如果要改变参数值,需要将参数地址传到函数

数组是值传递,切片是引用传递

  1. 传值

    go 语言中基本数据类型、结构体、数组都是传值

将变量的副本传递给形参 传递给函数的参数是被传数据的的副本,因此对形参(也就副本)的值进行更改操作时,并不会影响原始数据 同时,由于传值时,需要拷贝一份数据给形参,因此比较耗费资源。

  1. 传引用 将变量的地址复制一份传递给形参,它也可以看作传值,只不过传的是地址值的副本

  2. 传地址

传值传引用与传地址

知识点

  • 多态指定义了一个接口类型后,可以定义其他方法来实现改写改类型
  • 接口是声明了一组行为并支持多态的类型
  • struct 或者通过指定已存在的类型声明用户定义的类型
  • 类型本质 给类型增加删除某个值,是创建新值还是改变当前值,创建新值该类型方法就是值接收者,修改当前值就是指针接收者,同时影响内部传递类型值的方式

内置类型 go 语言中类型的默认值。如下:

数值类型(如 int8、int16、uint 等),默认值为 0 布尔类型,默认值为 false 字符串类型,默认值为”" 指针、通道、切片、字典等,默认值为 nil 复合类型的默认值,为所包含类型的默认值

引用类型 切片/映射/通道/接口/函数,创建的变量为标头值

  • 嵌入关系 值 方法接收方 T 类型包含 (t T) *T 类型包含 (t T) 和 (t *T)

方法接收方 值 (t T) T 和*T (t *T) *T

类型 S 包含匿名字段 T,则 S 和S 方法集包含 T 方法 类型 S 包含匿名字段T,则 S 和*S 方法集包含 T + T 方法 不管嵌入的是 T 还是T,*S 方法集包含 T + *T 方法

当 user 定义一个用户类型,方法实现一个通过 user 类型值的指针,admin 包含 user 类型,admin 可以调用 user 内部的方法,提升到外部类型,当 admin 也实现了该方法,则不会调用 user 方法,可以通过直接访问 user 方法

  • 未公开标识符 定义类型,小写开头为未公开标识符 文件夹应该同包名相同 当需要调用未公开标识符时,可以创建一个工厂函数 New 来返回该未公开标识符

6. 并发

7. 并发模式

8. 标准库

log 包

json 编码解码

Writer 和 Reader


9. 测试和性能

单元测试

使用 go test -v(提供冗余输出),没有加上除非失败,否则看不到测试输出 go 语言约定,_test.go 结尾的文件是测试文件,测试函数需要用 Test 开头,函数的签名必须接收一个指向 testing.T 类型的指针并且不返回任何值,

表组测试

建立多个值传入测试,查看不同

模仿调用

写一个 mockServer 模拟服务器返回

基准测试

使用 strconv 和 testing 包,文件名需要以_test.go 结尾

1
2
3
4
5
6
7
func BenchmarkSprintf(b *testing.B){
    number := 10
    b.ResetTimer()
    for i := 0; i <b.N; i++{
        fmt.Sprintf("%d", number)
    }
}

go test -v -run=“none” -bench=“BenchmarkSprintf”

-run 传递 none 保证运行基准测试前没有单元测试被运行 b.ResetTimer()初始化计时器 -benchmem 提供每次操作分配内存的次数,以及总共分配内存的字节数,allocs/op

最后更新于 05月19日 12点44分, 2026年