go基础知识
01 go包管理
每个go文件,默认都以当前所在文件夹的名字为包名。go.mod里的module指定了该项目的包名前缀。
假设go.mod里指定module com.yimi.go-learn,文件夹为a/b/c,那么c目录为一个package,被其他目录引用时的地址为import com.yimi.go-learn.a.b.c
在程序入口main函数的文件夹里,这种命名方式有所不同,package跟目录没关系,必须是main,并且同一个目录下,只能有一个main函数。
02 方法&函数
go没有类,可以为结构体定义【方法】
【方法】: 就是一类带特殊的 接收者 参数的普通函数
普通函数定义为 func funcName([param paramType]*) [resName]? resType? { ... }
结构体方法定义 func (recName recType) funcName([param paramType]*) [resName]? resType? { ... }
主要是在func和方法名之间,多了 (recName recType),如func (v Vertex) Abs() float64 {...}
接收者可以是结构体,也可以是其他非结构体类型,接收者的类型定义和方法声明,必须在同一个包内,不能为内建类型声明方法
指针与函数,指针与方法(传值还是传引用)
不论是作为函数参数,还是做为方法的接受者,
- 如果是用的类型本身,那就只是传值,在函数或者方法体里,可以读取,可以修改副本值,但无法修改本体值
- 而如果用的指针,那相当于传引用,在函数或者方法体里,可以读取,可以通过引用来修改本体值
指针和值
-
带指针参数的函数,必须接受一个指针,如果传了值,会编译错误
-
而以指针为接受者的方法,被调用时,可以传指针,也可以传值,这里如果传值,默认解释为指针&v(语法糖)
-
接受一个值为参数的函数,必须接受一个值,如果传了指针,会编译错误
-
而以值为接受者的方法,被调用时,可以传指针,也可以传值,如果这里传指针,默认解释为值*p(语法糖)
总的来说,对方法来说,无论接受者是值,还是指针,都会自动默认转换(需要指针,传了值,默认转为指针,需要值,传了指针,默认转为值)
方法申明里是指针,方法体里才能修改对象,无论调用时用的是指针还是值(语法默认转换)
对函数来说,函数申明的是什么,就必须传什么,否则会编译出错。
通常来说,所有给定类型的方法都应该有值或指针接收者,但并不应该二者混用
03 初始化二维数组
dy, dx int
result := make([][]uint8, dy)
for i := range result {
result[i] = make([]uint8, dx)
for j := range result[i] {
result[i][j] = uint8((i + j) / 2)
}
}
04 go内存管理
05 go部分命令
go env可以查看go的环境变量
go mod init 初始化go.mod
go mod tidy 更新依赖(增加&删除)
go mod download 下载依赖
go mod vendor 依赖放到项目根目录下的vendor目录中
go mod edit 手动修改依赖
go mod graph 打印依赖图
go mod verify 校验依赖
go get | go install
go get 从远程库下载或更新go代码包。代码包存储在$GOPATH/src中,并编译代码包,把可执行文件复制到$GOPATH/bin下或把库文件放到$GOPATH/pkg下
go install 编译安装go代码包,生成的可执行文件或库放到bin或pkg下。如果在项目目录里执行,会编译当前项目。
因此,go get用于下载和更新代码包并产生对应的程序或库,而go install用于将go代码转换为程序或库,并安装到系统路径(bin/pkg)以供使用。
go get 在go内部实际上分两步,第一步是下载源码包,第二步是执行go install
为什么要单独使用go install
使用go get时,有些情况下生成的程序可能无法生效,通常是因为版本不兼容或者编译环境问题导致。而使用go install可以避免这些问题