美文网首页
Go学习日志:基本概念及通道

Go学习日志:基本概念及通道

作者: 东方泯 | 来源:发表于2018-12-14 10:24 被阅读0次
    变量声明

    简短声明方法,使用:=,在函数内部使用,外部无法通过。

    全局变量

    使用var来定义。

    函数调用

    func 函数名 (int a, int b) (int c, int d)

    input = a, b ;

    output = c, d ;

    函数其实在之前已经见过了,第一次执行hello world程序的main()其实就是一个函数,而且是一个比较特殊的函数。
    每个go程序都是从名为main的package包的main()函数开始执行,包的概念不是这里的重点,以后做单独说明。同时main()函数是无参数,无返回值的。

    注意点

    小写字母开头的函数只在本包内可见,大写字母开头的函数才能被其他包使用。

    同时这个规则也适用于变量的可见性,即首字母大写的变量才是全局的。

    函数详解

    具体参照:https://yushuangqi.com/blog/2013/ysqi-golang-function-1.html

    func function_name( [parameter list] ) [return_types] {
      函数体
    }
    
    type mytype int    // 新的类型
    func (p mytype) funcname(q int) (r,s int) {return 0,0}
    

    定义解析:

    从Go的函数定义可以看出,Go的返回值是放在函数名和参数后面的,这点和C及Java的差别还是很多大的。

    func:Go的函数声明关键字,声明一个函数。

    function_name:函数名称,函数名和参数列表一起构成了函数签名。

    parameter list:参数列表,指定的是参数类型、顺序、及参数个数。参数是可选的,即函数可以不包含参数。参数就像一个占位符,这是参数被称为形参,当函数被调用时,将具体的值传递给参数,这个值被称为实际参数。

    return_types:返回类型,函数返回一列值。return_types 是该列值的数据类型。这里需要注意的是Go函数支持多返回值。有些功能不需要返回值,这种情况下 return_types 不是必须的。

    函数体:函数定义的代码集合,表示函数完成的动作。

    在golang里面,使用go这个关键字,后面再跟上一个函数就可以创建一个线程。后面的这个函数可以是已经写好的函数,也可以是一个匿名函数。

    那为什么会这样呢?因为程序会优先执行主线程,主线程执行完成后,程序会立即退出,没有多余的时间去执行子线程。如果在程序的最后让主线程休眠1秒钟,那程序就会有足够的时间去执行子线程。

    指针使用

    https://blog.csdn.net/whatday/article/details/74453089

    goroutine:

    Go语言是原生支持****语言级****并发的,这个并发的最小逻辑单元就是goroutine。goroutine就是Go语言提供的一种用户态线程,这种用户态线程是跑在内核级线程之上的,goroutine在运行时的调度是由Go语言提供的调度器来进行的,创建一个goroutine使用关键字go,go创建的goroutine不会阻塞主线程:

    go func_name()

    Go程序中没有语言级的关键字让你去创建一个内核线程,你只能创建goroutine,内核线程只能由调度器根据实际情况去创建。

    调度器原理参考链接:**http://studygolang.com/articles/1855

    channel:

    Channel是Go中的一个核心类型,可以把它看成一个管道,通过它可以发送或者接收数据进行通讯(communication)。配合goroutine,就形成了一种既简单又强大的请求处理模型,即N个工作goroutine将处理的中间结果或者最终结果放入一个channel,另外有M个工作goroutine从这个channel拿数据,再进行进一步加工,通过组合这种过程,可以胜任各种复杂的业务模型。

    channel的基本操作:

    var c chan int //声明一个int类型的channel,注意,该语句仅声明,不初始化channel

    c := make(chan type_name) //创建一个无缓冲的type_name型的channel,无缓冲的channel当放入1个元素后,后续的输入便会阻塞

    c := make(chan type_name, 100) //创建一个缓冲区大小为100的type_name型的channel

    c <- x //将x发送到channel c中,如果channel缓冲区满,则阻塞当前goroutine

    <- c //从channel c中接收一个值,如果缓冲区为空,则阻塞

    x = <- c //从channel c中接收一个值并存到x中,如果缓冲区为空,则阻塞

    x, ok = <- c //从channel c中接收一个值,如果channel关闭了,那么ok为false(在没有defaultselect语句的前提下),在channel未关闭且为空的情况下,仍然阻塞

    close(c) //关闭channel c

    for term := range c {} //等待并取出channelc中的值,直到channel关闭,会阻塞

    单向channel:

    var ch1 chan<- float64 //只能向里面写入float64的数据,不能读取

    var ch2 <-chan int //只能读取int型数据

    select:

    select用于在多个channel上同时进行侦听并收发消息,当任何一个case满足条件时即执行,如果没有可执行的case则会执行default的case,如果没有指定defaultcase,则会阻塞程序,select的语法:

    select {
    
       case communication clause :
    
          statement(s);     
    
       case communication clause :
    
          statement(s);
    
       /可以定义任意数量的 case /
    
       default : /可选 /
    
          statement(s);
    
    }
    
    说明:
    • 每个case都必须是一次通信

    • 所有channel表达式都会被求值

    • 所有被发送的表达式都会被求值

    • 如果任意某个通信可以进行,它就执行;其他被忽略。

    • 如果有多个case都可以运行,Select会随机公平地选出一个执行。其他不会执行。

    • 否则: 1.如果有default子句,则执行该语句。

    • 如果没有default字句,select将阻塞,直到某个通信可以运行;Go不会重新对channel或值进行求值。

    package main
    
    import (
    
    "fmt"
    
       "time"
    
    )
    
    func enqueue(q chan int) {
    
       time.Sleep(time.Second * 3)
    
        q <- 10
    
        close(q)
    
    }
    
    func main() {
    
        var c =make(chan int)
    
        go enqueue(c)
    
        for {
    
            select {
    
                casex, ok := <- c:
    
                   if ok {
    
                       fmt.Println(x)
    
                   } else {
    
                       fmt.Println("closed")
    
                       return
    
                   }
    
               default:
    
                   fmt.Println("waiting")
    
                   time.Sleep(time.Second)
    
            }
    
        }
    
    }
    

    channel里的数据跟array一样,会fifo,不会黏在一起。

    /* 声明变量,默认 map 是 nil */
    var map_variable map[key_data_type]value_data_type
    
    /* 使用 make 函数 */
    map_variable := make(map[key_data_type]value_data_type)
    

    相关文章

      网友评论

          本文标题:Go学习日志:基本概念及通道

          本文链接:https://www.haomeiwen.com/subject/caywhqtx.html