使用方法名字符串,调用方法
思路:通过 reflect
。
1
2
3
4
5
6
7
8
9
10
11
12
|
type animal struct {
name string
}
func (a *animal) Eat() {
println("animal eat")
}
func main() {
a := animal{"cat"}
reflect.ValueOf(&a).MethodByName("Eat").Call([]reflect.Value{})
}
|
3个 goroutine 按照顺序分别打印10次"cat",“fish”,“dog
思路:若限制只用 3 个 goroutine
,如下
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
|
var (
catChan = make(chan int)
fishChan = make(chan int)
dogChan = make(chan int)
allChan = make(chan struct{})
)
func cat(ch chan int) {
for v := range ch {
fmt.Printf("%v cat\n", v)
fishChan <- v
if v == 10 {
break
}
}
}
func fish(ch chan int) {
for v := range ch {
fmt.Printf("%v fish\n", v)
dogChan <- v
if v == 10 {
break
}
}
}
func dog(ch chan int) {
for v := range ch {
fmt.Printf("%v dog\n", v)
if v == 10 {
allChan <- struct{}{}
break
}
catChan <- v + 1
}
}
func main() {
go cat(catChan)
go fish(fishChan)
go dog(dogChan)
catChan <- 1
<-allChan
}
|
思路:若不限制 goroutine
数目
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
|
var (
catChan = make(chan int)
fishChan = make(chan int)
dogChan = make(chan int)
allChan = make(chan struct{})
)
func cat() {
v := <-catChan
fmt.Printf("%v cat\n", v)
fishChan <- v
}
func fish() {
v := <-fishChan
fmt.Printf("%v fish\n", v)
dogChan <- v
}
func dog() {
v := <-dogChan
fmt.Printf("%v dog\n", v)
if v == 10 {
allChan <- struct{}{}
return
}
catChan <- v + 1 // 注意是无缓冲的 chan,若放到 if 前,就会死锁!
}
func main() {
for i := 0; i < 10; i++ {
go cat()
go fish()
go dog()
}
catChan <- 1
<-allChan
}
|
启动 2 个 goroutine 2 秒后取消,第一个 1 秒执行完,第二个 3 秒执行完
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
|
func f1(ch chan struct{}) {
time.Sleep(time.Second * 1)
ch <- struct{}{}
}
func f2(ch chan struct{}) {
time.Sleep(time.Second * 3)
ch <- struct{}{}
}
func main() {
ctx, _ := context.WithTimeout(context.Background(), time.Second*2)
ch := make(chan struct{}, 1)
go func() {
go f1(ch)
select {
case <-ctx.Done():
println("f1 timeout")
case <-ch:
println("f1 done")
}
}()
go func() {
go f2(ch)
select {
case <-ctx.Done():
println("f2 timeout")
case <-ch:
println("f2 done")
}
}()
time.Sleep(time.Second * 5)
}
|
2 个 goroutine 交替打印 10 个字母和数字
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
|
var (
ch1 = make(chan byte)
ch2 = make(chan int)
)
func letter() {
for i := 0; i < 10; i++ {
v := <-ch1
fmt.Println(string(v))
ch2 <- int(v - 'a' + 1)
}
}
func number() {
for i := 0; i < 10; i++ {
v := <-ch2
fmt.Println(v)
if v == 10 {
return
}
ch1 <- byte(v + 'a')
}
}
func main() {
go letter()
go number()
ch1 <- 'a'
time.Sleep(time.Second * 2)
}
|
当 select 监控多个 chan 同时到达就绪态时,如何先执行某个任务?
可通过添加标签
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
func prioritySelect(ch1, ch2 <-chan string) {
for {
select {
case val := <-ch1:
fmt.Println(val)
case val2 := <-ch2:
priority: // 标签
for {
select {
// 若 ch1 有值,先打印 ch1 的值,再打印 ch2 的值
case val1 := <-ch1:
fmt.Println(val1)
default:
break priority
}
}
fmt.Println(val2)
}
}
}
|