1. context
context是上下文的意思,作为golang的标准包定义了context接口,具有生命周期,具有cancel channel信号的能力,可以用来管理goroutine的生命周期。
Context接口有4个实现函数:
Deadline():获取该context的过期时间和是否被设置过期时间
Done():返回一个channel,关闭该channel就代表关闭该context,返回nil代表该context不需要被关闭
Err():context未关闭返回nil;context正常关闭返回canceled;因为过期关闭返回DeadlineExceeded;发生错误返回对应的error
Value():根据指定key从context中取出value,如果没有关联的值返回nil
空context:
context.Background():用作初始的context
context.TODO():用作未实现功能的场景中,不清楚作用的context
4个非空context:
WithValue():基于现有context派生新的context,同时新context中带有指定的key和value
3个可关闭的context:
WithCancel():根据父context派生新的context,返回一个CancelFunc类型的函数。调用该cancel函数会关闭该context,对应的Done()返回的只读channel也会被关闭。
WithDeadline():根据父context和deadline派生一个新的context,返回值中也有一个CancelFunc函数。当到达过期时间,或者调用CancelFunc函数关闭,或者关闭父context会使生成的context关闭。
WithTimeout():入参中传入父context和一个时间间隔,其余和WithDeadline()类似。
2. select
select的每个case都是一个面向channel的IO操作
可以用来:
1、监听IO操作
2、实现timeout机制:
// 使用channel和select实现超时机制
func timeout(ch chan interface{}) {
timeout := make(chan bool, 1)
go func() {
time.Sleep(1e9)
timeout <- true
}()
select {
case x := <-ch:
fmt.Println(x)
case <-timeout:
fmt.Println("It's timeout.")
return
}
}
3、配合default检测channel的缓冲区是否已满:
// 使用select的default检测channel buffer是否已满
func isBufferFull() {
ch := make(chan int, 1)
ch <- 1
select {
case ch <- 2:
fmt.Println("ch")
default:
fmt.Println("ch is full.")
}
}
func IsBufferFull(ch chan interface{}, x interface{}) {
select {
case ch <- x:
fmt.Printf("%v\n", ch)
default:
fmt.Println("It's full.")
}
}
3. channel
优点:带缓冲区的channel可以用来做消息队列,为goroutine之间提供通信;并发安全;可以传递任意类型数据;支持阻塞等待。
缺点:性能不高,用锁实现;容量需要一开始就定好;只能支持本主机上本程序的使用;扩展性差;不能持久化,当进程挂掉时,缓存的消息会丢失。
4. goroutine,协程:
协程是在线程之下,线程中多个协程通过调度获取cpu时间片
优点:
轻量,创建时所需内存相比进程线程很小
由程序员控制上下文的切换,编程简单,结构清晰,易于理解
并且切换的内容只保存自己的用户态栈和堆内存中,切换的时间快,和同等数量的线程切换相比可以省去很多代价
5. defer
在函数返回return执行前,调用defer的操作,可以用来释放资源,做清理工作。
(1)defer表达式确定时,defer修饰的函数的参数也就确定了
func f(){
i := 0
defer func(h int){
fmt.Println(h)
}(i)
i++
}
输出结果是0不是1
(2)函数中有多个defer函数或语句时,defer遵循先进后出原则
(3)函数的返回值被defer修改。保存返回值-》执行defer-》执行return跳转
func fun1() int { //0
i:=0
fmt.Println("(1)",i)
defer func(){
i=5
fmt.Println("(2)",i)
}()
return i
}
func fun2() (i int){ //5
i=0
fmt.Println("(1)",i)
defer func(){
i=5
fmt.Println("(2)",i)
}()
return i
}
6. panic()和recover()
go的内置函数。
panic是停止程序执行的流程,但是defer还是会执行。
recover是可以捕获前面出现的panic,然后让函数又可以继续正常的执行。可以放到任何位置,但是只有在defer()中的才会起作用。
可以配合panic和recover,来设定返回值。