go(三)
数据类型
类型转化
并发
context
channel
channel主要使用在不同的goroutine之间进行通信
channel的类型
<-表示数据的方向
双向
-
只读channel(如果ch表示一个channel,那么只能使用value:=<-ch)声明的方式
valuename <- chan type,箭头是从chan到value,所以是一个只读的chan
-
只写channel(如果ch表示一个channel,那么只能使用ch<-message) 声明的方式
valuename chan <- type,箭头是从一个数据到chan,所以是一个只写的chan
关闭close channel
被close的channel只能用来读,不能用来写,否则会有panic
已经被close的channel可以用来读数据,并且读取数据不会被阻塞;当没有数据的时候会返回value的zero值。或者使用一个额外的参数来表示是否关闭。
value,ok:=<-ch
if !ok {
// channel is closed
}
如果使用range来访问channel,当channel中没有数据并且没有关闭的时候,会被blocking,程序在运行的时候可以直接panic。所有在range访问中,一定要有地方把对应的channel进行close才可以。
select channel
select的使用与switch非常类似,但是其只用于channel的通信中。select会去选择一组可能的send和receive去处理。如果多个case都可以的话,其会伪随机选择其中一个,如果都不符合就会选择default,如果没有default就会block。
selec{
case statement1:
operation1
case statement2:
operation2
default:
default operation
channel中的timer和tickers
timer可以实现定时任务,ticker实现定周期的任务
timer和ticker里面实现都是基于一个buffer size为1的 <-chan time类型。使用timer或者ticker的时候,如果到时间
在timer的时间到期(time expired)出发的事件有两种,一种是默认的sendtime
一种是使用func设置的func
。
其中sendtime
的实现,是在C如果满的情况下不会block,如果不满就将时间写入channel中(实现的方式是用select)
nil channel和zero channel
channel有nil和zero之分,其中nil是直接使用var 声明的。
nil channel不能用于send和receive操作,否者会有panic出现
channel使用错误(block channel和buffer channel)
声明channel的时候,如果没有使用buffer channel声明,是直接声明的是block channel。
block channel一定是两个goroutine都准备好的时候才能够send和receive
下边这种情况直接就被block,然后panic信息
messages := make(chan string)
messages <- "message"
msg := <-messages
fmt.Println(msg)
但是这种就不会出现问题
messages := make(chan string,1)
messages <- "message"
msg := <-messages
fmt.Println(msg)
错误处理(panic)
defer使用
A "defer" statement invokes a function whose execution is deferred to the moment the surrounding function returns, either because the surrounding function executed a return statement, reached the end of its function body, or because the corresponding goroutine is panicking.
再说接口(interface)
interface除了可以定义一组行为操作以外,在go中有更加重要的用途
判断interface的具体类型
当一个interface被多个struct实现的时候,我们需要判断这个interface具体是哪一个类型的,就可以使用go的断言操作
if en,ok:=i.(T);ok{
// 表示i是T类型的,其中i是interface的变量,en表示interface变量存储的值
}
t, ok := i.(T)
If i holds a T, then t will be the underlying value and ok will be true.
If not, ok will be false and t will be the zero value of type T, and no panic occurs.
使用switch进行断言操作
其中i.(type)表示取i的类型
switch t := i.(type) {
case *S:
fmt.Println("i store *S", t)
case *R:
fmt.Println("i store *R", t)
}
空interface
接口表示实现了一种公共的操作,但是空的interface是没有公共操作的,所以所有的类型都可以使用空的interface表示。
所以如果一个函数或者方法的参数或者返回值是interface类型的,那么这个函数的返回值或者参数可以是任意类型的。