go channel 用例

本文介绍了Go语言中的goroutine概念,以及如何通过sync包进行共享内存同步,重点讲解了channel的使用,包括未缓冲、缓冲和范围遍历,以及select和defaultcase在处理并发通信中的作用。
摘要由CSDN通过智能技术生成

goroutine

http://127.0.0.1:3999/concurrency/1

doc

https://golang.org/pkg/sync/

go demo

Goroutines run in the same address space, so access to shared memory must be synchronized. The sync package provides useful primitives, although you won’t need them much in Go as there are other primitives. (See the next slide.)

package main

import (
	"fmt"
	"time"
)

func say(s string) {
	for i := 0; i < 5; i++ {
		time.Sleep(100 * time.Millisecond)
		fmt.Println(s)
	}
}

func main() {
	go say("world")
	say("hello")
}


channel

Channels are a typed conduit through which you can send and receive values with the channel operator, <-.

this channel will be block until double side ready.

普通管道 没有缓冲区, 会被 job 两端 阻塞.
直到 双方数据准备好.

使用中 需要 避免死锁.
fatal error: all goroutines are asleep - deadlock!

package main

import "fmt"

func sum(s []int, c chan int) {
	sum := 0
	for _, v := range s {
		sum += v
	}
	c <- sum // send sum to c
}

func main() {
	s := []int{7, 2, 8, -9, 4, 0}

	c := make(chan int)
	go sum(s[:len(s)/2], c)
	go sum(s[len(s)/2:], c)
	x, y := <-c, <-c // receive from c

	fmt.Println(x, y, x+y)
}


Buffered Channels

缓冲管道.

Sends to a buffered channel block only when the buffer is full. Receives block when the buffer is empty.

package main

import "fmt"

func main() {
	ch := make(chan int, 2)
	ch <- 1
	ch <- 2
	fmt.Println(<-ch)
	fmt.Println(<-ch)
}

range and close channel

range 会尝试 持续的 获取 管道 输出, 无输出 时 也会 阻塞, 直到 管道 关闭 才会结束


package main

import (
	"fmt"
)

func fibonacci(n int, c chan int) {
	x, y := 0, 1
	for i := 0; i < n; i++ {
		c <- x
		x, y = y, x+y
	}
	close(c)
}

func main() {
	c := make(chan int, 10)
	go fibonacci(cap(c), c)
	for i := range c {
		fmt.Println(i)
	}
}

judge channel state

Another note: Channels aren’t like files; you don’t usually need to close them. Closing is only necessary when the receiver must be told there are no more values coming, such as to terminate a range loop.
管道 并不像 文件一样. 没有必要 关闭.
除非 接收端 使用了 range , 或者 处于 某种 设计 .

Note: Only the sender should close a channel, never the receiver. Sending on a closed channel will cause a panic.
注意 只有 发送端 应该 关闭 管道, 因为 接受者 关闭 管道 后, 会导致 发送端 引发 异常, ok 探测 也能在 接收端 进行.


v, ok := <-ch
if !ok {
  panic("channel have be closed")
}

select on channel

The select statement lets a goroutine wait on multiple communication operations.
select 让go 协程, 在 多个 通信 操作 之间 等待.

A select blocks until one of its cases can run, then it executes that case. It chooses one at random if multiple are ready.
select 会阻塞, 直到 其中一个 通信 操作 可以 进行.
如果 有 多个 通信 操作 可以执行, 他会 随机选择 一个 去执行.

package main

import "fmt"

func fibonacci(c, quit chan int) {
	x, y := 0, 1
	for {
		select {
		case c <- x:
			x, y = y, x+y
		case <-quit:
			fmt.Println("quit")
			return
		}
	}
}

func main() {
	c := make(chan int)
	quit := make(chan int)
	go func() {
		for i := 0; i < 10; i++ {
			fmt.Println(<-c)
		}
		quit <- 0
	}()
	fibonacci(c, quit)
}

default in select channel

The default case in a select is run if no other case is ready.
当 左右 case 都无法 触发 的 时候, default 会被 执行.

Use a default case to try a send or receive without blocking:
当你 不想 被 通信 锁死的 时候, 请选择 default


package main

import (
	"fmt"
	"time"
)

func main() {
	tick := time.Tick(100 * time.Millisecond)
	boom := time.After(500 * time.Millisecond)
	for {
		select {
		case <-tick:
			fmt.Println("tick.")
		case <-boom:
			fmt.Println("BOOM!")
			return
		default:
			fmt.Println("    .")
			time.Sleep(50 * time.Millisecond)
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yuemake999

请我喝茶呗

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值