channel示例

通道基础 #

操作 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
...