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

东方泯 · · 1193 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

变量声明

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

全局变量

使用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学习日志:基本概念及通道

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1193 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传