2019-01-19 Golang-goroutine
1.Go协程和主线程
1.Go主线程可以有多个协程(协程是轻量级的线程)编译器优化
2.Go协程的特点
- 有独立的栈空间
- 共享程序的堆空间
- 调度由用户控制e
- 协程是轻量级的线程
2.goroutine入门
1.MPG模型
- M: 操作系统的主线程
- P: 协程执行需要的上下文
- G: 协程
2.简单协程操作
package main
import (
"fmt"
"time"
)
func routine() {
for i := 0; i < 10; i++ {
fmt.Printf("function routine is run %d\n", i)
time.Sleep(time.Second)
}
}
func main() {
/*
使用协程与主线程交替打印文字
*/
go routine()
for i := 0; i < 10; i++ {
fmt.Printf("function main is run %d\n", i)
time.Sleep(time.Second)
}
}
3.Channel的引出
1.channel的介绍
1. channel的本质就是一个数据结构-队列
2. 数据是先进先出 FIFO
3. 线程安全 多个goroutine访问时 不需要加锁 channel本身线程安全
4. channel有类型 一个string的channel只能存放string类型的数据
5. channel是引用类型
2.channel入门案例
package main
import "fmt"
/*
channel的练习
*/
func main() {
// channel 的初始化
var intChan chan int
intChan = make(chan int, 5)
intChan <- 5
num1 := 200
intChan <- num1
// 数据的取出
num2 := <- intChan
fmt.Println(num2)
fmt.Println(<- intChan)
fmt.Printf("len of channel: %d, cap of channel: %d", len(intChan), cap(intChan))
}
3.channel的问题所在
var faChan chan interface{}
faChan = make(chan interface{}, 5)
person01 := Human{"小张", 20}
person02 := Human{"小李", 22}
faChan <- person01
faChan <- person02
faChan <- "嘤嘤嘤"
faChan <- 1122
// 这里注意 person03 类型为interface类型 需要转型为Human类型才可以后续正常操作
person03 := <- faChan
// 这里进行类型断言使用
person04 := person03.(Human)
fmt.Println(person04.Name)
4.channel的关闭
fmt.Println("-------------------------")
close(faChan)
fmt.Println( <- faChan)
fmt.Println( <- faChan)
fmt.Println( <- faChan)
// 注意channel在关闭之后不能再进行写入 但是还可以进行读取
5.channel的遍历
s// channel的遍历
var interChan chan int
interChan = make(chan int, 10)
for a := 0; a < 10; a++ {
interChan <- a
}
len := len(interChan)
for a := 0; a < len; a++ {
fmt.Println( <- interChan)
}
//for-range 进行遍历
for a := 0; a < 9; a++ {
interChan <- a
}
// 注意在遍历之前的关闭是不可少的
close(interChan)
for v := range interChan {
println(v)
}
6.select相对于管道的使用
package main
import "fmt"
func main() {
var channel01 chan int
var channel02 chan int
channel01 = make(chan int, 20)
channel02 = make(chan int, 20)
for a := 0; a < 20; a++ {
channel01 <- a
}
for b := 10; b < 30; b++ {
channel02 <- b
}
// 进行读取操作
ForBlock:
for {
select {
case v := <- channel01:{
fmt.Println(v)
}
case v := <- channel02:{
fmt.Println(v)
}
default:{
fmt.Println("结束")
break ForBlock
}
}
}
}
7.goroutine中发生错误时的操作
func ReadSth() {
defer func(){
if err := recover(); err != nil {
fmt.Printf("发生了异常:%v\n", err)
}
}()
var myMap map[int]string
myMap[1] = "嘤嘤嘤"
}
// 使用recover捕获错误
4.go语言的互斥锁
package main
import (
"fmt"
"sync"
"time"
)
/*
求阶乘引出go语言中的锁相关的问题
*/
var (
maps = make(map[int]int, 10)
lock sync.Mutex
)
func Factorial(input int){
result := 1
for a := 1; a <= input; a++ {
result *= a
}
lock.Lock()
maps[input] = result
lock.Unlock()
}
func main() {
time.Sleep(time.Second * 5)
for a := 1; a <= 100; a++ {
go Factorial(a)
}
for k, v := range maps {
fmt.Printf("key is %d, value is %d\n", k, v)
}
}