go get 导入 github 包
godoc -http=:6060 运行本地文档,可以浏览官网所有文档,且包含本地包的文档
go 是一个按值传递的语言,函数调用时接收的是一个参数的拷贝,传入指针可破
go 数组的大小是固定的,不能增长或收缩,不同大小的数组是“不同的类型”
与数组相对的,切片不限制大小,所以更为常用
切片声明不创建切片,需要通过 make([]string,1) 或 切片字面量 创建
切片的底层数组并不能增长大小。如果数组没有足够的空间来保存新的元素,所有的元素会被拷贝至一个新的更大的数组,并且切片会被更新为引用这个新的数组。但是由于这些场景都发生在append函数内部,无法知道返回的切片与传入append函数的切片是否具有相同的底层数组。如果你保留了两个切片,会导致一些非预期的错误。
可变长参数函数的最后一个参数接收一个切片类型的变长参数,这个切片可以被函数当作普通切片来处理
...int 是 int 的变长参数,传入一个切片
slice... 是把切片拆成变长参数
区分未赋值和零值:val,ok := vals[xx]
for...range以随机的顺序遍历映射的键和值,因为映射是一个非有序的键/值对集合
当你需要保存超过一种类型的数据时,使用 struct 类型
使用 type 关键字创建新的类型
如果你已经在当前包定义了一个名为car的类型,并且你同时也声明了一个名为car的变量,这个变量会遮盖类型名称,使后者无法被访问
(*pointer).field 可以,pointer.field 更可以
为了防止大型 struct 拷贝速度慢的问题,建议传入函数的 struct 都使用指针(返回同理)
即使一个struct类型被从包中导出,如果它的字段名称没有首字母大写的话,它的字段也不会被导出
数组、切片、映射、结构字面量,都是一个套路
struct 可以套 struct,不禁止套娃
使用匿名 struct 可以省掉命名和获取时多一层命名的问题
也可以用 type 关键字和已有类型直接新建类型,就跟一个类型的别名差不多吧
go 不支持重载,但可以通过给一个类型定义方法的方式处理此问题
定义方法:func(m myType) functionName(){},同时,m 也是一个参数(就像 JavaScript 的 this)(约定是使用接收器参数类型名称的第一个字母)
获取指针的话是这样 func(m *myType) functionName(){}
保存到变量里才有指针,否则用指针会报错
你可以通过不导出 field 和 setter、getter 函数限制字段内容
有时你并不关心一个值的特定类型。你不需要关心它是什么。你只需要知道它能做特定的事情。你能够在其上调用特定的接口。不需要关心是 pen 还是 pencil,你仅仅需要一个 Draw 方法。不需要关心是 Car 还是 Boat,你只需要一个 Steer 方法,这就是Go接口的目标
使用 type myInterface interface {...一系列方法} 创建一个具有一系列特定方法的 interface
要符合一个 interface,方法可多不可少
interface 使用指针方法时要用变量指针调用
类型断言:recorder,ok := Player.(Recorder)
Error 就是一个接口
定义 string 方法,成为 Stringer 接口后,直接传入 print 等函数就能自动调用 string 方法
任何类型都实现了空接口 interface{}
空接口没有任何方法,需要用断言转换
panic 可以让程序崩溃
panic 可以通过 recover 恢复
不要在Go中寻找等同于exception的东西。这个特性被故意省略了。对于习惯了使用exception的开发人员来说,可能需要一段时间的调整,但Go的维护者相信,这最终会使软件变得更好
每个 go 程序的 main 函数都是使用 goroutine 启动的,因此每个 go 程序至少运行一个 goroutine
默认情况 main 的 goroutine 不等待其他 goroutine,运行完就直接结束了
使用 channel 确保在接收的 goroutine 尝试使用该值之前,发送的 goroutine 已经发送了该值,跟 JavaScript 的 await 功能有点相似
channel := make(chan int) 创建 channel
channel <- val 发送 val 到 channel(塞进去)
<- channel 从 channel 拿东西出来
塞进去(缓冲满时)和拿出来都会阻塞运行
注意 goroutine 的 deadlock
使用 testing 包编写测试
函数和其签名搭配起来就是一个“特定的函数类型”
os.O_WRONLY | os.O_APPEND 看起来是“或”事实上是合并两个选项(同时有效)