协程 go

函数相互独立运行的能力。
Goroutines是并发运行的函数

创建语法

1
go task()

实例1

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
package main

import (
"fmt"
"time"
)

func f1(s string) {
for i := 0; i < 10; i++ {
fmt.Printf("第%d次执行 %v \n", i + 1, s)
time.Sleep(time.Millisecond * 100)
}
}

func main() {

go f1("test")
// f1("test")

f1("test2")

fmt.Println("over")

}

通道 channel

用于在协程之间共享数据
作为协程之间的管道保证通信同步
需要在声明通道时指定数据类型
任何给定时间都只有一个能访问通道

通道由make函数创建,该函数指定chan关键字和通道的元素类型

创建语法

1
2
3
4
5
// 整型无缓冲通道
Unbuffered := make(chan int)
// 字符串型有缓冲
buffered := make(chan string, 10)

发送接受语法

1
2
3
4
5
6
7
var myChannel = make(chan string)
var s string
//将s写入进channel
myChannel <- s
//从channel中读取数据保存到s
s <- myChannel

WaitGroup实现同步

实例

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
package main

import (
"fmt"
"sync"
)

var wg sync.WaitGroup

func say(i int) {
defer wg.Done() //结束协程 登记 -1
// 等价于 wg.Add(-1)
fmt.Printf("这是第%d\n", i + 1)
}

func main() {

for i := 0; i < 10; i++ {
go say(i)
wg.Add(1) //每启动一个协程 登记 +1
}

wg.Wait() // 等待所有携程结束

}

Mutext 互斥锁

实例

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
package main

import (
"fmt"
"sync"
"time"
)

var wg sync.WaitGroup
var lock sync.Mutex
var res = 100

func add() {
defer wg.Done()
// lock.Lock()
res += 1
time.Sleep(time.Millisecond * 10)
// lock.Unlock()
}

func sub() {
defer wg.Done()
// lock.Lock()
res -= 1
time.Sleep(time.Millisecond * 10)
// lock.Unlock()
}

func main() {

for i := 0; i < 100; i++ {
go add()
wg.Add(1)
go sub()
wg.Add(1)
}

wg.Wait()
fmt.Print(res)

}

select

  • 类似于switch 用于处理异步IO操作。select会监听case中channel的读写操作,当case中的channel读写操作为非堵塞状态时会触发相应动作
  • 如果多个case都可以运行,则会随机选择一个执行
  • 如果没有default语句,且没有可执行case语句,select将会堵塞

实例

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
package main

import (
"fmt"
"time"
)

var chanInt = make(chan int)
var chanStr = make(chan string)

func main() {

go func() {
chanInt <- 1
// close(chanInt)
}()

go func() {
chanStr <- "test"
// close(chanStr)
}()

for{
select {
case r := <-chanInt:
fmt.Printf("%v\n", r)
case r := <-chanStr:
fmt.Printf("%v\n", r)
default:
fmt.Println("none")
}
time.Sleep(time.Second)
}

}