ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Go基础知识梳理(四)

2022-02-08 11:31:08  阅读:102  来源: 互联网

标签:case func fmt 基础知识 Println go time Go 梳理


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

  1. 先打乱所有的case语句
  2. 遍历case语句,查看是否已经读写了
  3. 选择可读写的case去执行
  4. 没有可读写的case,则查看default语句是否定义,再去执行
  5. 没有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 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是否堵塞的时候,都会执行一次该方法

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:
            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附带了个键对值

标签:case,func,fmt,基础知识,Println,go,time,Go,梳理
来源: https://www.cnblogs.com/xiaofua/p/15870609.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有