Go语言编程
1. 顺序编程
- 有限的类型推导
- var k = "hello" or k := "hello"
- 不会对函数返回值类型进行推导
- 不定参数 `args …int` 可以认为是数组切片类型 `args []int`
- range用来遍历数组, 切片, 以及字典.
- 数组和切片
- 切片是数组的封装,为数组操作提供更多接口
- 切片更像是数组指针,保存对底层数组的引用
- len表示切片当前长度,cap表示切片最大容量
- 指针 仅限于引用,不可以运算,智能解引用((&s).X 和 s.X)
- 映射 `_, ok ` m[key]= 判断是否存在; delete 删除映射
- 取消while, 只保留for.
- for <init>; <loop>; <pred> { … }
- for <loop> { … }
- for { … }
- 多重赋值, 多值返回, 匿名函数与闭包
- 错误处理 error
- RAII解决方案 defer
- 异常传播 panic + recover
- panic(value). 触发异常并携带value
- if r := recover() ; r != nil 捕获可能的异常并处理.
- new用来分配对象内存,make只用于创建切片,映射和信道并且不返回指针
- 每个源文件内部 `init()` 函数会在初始化时候调用
2. 类型系统
- 值语义 vs. 引用语义
- 大部分cases都是值语义
- 看起来像引用语义的有
- 数组切片
- map
- channel
- interface
- 这些"引用语义"类型内部实现都是维护指针
- 方法和函数差别不大 `func (v Vertex) Abs()` 和 `func Abs(v Vertex)`
- 方法 `func (a A)` 自动会实现 `func (a *A)`
- 智能解引用
- 通常使用指针作为接受者,好处有下面两点:
- 可以修改结构里面的字段
- 如果是大型结构体可以避免拷贝
- 初始化 new(A), A{a:1, b:2}, A{1,2}
- 匿名组合
- 类型和接口都可以通过匿名组合来实现继承
- 隐式地实现接口
- 非侵入式接口
- 对象实例可以赋值给接口
- 接口之间可以赋值
- 在内部接口值可以看做包含值和具体类型的元组(value, type).
- 类型/接口查询
- 值是否实现某个接口 `v.(IReader)` 或是什么类型 `v.(type)`
- t, ok := i.(T) 如果成功,ok=True, t则为对应类型T
- i.(type) 取得底层类型
3. 并发编程
- goroutine go协程 see libtask
- 使用CPU数量 runtime.GOMAXPROCS()
- 主动yield runtime.GoSched()
- 并发通信
- 基于消息传递 channel `chan type`
- 单向写入channel `chan<- type`
- 单向读出channel `<-chan type`
- 通过make(chan type [,bufsize])来创建. 信道可以是有缓冲的
- 基于内存共享 sync.* 同步机制
- select 有效轮询各个channels状态
- select本身没有提供timeout机制
- workaround办法是启动另外一个检测超时的goroutine
4. 工程管理
- 目录组织 # src/pkg/bin
- 集成工具 # go pkg/perf/…
- 代码风格 # go fmt
- 远程import支持 # go get
- 内置单元测试和性能测试 # testing