生成器设计模式
生成器模式,产生一个可以不停生成数据的对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| func randNum(max int) <-chan int { rand.Seed(time.Now().UnixNano()) ch := make(chan int) go func() { for { select { case ch <- rand.Intn(max): } } }() return ch }
func main() { re := randNum(100) for i := 0; i < 100; i++ { fmt.Println(<-re) } }
|
过滤器
例如获取范围内的素数,可以通过最小的数字作为过滤,将后续能整除的数字过滤掉,当队列为空,则结束
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| func filer(ch chan int, wg *sync.WaitGroup) { wg.Add(1) defer wg.Done() num, ok := <-ch if !ok { return } fmt.Println(num) chlid := make(chan int) defer close(child) go filer(chlid, wg) for i := range ch { if i%num != 0 { chlid <- i } } }
func main() { n := 10000 ch := make(chan int) wg := &sync.WaitGroup{} go func() { for i := 2; i <= n; i++ { ch <- i } close(ch) }() filer(ch, wg) wg.Wait() }
|
单例模式
单例模式是指在多线程下执行同一个命令,最终只会产生执行一次的效果。常用于初始化。
golang中的单例模式一般通过sync.Once
实现,init
函数也可以实现,这两者其实都是通过一个标记实现是否已经进行单例的初始化。
例如使用sync.Once
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| var money int var one sync.Once
func main() { wg := sync.WaitGroup{} for i := 0; i < 1000; i++ { wg.Add(1) go func() { defer wg.Done() one.Do(func() { time.Sleep(time.Millisecond) money += 10 }) }() } wg.Wait() fmt.Println(money) }
|
使用标记
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| var money int var one bool var mu sync.Mutex
func main() { wg := sync.WaitGroup{} for i := 0; i < 1000; i++ { wg.Add(1) go func() { defer wg.Done() mu.Lock() defer mu.Unlock() if !one { time.Sleep(time.Millisecond) money += 10 one = true } }() } wg.Wait() fmt.Println(money) }
|
判断是否已经执行的时候,可以不需要加锁,后续修改值的时候再加,可以节省资源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| var money int var one bool var mu sync.Mutex
func main() { wg := sync.WaitGroup{} for i := 0; i < 1000; i++ { wg.Add(1) go func() { defer wg.Done() if !one { mu.Lock() defer mu.Unlock() if !one { time.Sleep(time.Millisecond) money += 10 one = true } } }() } wg.Wait() fmt.Println(money) }
|