go语言快速入门教程

发表时间:2020-05-11 16:46

  go语言是目前非常火热的语言,广泛应用于服务器端,云计算,kubernetes容器编排等领域。它是一种开源的编译型程序设计语言,支持并发、垃圾回收机制以提升应用程序性能。它既具有像c这种静态编译型语言的高性能,又具备像python这种动态语言的高效性。很多go程序员都是从C++,Java等面向对象语言因为工作的需要转过来的,因此没有必要从0开始学习go,当初自己的想法是找一篇半小时入门go的博客,貌似没有类似的好文章=_=。搜到的都是一些从小白入手的臃肿教程,学习起来太慢!!!so,打算写这篇go语言快速入门的指南。

  本文写作思路重点在于和C++语言的不同之处入手,强调go的特性,注重快速入门,因此不介绍一些非常基础的知识,非常基础的一些知识可以去看go语言圣经。关于go环境的安装配置以及vscode编辑器的配置在之前的博客已经介绍,请移步。本文整体组织结构如下:

  在学习任何一门语言的时候,首先都是给出hello world的示例,因此本文也不免俗,看看第一个go语言程序:

  和python语言很像,go程序都必须包含在一个包package中,go程序一般由三部分组成:包声明部分、第三方包导入部分和函数声明部分。go语言使用关键字package声明要创建的包;使用import导入第三方包;使用关键字func声明要创建的函数。

  按照惯例,处于同一个文件里的代码文件,必须使用同一个包名,包和文件夹的名字相同。Go编译器不允许声明导入某个包却不使用。使用下划线可以让编译器接收这类导入,并且调用对应包内的所有代码文件中定义的init函数。 init函数会在main函数执行前执行。

  go语言规定,函数、控制结构(if,for,switch)等的左大括号“{”必须和函数声明或控制结构放在同一行

  可见性规则:go语言使用大小写来决定常量、变量、类型、接口、结构或函数是否可以被外部包所调用。

  8为整型:int8/uint8,长度是1字节,取值范围:-128~127/0-255

  计算方法,2^8 / 2给负数部分,剩下分一个给0,最后的部分给整数部分。

  int16/uint16,int32/uint32,int64/uint64

  引用类型:slice(切片,特有类型),map(哈希表),chan(通道)

  类型的零值:就是默认值,int默认是0,bool默认是false,字符串默认是空字符串。

  全局变量不能省略var关键字,函数内的变量声明可以省略。 go语言中使用关键字func声明函数,关键字后面跟函数名、参数名以及返回值。

  Go虽然保留了指针,但不同点在于go不支持指针运算以及-运算符,而直接采用.选择符来操作指针目标对象的成员。

  if后面定义的变量,属于if语句的局部变量,只能在对应的if-else中使用,不能在外部使用。之间通过;分割语句。

  条件语句每次循环都会被重新检查,因此不建议在条件语句中使用函数,尽量提前计算好条件并以变量或常量代替。

  init: 一般为赋值表达式,给控制变量赋初值;一定在这里赋初值,不然出错 condition: 关系表达式或逻辑表达式,循环控制条件; post: 一般为赋值表达式,给控制变量增量或减量。

  2)判别赋值表达式init是否满足给定条件,若其值为真,满足循环条件,则执行循环体内语句,然后执行post,进入第二次循环,再判别condition;否则判断condition的值为假,不满足条件,就终止for循环,执行循环体外语句。

  关键字range会返回两个值,第一个值是当前迭代到的索引位置,第二个值是该位置对应元素值的一份副本。而不是返回对该元素的引用。

  switch语句默认情况下case最后自带break语句,匹配成功后就不会执行其他case,如果我们需要执行后面的case,可以使用fallthrough。

  记住ab是不同的类型,不能直接赋值,元素个数也是数组类型的一种。需要使用循环语句进行操作。 也可以不指定数组元素的个数。

  需要注意的是所有值类型变量在赋值或作为参数传递的时候将产生一次复制操作。如果将数组作为函数的参数类型,则在函数调用是将该参数将发生数据复制,函数体内无法修改数组的内容,因为函数体内操作是变量的一个副本。

  多维数组的声明如下所示,其中第一维度行的数量是可以省略的,使用...代替。

  切片是数组的一个引用,它会生成一个指向数组的指针,并通过切片长度关联到底层数组部分或者全部元素,还提供了一系列对数组的管理功能(append,copy),可以随时动态的扩充存储空间。属于变长数组,相当于C++的vector。创建切片的格式如下:

  下式表示,创建整型切片slice1,元素个数为5,元素初值为0,并预留10个元素的存储空间。

  对切片的访问方式可以通过下标的方式访问,也可以通过range关键字进行访问,同数组。

  使用切片做值函数传递时,以值的形式传递切片,由于切片的尺寸很小,所以成本很低,与切片关联的数据保存在底层数组中,不属于切片本身,所以切片的效率很高。slice的拷贝可以使用 s2 := s1[:],拷贝首元素省略,拷贝末尾元素也可以省略,:表示拷贝全部元素。

  map就是理解为C++里面的map,是key-value类型,也称为字典或者哈希表。

  使用“{ }”操作符对字典进行初始化操作,或者使用make()函数来创建字典。初始化或者创建后,就可以使用“=”操作符对字典动态的增添数据项了。

  map的查找:如果查找的key存在,则将key对应的value值赋予v,OK为true,反之,如果Key不存在,则v等于0,OK为false。

  delete()用于删除容器内的元素,也可以用于删除map内的键值对,例如:

  下面将从map1中删除键值为key1的键值对,如果key1这个键不存在,那么这个调用将什么也不会发生。

  key必须是支持==或!=比较运算的类型,不可以是函数、map或者slice

  记住每个map都必须进行单独的初始化操作。 使用make进行初始化操作。有几层map就需要使用几次make进行初始化操作。

  go中可以抛出一个panic的异常,然后在defer中通过recover捕获这个异常,然后正常处理

  因为defer是逆序执行的,在i变为4之后,闭包中指向的是i的地址,所以闭包中的i的值都是指向i=4的地址。

  go语言的method类似于一个函数,只是函数名前多了个绑定类型参数---receiver,基本格式如下:

  method中的receiver可以是内置类型、自定义类型、结构体或指针类型。

  不同包中大小写变量方法才有权限的区别,同一个包中可以访问private字段的内容,大写的public权限可以被不同包之间访问。type tz int,记住tz i和int i还是不同的类型,前面的i属于tz类型。要两者相加必须使用强制类型转换。

  接口是用来定义行为的类型,这些被定义的行为不由接口直接实现,而是通过方法由用户定义的类型实现。

  MethodByName()方法使用原对象的方法名name获取该方法的Value值,如果所访问的方法不存在,MethodByName会返回0.

  在go语言中传递给方法的参数要和方法定义的参数类型保持一致,为了处理变参这种复杂情况,传递给被调用方法的参数通常首先保存在一个Slice中,然后在复制到参数列表中。

  协程本质是一种用户态线程,不需要操作系统进行抢占性调度,而且在真正执行的时候中寄存于线程中。因此,协程系统开销极小,可以有效提高线程任务的并发性,避免高并发模式下线程并发的缺点。协程最大的优势在于轻量级,可以轻松创建上百万个而不是导致系统资源衰竭,系统最多能创建的进程、线程的数量却少的可怜。使用协程的优点是编程简单,结果清晰。但是缺点就是需要语言的支持,如果语言不支持,则需要用户在程序中自行进行调度。

  Channel的主要用途是在不同的Goroutine之间传递数据,它使用通道运算符-接收和发送数据,将一个数据发送(写入)至channe的方法是ch - value

  只需要看第二个bool返回值极客,如果返回值是false则表示Channel已关闭。

  在Goroutine间传输大量数据的时候,可以使用异步通道(Asynchronous-channel),类比消息队列的效果。

  异步Channel就是给Channel设定一个buffer值,在buffer未写满的情况下,不阻塞发送操作。buffer指的是被缓冲的数据对象的数量,而不是指内存大小。

返回顶部