类型
定义
简短模式
简短模式并不总是重新定义变量,也饿能是部分退化的赋值操作
退化赋值的前提条件是: 最少有一个新变量被定义,且必须是同一作用域
常量
值类型
引用类型
slice
map
channel
function
interface
别名
byte int8
rune int32
别名可以直接赋值
自定义类型
无法继承基础类型的方法,与基础类型是完全无关的两个类型
类型转换
(转换类型)()
表达式
注意for i:=range x 与fork,v:=range x的区别 前者i是索引而不是值
函数
参数
值拷贝
如果参数过多,建议将其重构为一个复合结构体类型 比如serverOption,既方便扩展,也方便通过newOption函数设置默认值
变参
本质是一个切片,且比如放在列表尾部
返回值
匿名函数
闭包
闭包直接饮用了原环境变量
延迟调用
defer
错误处理
panic
recover
数据
字符串
字符串的切片还是字符串例如 s:=”abcdefg” seg:=s[1:3] fmt.Println(reflect.TypeOf(seg)) //结果是string
字符串遍历
byte
rune
字符串修改
要修改字符串,需将其转成可变类型([]rune或[]byte),不管如何转变,都需重新分配内存并复制数据
并发
channel
按关闭状态来区分
未关闭信道
已关闭信道
按缓冲区长度来区分
无缓冲信道
有缓冲信道
按照是否是nil来区分
非nil信道
nil信道
按同步/异步模式来区分
无缓冲队列(同步)
缓冲队列(异步)
如何解除channel阻塞
1.写入数据
2.关闭信道 close
channel用途
1.数据传输
2.事件通知
通知可以是群体性的(阻塞信道,然后通过关闭信道解除阻塞)
一次性事件用close效率更好,连续或多样性时间,可传递不同数据标识实现,还可使用sync.Cond实现单播或广播事件
如何实现等待多个任务结束
1.sync.WaitGroup
2.
对于closed以及nil信道,发送和接收都有相应规则
1.向已关闭信道发送数据,引发panic
2.从已关闭信道接收数据,返回以缓冲数据或零值
3.无论收发,nil信道都会阻塞
[信道4准则](https://dave.cheney.net/2014/03/19/channel-axioms)
Goshed
Goexit: 立即终止整个调用栈,它会等待其他任务执行结束
channel操作
channel本身是个指针,可以用相等操作符判断是否为同一个对象或nil
cap和len返回缓冲区大小和当前以缓冲数量,而对于同步channel则都返回0,据此可判断通道是同步还是异步
channel数据处理
1.简单发送接收操作<-ch/ch<-
2.ok-idom
举例,对于v,ok:=<-ch其中ok为true表示从信道中获取到了数据,ok为false表示信道已经关闭且这时v为0
3.range
ps: 如果遇到nil的channel,结束range
单向信道
信道默认是双向的,不区分发送和接收端,我们可以用单向信道限制收发操作的方向来获得更严谨的操作逻辑,通常使用类型转换类获取单向通道,并分别赋予双方
123
c:=make(chan int)var send chan<-int = c //单向发送信道var recv <-chan int = c //单向接收信道
> 无法将单向信道转换为双向信道
选择
如果同时处理多个信道,可选用select,它会随机选择一个可用信道做收发操作
如果不想再选择某个信道,可以将该信道设置为nil,这样它就会被阻塞,不再被select选中
当所有信道不可用时,select会执行default语句,如此可避开select阻塞,但需要注意处理外层循环,以免陷入空耗
同步
信道不是用来取代锁的,他们有不同的使用场景。信道倾向于解决逻辑层次的并发处理,而锁则用来保护局部范围内的数据安全
互斥锁和读写锁
读写并发时,读写锁性能会好一些
将Mutex作为匿名字段时,相关方法必须实现为pointer-receiver,否则会因复制导致锁机制失效
也可以嵌入*Mutex,但是需要专门初始化
Mutex不支持递归锁,即使同一个goroutine下也会导致死锁
如何构建协程池