1、goroutine
(1)通过go关键字创建一个协程
(2)主协程退出后,子协程也会退出
package main
import (
"fmt"
"time"
)
func main() {
// 新建一个协程
go newTask()
// 主协程退出后,子协程也会退出
i := 0
for {
i++
fmt.Println("main")
time.Sleep(time.Second)
if i == 3 {
break
}
}
}
func newTask() {
for {
fmt.Println("newTask")
time.Sleep(time.Second)
}
}
2、runtime包
(1)n := runtime.GOMAXPROCS(1) -> 指定协程的核心数,返回之前的核心数
(2)runtime.Goexit() -> 终止所在的协程
(3)runtime.Gosched() -> 让出时间片,先让其他协程执行,再回来执行这个协程
package main
import (
"fmt"
"runtime"
)
func main() {
// 指定协程的核心数,返回之前的核心数
n := runtime.GOMAXPROCS(1)
fmt.Println("n = ", n)
go func() {
for i := 0; i < 5; i++ {
fmt.Println("goroutine")
if i == 2 {
// 终止所在的协程
runtime.Goexit()
}
}
}()
for i := 0; i < 3; i++ {
// 让出时间片,先让其他协程执行,再回来执行这个协程
runtime.Gosched()
fmt.Println("mian")
}
}
3、channel
(1)创建channel,make(chan Type),make(chan Type,capacity)
- 无缓冲的channel,如果里边的数据不读,写数据会阻塞
- 有缓冲的channel,当channel满了,写数据也会阻塞
(2)channel <- 向channel中写数据
(3)从channel中读取数据,如果没有数据,将阻塞;
- <- channel:接受并丢弃数据
- x := <- channel :从channel中读取数据,赋值给x
- x,ok := <- channel :从channel中读取数据,并判断channe是否已经关闭或者是否为空
- for data:= rang channel:通过rang获取管道的数据
(4)close(channel) 关闭channel,无法再发送数据,但是可以读数据
(5)双向channel能隐式转换成单项channel:chan<- 、<-chan
package main
import (
"fmt"
"time"
)
var ch = make(chan int)
func main() {
go func() {
Printer("hello")
// 给管道写数据
ch <- 1
}()
go func() {
// 从管道取数据,如果没有数据就阻塞
<-ch
Printer("world")
}()
for {
}
}
func Printer(world string) {
for _, data := range world {
fmt.Printf("%c", data)
time.Sleep(time.Second)
}
fmt.Println()
}
4、timer
(1)timer := time.NewTimer(2 * time.Second):实现延时功能
(2)timer.Stop():停止定时器,
(3)timer.Reset(2 * time.Second):重新设置timer的时间
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println(time.Now())
// 直接返回一个管道
timer := time.After(2 * time.Second)
t := <-timer
fmt.Println(t)
}
func main1() {
fmt.Println(time.Now())
time.Sleep(2 * time.Second)
fmt.Println(time.Now())
}
func main2() {
// 创建一个定时器,2s后,往time通道写入当前时间
timer := time.NewTimer(2 * time.Second)
fmt.Println(time.Now())
t := <-timer.C
fmt.Println(t)
}
5、ticker
package main
import (
"fmt"
"time"
)
func main() {
ticker := time.NewTicker(time.Second)
i := 0
for {
<-ticker.C
i++
fmt.Println("", i)
if i == 5 {
ticker.Stop()
break
}
}
}
6、select
select 中 case的条件必须是一个io操作
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan int)
quit := make(chan bool)
go func() {
for i := 0; i < 10; i++ {
fmt.Println(<-ch)
}
quit <- false
}()
feibona(ch, quit)
}
func feibona(ch chan<- int, quit <-chan bool) {
ticker := time.After(5 * time.Second)
x, y := 1, 1
for {
select {
case ch <- x:
x, y = y, x+y
time.Sleep(time.Second)
case flag := <-quit:
if flag {
fmt.Println("结束啦:", flag)
return
} else {
fmt.Println("收到标记:", flag)
}
case <-ticker:
fmt.Println("超时啦")
return
}
}
}