大佬教程收集整理的这篇文章主要介绍了Go基础知识梳理(四),大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
GO的哲学是“不要通过共享内存来通信,而是通过通信来共享内存”,通道是GO通过通信来共享内存的载体。
runtime.NumGoroutIne() //返回当前程序的协程数量
runtime.GOMAXPROCS(0) //获取当前的GOMAXPROCS数量
runtime.GOMAXPROCS(2) //设置程序的GOMAXPROCS数量为2
@H_673_12@goroutIne
特性
fun main() {
//另起一个协程去打印
go func() {
fmt.Println("gorunTine")
}()
}
//创建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
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")
}
看一段融合了并发,缓冲,退出通知等多重特性的代码
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 ch
}
func GenerateB(done chan struct{}) chan int {
ch := make(chan int, 5)
go func() {
fmt.Println("线程数+B")
Label:
for {
SELEct {
case res := <-done:
fmt.Println("done", res)
break Label
case ch <- rand.Int():
}
}
close(ch)
}()
return ch
}
func GenerateInt(done chan struct{}) chan int {
//无缓冲通道
ch := make(chan int)
send := make(chan struct{})
go func() {
Label:
for {
SELEct {
case <-done:
send <- struct{}{}
send <- struct{}{}
break Label
case ch <- <-GenerateA(send):
fmt.Println("chose A")
case ch <- <-GenerateB(send):
fmt.Println("chose B")
}
}
close(ch)
}()
return ch
}
func main() {
done := make(chan struct{})
ch := GenerateInt(donE)
fmt.Println(runtime.NumGoroutIne())
for i := 0; i < 10; i++ {
fmt.Println(<-ch)
}
fmt.Println(runtime.NumGoroutIne())
done <- struct{}{}
fmt.Println("stop gernate", struct{}{})
time.Sleep(1 * time.Second) //等待1s,让停止的goruntime打印,如果不加这句话,可能会导致主线程比新起的协程早退出,从而无法打印出done {}
}
打印结果不展示,其中发现的问题:
1.打印出来的数字长度不固定
2.每次SELEct查看case是否堵塞的时候,都会执行一次该方法
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:
fmt.Printf("%s is running \n", Name)
time.Sleep(1 * time.Second)
}
}
}
func workWithValue(ctx context.Context, name String) {
for {
SELEct {
case <-ctx.Done():
fmt.Printf("%s get msg to cancel\n", Name)
return
default:
value := ctx.Value("key").(String)
fmt.Printf("%s is running value=%s \n", name, value)
time.Sleep(1 * time.Second)
}
}
}
这段代码中,都是一条链路下来的
根节点 context.BACkground() -> ctxa -> ctxb -> oc
其中ctxa加了个时间控制,所以到达一定的时间就会自动关闭
oc附带了个键对值
以上是大佬教程为你收集整理的Go基础知识梳理(四)全部内容,希望文章能够帮你解决Go基础知识梳理(四)所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。