Go基础知识梳理(四)
GO的哲学是”不要通过共享内存来通信,而是通过通信来共享内存”,通道是GO通过通信来共享内存的载体。
rumtime包常用方法
runtime.NumGoroutine() //返回当前程序的协程数量
runtime.GOMAXPROCS(0) //获取当前的GOMAXPROCS数量
runtime.GOMAXPROCS(2) //设置程序的GOMAXPROCS数量为2
goroutine
特性
- 执行是非阻塞的,不会等待
- go 后面的返回值会被忽略
- 调度器不能保证goroutine的执行顺序
fun main() {
//另起一个协程去打印
go func() {
fmt.Println("goruntine")
}()
}
chan
//创建chan
c := make(chan dataType)
//无缓冲, len 和 cap 都是0
fmt.Println(len(c)) //0
fmt.Println(cap(c)) //0
//有缓冲
c = make(chan dataType, 10)
//len 代表没有被读取的元素数, cap 代表整个通道的容量
fmt.Println(len(c)) //0
fmt.Println(cap(c)) //10
WaitingGroup组件
Add(10) 给内置计数器加10
Done() 相当于Add(-1)
Wait() 内置计数器不为0则一直等待
// 写法
func main() {
var wg sync.WaitGroup
wg.Add(10)
for i := 0; i < 10; i++ {
go func(i int) {
defer wg.Done()
fmt.Println(i)
time.Sleep(time.Millisecond * 3000)
}(i)
}
wg.Wait()
fmt.Println("done")
}
select
- 先打乱所有的case语句
- 遍历case语句,查看是否已经读写了
- 选择可读写的case去执行
- 没有可读写的case,则查看default语句是否定义,再去执行
- 没有defaul语句,则会等待可执行的case
看一段融合了并发,缓冲,退出通知等多重特性的代码
func GenerateA(done chan struct{}) chan int {
ch := make(chan int, 5)
// fmt.Println("通道数+1")
go func() {
fmt.Println("线程数+A")
Label:
for {
select {
case res := <-done: fmt.println("done", res) break label case ch <- rand.int(): } close(ch) }() return func generateb(done chan struct{}) int { :="make(chan" int, 5) go func() fmt.println("线程数+b") label: for select res generateint(done 无缓冲通道 int) send <-done: struct{}{} <-generatea(send): fmt.println("chose a") <-generateb(send): b") main() done fmt.println(runtime.numgoroutine()) i < 10; i++ fmt.println(<-ch) fmt.println("stop gernate", struct{}{}) time.sleep(1 * time.second) 等待1s,让停止的goruntime打印,如果不加这句话,可能会导致主线程比新起的协程早退出,从而无法打印出done {} code></-done:>
打印结果不展示,其中发现的问题:
1.打印出来的数字长度不固定
2.每次Select查看case是否堵塞的时候,都会执行一次该方法
Context
func main() {
ctxa, cancel := context.WithCancel(context.Background())
go work(ctxa, "work1")
tm := time.Now().Add(3 * time.Second)
ctxb, _ := context.WithDeadline(ctxa, tm)
go work(ctxb, "work2")
oc := OtherContext{ctxb}
ctxc := context.WithValue(oc, "key", "andes, pass from main")
go workWithValue(ctxc, "work3")
time.Sleep(10 * time.Second)
cancel()
time.Sleep(5 * time.Second)
fmt.Println("main stop")
}
type OtherContext struct {
context.Context
}
func work(ctx context.Context, name string) {
for {
select {
case <-ctx.done(): fmt.printf("%s get msg to cancel\n", name) return default: is running \n", time.sleep(1 * time.second) } func workwithvalue(ctx context.context, name string) { for select case <-ctx.done(): value :="ctx.Value("key").(string)" name, value) < code></-ctx.done():>
这段代码中,都是一条链路下来的
根节点 context.Background() -> ctxa -> ctxb -> oc
其中ctxa加了个时间控制,所以到达一定的时间就会自动关闭
oc附带了个键对值
Original: https://www.cnblogs.com/xiaofua/p/15870609.html
Author: 小傅啊
Title: Go基础知识梳理(四)
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/516446/
转载文章受原作者版权保护。转载请注明原作者出处!