1、生成器
在应用系统编程中,常见的应用场景就是调用一个统一的全局的生成器服务,用于生成全局事务号、订单号、序列号和随机数等。G0对这种场景的支持非常简单,下面以一个随机数生成器为例来说明。
- 最简单的带缓冲的生成器。例如:
package main
import (
"fmt"
"math/rand"
)
func main() {
ch := GenerateIntA()
fmt.Println(<-ch)
fmt.Println(<-ch)
}
func GenerateIntA() chan int {
ch := make(chan int, 10)
//启动一个goroutine用于生成随机数,函数返回一个通道用于获取随机数
go func() {
for {
ch <- rand.Int()
}
}()
return ch
}
//结果
5577006791947779410
8674665223082153551
- 多个goroutine增强生成器。例如:
package main
import (
"fmt"
"math/rand"
)
func main() {
ch := GenerateInt()
for i := 0; i < 100; i++ {
fmt.Println(i, ":", <-ch)
}
}
func GenerateIntA() chan int {
ch := make(chan int, 10)
go func() {
for {
ch <- rand.Int()
}
}()
return ch
}
func GenerateIntB() chan int {
ch := make(chan int, 10)
go func() {
for {
ch <- rand.Int()
}
}()
return ch
}
func GenerateInt() chan int {
ch := make(chan int, 20)
go func() {
for {
//使用select的扇入技术(Fan in)增加生成的随机源
select {
case ch <- <-GenerateIntA():
case ch <- <-GenerateIntB():
}
}
}()
return ch
}
- 有时希望生成器能够自动退出,可以借助Go通道的退出通知机制实现。例如:
package main
import (
"fmt"
"math/rand"
)
func main() {
done := make(chan struct{})
ch := GenerateIntA(done)
fmt.Println(<-ch)
fmt.Println(<-ch)
//不再不要生成器,通过close chan发送一个通知给生成器
close(done)
//done <- struct{}{}
for v := range ch {
fmt.Println(v)
}
}
func GenerateIntA(done chan struct{}) chan int {
ch := make(chan int, 10)
go func() {
Lable:
for {
//通过select监听一个信号chan来确定是否停止生成
select {
case ch <- rand.Int():
case <-done:
break Lable
}
}
close(ch)
}()
return ch
}
- 一个融合了并发、缓冲、退出通知等多重特性的生成器。例如:
package main
import (
"fmt"
"math/rand"
)
func main() {
//创建一个作为接收退出信号的chan
done := make(chan struct{})
//启动生成器
ch := GenerateInt(done)
//获取生成器资源
for i := 0; i < 10; i++ {
fmt.Println(<-ch)
}
//通知生产者停止生产
done <- struct{}{}
fmt.Println("stop gernarate")
}
//done接收通知退出信号
func GenerateIntA(done chan struct{}) chan int {
ch := make(chan int, 5)
go func() {
Lable:
for {
select {
case ch <- rand.Int():
case <-done:
break Lable
}
}
close(ch)
}()
return ch
}
//done接收通知退出信号
func GenerateIntB(done chan struct{}) chan int {
ch := make(chan int, 5)
go func() {
Lable:
for {
select {
case ch <- rand.Int():
case <-done:
break Lable
}
}
close(ch)
}()
return ch
}
//通过select执行扇入(Fan in)操作
func GenerateInt(done chan struct{}) chan int {
ch := make(chan int)
send := make(chan struct{})
go func() {
Lable:
for {
select {
case ch <- <-GenerateIntA(send):
case ch <- <-GenerateIntB(send):
case <-done:
send <- struct{}{}
send <- struct{}{}
break Lable
}
}
close(ch)
}()
return ch
}