zoukankan      html  css  js  c++  java
  • GO/GOLANG程序员笔记大全

    ---------------------------------------- go 并发

    // 注解:go 语言天生为程序并发所设计,可以说go的强项就是在cpu并发上的处理。
    // go 语言层面就支持了并发。(不是一般高级语言的多线程并发,是系统级真实并发)
    // go 语言通过安全的通道发送和接受数据以实现同步
    // 一般情况下,一个普通的桌面计算机跑十几二十几个线程就有点负载过大了,但是同样的硬件设备go可以轻松上K。

     

    ----------------------------------------- goroutine

    // 注解:go 并发设计的核心,goroutine在并发中起到的作用就是协程(CSP),但是它比线程更小。(协程=微线程)
    // go 不支持后台协程,意思就是主程序退出,协程跟着一起退出
    func newTask() {
        for {
            fmt.Println("new task ...")
            time.Sleep(time.Second) // 休眠1s
        }
    }
    
    func main() {
        go newTask()    // 新建一个协程,新建一个任务
        
        for {
            fmt.Println("main ...")
            time.Sleep(time.Second) // 休眠1s
        }
    }
    // result : 
    // main... 
    // new task ...
    // ....

     

    ----------------------------------------- gosched

    // 注解:让出CPU时间片,让出当前 gorotine 的执行权限,
    // 调度器安排其他等待任务运行,并在下次某个时候从该位置恢复执行。
    func main() {
        go func() {
            for i := 0; i < 5; i++ {
                fmt.Println("go")
            }
        }()
        
        for i := 0; i < 2; i++ {
            fmt.Println("hello")
        }
        
        // 这种情况,匿名函数未得到执行程序就结束了。    
        // 时间片案例演示代码,修改如下:
        for i := 0 .... {
            runtime.Gosched()
            fmt.Println("hello")
        }
        // 执行结果:
        // go go ... hello ..
    }


    ----------------------------------------- goexit

    import "runtime"
    // 注解:终止所在的协程 (所在的协程不是当前函数)
    func test() {
        defer fmt.Println("ccccc")    
        runtime.Goexit()
        fmt.Println("dddd")
    }
    
    func main() {
        go func (){
            fmt.Println("aaaa")
            test()
            fmt.Println("bbbb")
        }
        for {
        }
        
        // result:
        // aaaa  cccc
    }

     

    ----------------------------------------- gomaxProcs

    // 注解:设置可以并行计算的 CPU 核数的最大值
    import "runtime"
    
    func main() {
        n := runtime.GOMAXProcs(1)    //制定以1核运算
        fmt.Println("n = ", n)
        
        for {
            go fmt.Print(1)    
            fmt.Print(0)
        }
        
        // 打印结果:11111.. 一大片, 00000...一大片
        // 如果设置 GOMAXProcs(4) 为 4 核交叉效果更好
    }


    ----------------------------------------- 资源争夺问题 channel

    // 注解:channel 也是一种数据类型,同步
    // 语法:channel <- value     // 发送 value 数据到 channel
    // <- channel                 // 接收并丢弃
    
    // 案例:
    // 全局变量,创建一个 channel
    var ch = make(chan int)
    
    // 定义一个打印机,参数为字符串,按每个字符打印
    func Printer(str string) {
        for _, data := range str {
            fmt.Printf("%c", data)
            time.Sleep(time.Second)
        }
        fmt.Printf("
    ")
    }
    
    func person1() {
        Printer("loong print")
        ch <- 666        // 给管道写数据
    }
    
    func person2() {
        <- ch            // 从管道取数据,如果管道没有数据前他就会阻塞
        Printer("make print")
    }
    
    func main() {
        // 新建 2 个协程,代表 2 个人,2 个人同时使用打印机
        go person1()
        go person2()
    }
    // 注解: 【认真看】
    // 没有 channel 的情况
    // 打印结果混乱,person1 打印一个h,person2 打印一个 w,交叉了。不符合我们的要求
    // 增加 channel ,则在 <-ch 的地方进行了阻塞,通过进、出的方式融合这种解决这种并发互抢资源的问题。


    ----------------------------------------- channel 实现同步和数据交互

    fun main() {
        ch := make(chan string)
        
        defer fmt.Println("主协程也结束")
        
        go func() {
            defer fmt.Println("子协程调用完毕。")
            
            for i := 0; i < 2; i++ {
                fmt.Println("子协程 i=", i)
                time.Sleep(time.Second)
            }
            
            ch <- "我是子协程,工作完毕"
        }
        
        str := <-ch // 没有数据前,阻塞
        fmt.Println("str = ", str)
    }
    
    // 注意:程序需求:主程序结束之前,能够完整执行匿名函数中的代码
    // 使用 channel 配合完成


    ----------------------------------------- channel 无缓存&有缓存

    c1 := make(chan int)         无缓冲
    c2 := make(chan int,1)      有缓冲
    c1 < -1                            
    // 无缓冲:不仅仅是向 c1 通道放 1,
    // 而是一直要等有别的协程 <-c1 接手了这个参数,那么c1<-1才会继续下去,要不然就一直阻塞着。
    // 有缓冲: c2<-1 则不会阻塞,因为缓冲大小是1(其实是缓冲大小为0),
    // 只有当放第二个值的时候,第一个还没被人拿走,这时候才会阻塞。
    
    // 不需要再使用记得关闭channel  close(c1)
    // 判断管道是否关闭 if num, ok := <- c1; ok == true { // 关闭了 }
    
    
    ----------------------------------------- channel 单方向
    var ch1 chan int        // ch1 是一个正常的 channle,不是单向的
    var ch2 chan<- float64    // ch2 是单向 channel,只用于写 float64 数据
    var ch3 <-chan int        // ch3 是单向 channel,只用于读取 int 数据
    
    // * 管道的操作,一定要避免死锁的情况。


    ----------------------------------------- channel 应用

    // 此案例可以应用很多场景,每写一个,则可以消耗一个
    // 此通道只能写,不能读
    func producer(out chan<- int) {
        for i := 0; i < 10; i++ {
            out <- i * i
        }
        
        close(out)
    }
    
    // 此通道只能读,不能写
    func consumer(in <-chan int) {
        for num := range in {
            fmt.Println("num = ", num)
        }
    }
    
    func main() {
        // 创建一个双向通道
        ch := make(chan int)
        
        // 生产者,生产数字,写入 channel
        // 开启一个协程
        go producer(ch)
        
        // 消费者,从channel读取内容打印
        consumer(ch)
    }

     

    ----------------------------------------- Timer

    import (
        "time"
        "fmt"
    )
    
    func main() {
        // 创建一个定时器,设置时间为2s,2s后,往time通道写内容
        timer := time.NewTimer(2 * time.Second)
        fmt.Println("当前时间:", time.Now())
        
        // 2s后,往timer.C写数据,有数据后读取
        t := <-time.C    // channel 没有数据前后阻塞
        fmt.Println("t = ", t)
    }


    ----------------------------------------- select

    // 注解:go语言提供了一个关键字 select,通过 select 可以监听 channel 上的数据流动
    // 语法:(类似 switch)
    select {
        case <-chan:
            // 如果channel 成功读到数据,则进入 case 块语句
        case chan<- 1:
            // 如果channel 成功写到数据,则进入 case 块语句
        default:
            // 如果上面都没有成功,则进入default处理流程
            // 注意:慎用,很消耗 cpu
    }

     

  • 相关阅读:
    C#时间格式转换问题(12小时制和24小时制)
    ajax跨域请求webservice webconfig配置
    C#时间戳转化为DateTime
    C#生成缩略图
    codeforces-1348-C Phoenix and Distribution
    P4314 CPU监控
    YangK's dfs序与树链剖分
    Yangk's 静态主席树
    P2253 好一个一中腰鼓!
    codeforces-1341D-Nastya and Scoreboard 记忆化搜索
  • 原文地址:https://www.cnblogs.com/dqh123/p/9481718.html
Copyright © 2011-2022 走看看