例:统计~20000哪些是素数?
- 现有的知识点:for循环遍历判断 ```go package main
import “fmt”
// 求1~200000的素数
func main() { var lists []int for n:=1; n<=40000; n++{ for m:=2;m<n; m++ { if n % m != 0 { if n - m == 1 { lists = append(lists, n) } continue } break } } fmt.Println(lists) }
并发和并行
1. 多线程程序在单核上运行,就是并发
- 多个任务作用在一个cpu
- 从微观的角度看,在一个时间点上,其实只有一个任务在执行
2. 多线程程序在多核上运行,就是并行
- 多个任务作用在多个cpu
- 从微观的角度看,在一个时间点上,就是多个任务在同时执行。
<a name="hGEFE"></a>
# goroutine基本介绍
<a name="7xeLf"></a>
## go协程和go主线程
1. go主线程(有程序员直接成为线程,也可以理解成进程);一个go线程上,也可以起多个协程,你也可以这样理解,协程是轻量级线程。
1. Go协程的特点
- 有独立的栈空间
- 共享程序堆空间
- 调度由用户控制
- 协程是轻量级线程
<a name="HRgax"></a>
# goroutine的调度模型
![image.png](https://cdn.nlark.com/yuque/0/2021/png/425259/1637676343925-bc96a60b-36b6-4e5f-9baf-ae70a81d9d60.png#align=left&display=inline&height=440&margin=%5Bobject%20Object%5D&name=image.png&originHeight=440&originWidth=694&size=173701&status=done&style=none&width=694)
![image.png](https://cdn.nlark.com/yuque/0/2021/png/425259/1637676666758-626bb4bc-848c-48cd-827d-3ac97797d36d.png#align=left&display=inline&height=560&margin=%5Bobject%20Object%5D&name=image.png&originHeight=560&originWidth=1048&size=428394&status=done&style=none&width=1048)
![image.png](https://cdn.nlark.com/yuque/0/2021/png/425259/1637677310834-add1da45-19c0-4ea6-a146-a90a6d8acdd7.png#align=left&display=inline&height=690&margin=%5Bobject%20Object%5D&name=image.png&originHeight=690&originWidth=1435&size=665854&status=done&style=none&width=1435)
<a name="7O3PT"></a>
# 设置Golang运行的CPU数
1. go1.8之后,默认让程序运行在多个核上,可以不用设置
1. go1.8之前,需要自己设置
```go
package main
import (
"fmt"
"runtime"
)
func main() {
cpuNu := runtime.NumCPU() // 获取电脑的cpu数量
fmt.Println(cpuNu)
// 可以自己设置使用多个cpu
runtime.GOMAXPROCS(cpuNu-1)
}
channel
- 只写管道
- 只写管道
- 入参设置只读
入参 channame <- chan string
- 函数传参只写
channame chan <- string
代码
package main
func readChan(genChan <- chan string) {
<- genChan
genChan <- "c"
}
func writeChan(genChan chan <- string) {
genChan <- "ccc"
<- genChan
}
func main() {
// 传参只读
generalChan := make(chan string, 2)
generalChan <- "a"
readChan(generalChan)
// 传参只写
writeChan(generalChan)
}
select 遍历channel
- 在不确定是否能关闭管道的时候,使用select ```go package main
import “fmt”
func main() { numChan := make(chan int, 10) for i:=1 ;i<=10; i++{ numChan <- i }
for true {
select {
case v:= <- numChan:
fmt.Printf("get number %d\n" ,v)
default:
fmt.Println("get over")
return
}
}
} ```