select

用于chan通道专用的控制结构

1
2
3
4
5
6
7
ch := make(chan bool)
select {
case c <- ch:
	fmt.Println("hello world")
default:
	return
}

使用误区

  1. 39行, return 会一直阻塞? 希望大神解释下?
    1. 答: return相当于返回,不再继续,将永远阻塞,直到主程序退出.一般用于结束这个goroutine才加上return,否则不要轻易使用.
  2. 如果return 换成break或continue就不会阻塞
 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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"log"
	"math/rand"
	"sync"
)

type Cache struct {
	ch chan int
}
var (
	_cache *Cache
	_once sync.Once
)
func NewCache() *Cache {
	_once.Do(func() {
		_cache = &Cache{
			ch: make(chan int, 10),
		}
		_cache.monitor()
	})
	return _cache
}
func (c *Cache) Push(x int) {
	c.ch <- x

}
func (c *Cache) monitor() {
	go func() {
		for {
			select {
			case result, ok := <-c.ch:
				n := c.N()
				log.Printf("result:%d, ok:%v, n:%d\n", result, ok, n)
				if n == 1 {
					return // 如果换成return 会一直阻塞. 这是为什么?
				}
				if ok {
					log.Println("-----------result:", result)
				}
			}
		}
	}()
}
func (c *Cache) N() int {
	return rand.Intn(2)
}

func main() {
	log.SetFlags(log.Lshortfile)
	r := gin.Default()
	r.GET("/add", func(c *gin.Context) {
		NewCache().Push(rand.Intn(1000))
		NewCache().Push(rand.Intn(1000))
		NewCache().Push(rand.Intn(1000))
		NewCache().Push(rand.Intn(1000))
		c.JSON(200, gin.H{
			"x":"ok",
		})
	})
	r.Run(":8080")
}

参考

  1. Go 语言设计与实现 5.2 select