一、Golang:变量定义(代码)
1. 变量定义要点:
- 变量类型写在变量名之后
- 编译器可推测变量类型
- 没有char,只有rune
- 原生支持复数类型
2. 内建变量类型:
- bool, string
- (u)int, (u)int8, (u)int16, (u)int32, (u)int64, uintptr(指针)
- byte, rune(就是char类型,为了应付多语言的一字节来设计,32位,与int32可混用)
- float32, float64, complex64, complex128(表示实数,128表示实部和虚部分别是64位)
条件、循环要点:
- for, if后面的条件没有括号
- if条件里也可以定义变量
- 没有while
- switch不需要break,也可以直接switch多个条件
三、Golang:函数和指针(代码)
1. 函数要点:
- 返回值类型写在最后面
- 可返回多个值
- 函数作为参数
- 没有默认参数、可选参数等,只有可变参数列表
2. 值传递和引用传递:
- cpp中可以值传递也可以引用传递(&)
- python和java除了系统内建类型是值传递以外,都是引用传递
- go只有值传递,要改变值必须用指针参数
四、Golang:内建容器(代码)
1. 数组:
- 数组是值类型
- [10]int和[20]int是不同的类型
- 调用func f(arr [10]int)会拷贝数组。想改变原数组的值,用指针类型参数
- go中一般不直接使用数组
2. 切片:
3. Map:
- map的操作:
- 创建:make(map[string]int)
- 获取元素:m[key]
- key不存在时,获得Value类型的初始值
- 用value, ok:=m[key]来判断是否存在key
- 用delete删除一个key
- 使用len获得元素个数
- map的遍历:
- 用range遍历key,或者遍历key-value对
- 不保证遍历顺利,如需顺序,需手动对key排序
- map的key:
- map使用哈希表,必须可以比较相等
- 除了slice,map,function的内建类型都可以作为key
- Struct类型中只要不包含上述三个字段,也可作为key
4. rune(go中的char):
- 使用range遍历pos-rune对
- 使用utf8.RuneCountInString获得字符数量
- 使用len获得字节长度
- 使用[]byte获得字节
1. Go不能算是一种面向对象的语言:
- go只支持封装,不支持继承和多态
- go只有struct,没有class
2. 结构(struct)创建在堆上还是栈上?
- cpp中,局部变量分配在栈上,在外界也要使用的变量要分配到堆上,并且要手动释放
- java中,对象都分配在堆上,有对应的垃圾回收机制
- go中不需要知道分配在堆上还是栈上。比如返回了局部变量的地址,那么是分配在堆上,并有对应的垃圾回收,这些都是编译器自己识别并实现的
3. 值接收者 vs 指针接收者:
- 要改变内容必须使用指针接收者
- 结构过大也考虑使用指针接收者
- 一致性:如果有指针接收者,最好都是指针接收者
- 值接收者是go语言特有,值/指针接收者均可接受值/指针
4. 封装:
- 名字一般使用CamelCase形式
- 首字母大写:public
- 首字母小写:private
- 首字母大小写是针对包(package)来说的
5. 包:
- 每个目录一个包
- main包包含可执行入口,如果这个包里有main函数,那么这个目录下只能有一个main包
- 为结构定义的方法必须放在同一个包内,可以是不同文件
6. 扩展系统类型或者别人的类型:
六、Golang:面向接口(代码)
1. go语言的duck typing:
- 具有python,cpp的duck typing的灵活性
- 又具有java的类型检查
2. 接口变量里有什么?
- 实现者的类型
- 实现者的值(或指针指向实现者)
3. 注意:
- 接口变量里自带指针,接口变量本身采用值传递,几乎不需要使用接口的指针
- 指针接收者实现只能以指针方式使用;值接收者都可以
七、Golang:函数式编程(代码)
1. 函数式编程 vs 函数指针:
- 函数是一等公民:参数,变量,返回值都可以是函数
- 高阶函数
- 函数->闭包
2. “正统”函数式编程:
- 不可变性:不能有状态,只有常量和函数
- 函数只能有一个参数
- go没有以上规定
3. go闭包的应用:
- 更为自然,不需要修饰如何访问自由变量
- 没有lambda表达式,但是有匿名函数
八、Golang:goroutine(代码)
1. 与协程Coroutine相似:
- 轻量级“线程”
- 非抢占式多任务处理,由协程主动交出控制权
- 编译器/解释器/虚拟机层面的多任务
- 多个协程可能在一个或多个线程上运行
2. goroutine的定义:
- 任何函数只需加上go就能送给调度器运行
- 不需要在定义时区分是否是异步函数
- 调度器在合适的点进行切换
- 使用-race来检测数据访问冲突
3. goroutine可能的切换点(参考):
- I/O, select, channel
- runtime.Gosched()
- 等待锁,函数调用(有时)
九、Golang:channel(代码)
1. Groutine和channels实现了CSP(Communicating Sequential Processes)模型
2. channles在goroutine的通信和同步中承担着重要的角色
3. channel实现四个特性:
- goroutine安全
- 在不同的goroutine之间存储和传输值
- 提供FIFO语义(buffered channel提供)
- 可以让goroutine block/unblock