通道基础
#
操作 |
A Nil Channel |
A Closed Channel |
A Not-Closed Non-Nil Channel |
Close |
panic |
panic |
succeed to close(C) |
Send |
block for ever |
panic |
block or succeed to send(B) |
Receive |
block for ever |
never block(D) |
block or succeed to receive(A) |
关闭操作
#
关闭一个nil 通信
#
func main() {
var ch chan int
close(ch) //A Nil Channel
}
#output
panic: close of nil channel
关闭一个close的通信
#
ch := make(chan int)
fmt.Printf("为ch分配一个内存地址%v\n",ch)
close(ch) //A Not-Closed Non-Nil Channel
fmt.Println("关闭通道")
time.Sleep(time.Millisecond * 5)
close(ch) //A Closed Channel
#output
为ch分配一个内存地址0xc00001c0c0
关闭通道
panic: close of closed channel
发送操作
#
var ch chan bool
ch <- true //block for ever
fmt.Println(<-ch) //block for ever
#output
fatal error: all goroutines are asleep - deadlock!
#reason
未分配内存地址
ch := make(chan bool)
ch <- true //succeed to send(B)
fmt.Println(<-ch) //block for ever
#output
fatal error: all goroutines are asleep - deadlock!
#reason
同步操作,未有缓冲区
带有缓冲区
#
ch := make(chan bool,1) //注意长度为1
ch <- true //succeed to send buffer
fmt.Println(<-ch) //receive from buffer
#output
true
ch := make(chan bool,2)
ch <- true
ch <- false
fmt.Println(<-ch,<-ch)
#output
true false
使用并发发送
#
ch := make(chan interface{})
go func() {
fmt.Println("send channel")
ch <- 12 //block or succeed to send(B)
}()
fmt.Println("block wait receive")
fmt.Println(<-ch) //block or succeed to receive(A)
#output
block wait receive
send channel
12
ch := make(chan interface{})
go func() {
fmt.Println("receive channel")
fmt.Println(<-ch) //block or succeed to receive(A)
//time.Sleep(time.Second) 要开启延迟,main先退出,直接kill掉goroutine,不会执行下面defer
defer fmt.Println("exist goroutine")
}()
fmt.Println("block wait send")
ch <- "aaaa" //block or succeed to send(B)
defer fmt.Println("exist main proc")
#output
block wait send
receive channel
aaaa
exist goroutine
exist main proc
接收命令
#
var ch chan struct{}
fmt.Println(<-ch) //block for ever
#output
fatal error: all goroutines are asleep - deadlock!
ch := make(chan struct{})
fmt.Println(<-ch) //block
#output
fatal error: all goroutines are asleep - deadlock!
ch := make(chan struct{})
go func() {
fmt.Println("start goroutine")
fmt.Println(<-ch) //block wait receive
defer fmt.Println("exist goroutine") //not run for ever
}()
time.Sleep(time.Second)
defer fmt.Println("exist main")
#output
start goroutine
exist main
ch := make(chan int)
go func() {
fmt.Println("start goroutine")
ch <- rand.Intn(100)
time.Sleep(time.Second)
close(ch)
}()
fmt.Println(<-ch) //block wait receive
for {
time.Sleep(time.Second)
fmt.Println(<-ch) //never block(D)
}
#output
start goroutine
81
0
...
综合示例
#
//消息发送者
type sender struct {
name string
}
func (s *sender)Send(message string,rc chan string) {
rc <- message
}
//消息过滤处理
type proc struct {
rc chan string
wc chan string
sender *sender
receiver *receiver
}
func (p *proc)Process() {
for {
p.wc <- fmt.Sprintf("%s to %s:%s",p.sender.name,p.receiver.name,<-p.rc)
}
}
//消息接收
type receiver struct {
name string
}
func (r *receiver)Recv(wc chan string) {
for {
fmt.Println(<-wc)
}
}
func main() {
s := &sender{name:"mike"}
r := &receiver{name:"ben"}
p := &proc{
rc: make(chan string),
wc: make(chan string),
sender: s,
receiver: r,
}
for i := 0; i < 20; i++ {
m := "message" + strconv.Itoa(i)
go p.sender.Send(m,p.rc)
}
go p.Process()
go p.receiver.Recv(p.wc)
time.Sleep(time.Second * 10)
}
#output
mike to ben:message0
mike to ben:message2
mike to ben:message4
mike to ben:message3
...