Go 语言入门指南:基础语法和常用特性解析

99 阅读6分钟

go语言基础特性

golang源文件以.go结尾
golang代码格式很重要,可以用go fmt命令格式化包中的代码
golang使用nil表示空
golang是强类型语言
golang默认支持utf-8
golang中引用只是其中一种类型,而java除了基本类型全部作为引用
golang中每种类型都有该类型运行时的值(不指定初始值时都有默认值)
golang最小封装单位是包
golang支持接口的隐式实现
golang支持并发:goroutine
go build 编译源文件
go run 编译并运行源文件
go mod init path 初始化一个module
go代码由package(单个目录)组织, 每个package属于一个模块,每个源文件由package声明开始。 main包定义一个独立可执行的程序。

导入包: import ( "xxx/xxx" ... "xxx" ) 每个包对应独立的名称空间,同一个包下不同源文件可以直接引用。包所在目录路径的后缀是包的导入路径。包导入之后使用包名访问里面的内容。 包的初始化首先解决包级变量的依赖顺序,然后按照包级别变量声明出现的顺序依次初始化,每个包只初始化一次。

注释:

  1. // 2. /* */ (不允许嵌套注释,因为没什么用)

程序结构

类型声明语句:const, var, func, type(常量,变量,函数和类型) 变量声明:

  1. var 变量 类型 = 表达式 (类型和表达式可省略其中一个)
  2. 变量 := 表达式 (短变量声明,一种声明加初始化的语法,左边的变量必须有未声明过的新变量)
  3. 变量 := new(T) 创建T类型的匿名变量,返回* T的指针类型

常量声明: const ( xxx 类型= yyy ... xxx 类型= yyy ) 常量类型为bool,string或者数字类型 当不指定类型的时候常量根据初始化值变成无类型常量(无类型的bool,无类型的字符,无类型的字符串,无类型的数字),拥有更高的运算精度 无类型常量(字面量也是常量)参与计算时,会被隐式转换,没有指定转换类型时涉及到默认转换:int,float64,rune,complex128 常量间的所有算术运算、逻辑运算、比较运算结果都是常量 iota常量生成器,比如: const ( x = iota //x=0 y //y=1 z //z=2 ) y和z会依照x的规则做类似的初始化,iota在y,z中的值会依次递增

命名类型声明: type 类型名字 底层类型 具有相同底层类型的不同类型是不可以相互比较的,属于两个不同的概念。可以使用显式强制转换改变低层类型相同的两个类型

可以像python一样使用元组赋值:x, y = y, x

for循环两种形式:

  1. for 初始化;条件;后处理 (可以省略初始化和条件或者全部省略)
  2. for index,arg := range 数据区间 (通过range关键字产生索引和具体值,不使用index用下划线代替, 这两个也可以都省略,注意:这种形式的arg只能用于读,不能修改

for 和 if 初始化的变量作用域是整个语句块

数据类型

golang四类数据类型:基础类型(数字、字符串和布尔型)、复合类型(数组、结构体)、引用类型(指针、切片、字典、函数和通道)和接口类型

数字:整型,浮点型,复数 整型:int8, int16, int32, int64; uint8, uint16, uint32, uint64; int 和uint和cpu平台有关。 rune(unicode码点)= int32; byte = int8; uintptr(不定大小,用于存储指针) 运算符: ^表示XOR和NOT &^表示AND NOT

浮点数:float32和float64 复数: complex64和complex128(分别对应float32和float64)real和imag函数本别返回复数的实部和虚部,指定实部和虚部通过complex函数生成复数

注意:整型的字面量默认类型是int,浮点数的字面默认类型是float64

布尔型:true和false

字符串:不可改变的字节序列,索引和len以字节为单位计算 和java类似,字符串的内部值不会被修改,但是字符串变量会引用新的字符串 和java不同,字符串变量可以用== !=比较 字符串中可以通过转义用16进制或8进制表示任意字节(不得超过255),前者是\xhh,后者\ooo(h和o分别表示16进制和8进制的数字) golang中用...表示原生字符串 rune类型(int32)表示unicode码点(通过\uhhhh或\Uhhhhhhhh输入),一个码点对应一个字符 标准库中和字符串处理相关的包:bytes,strings,strconv(字符串和数字之间转换),unicode 大多数类型都定义了String()方法来转化成字符串

数组:长度固定的序列,golang的数组理解为一个变量有多个存储单元 var 名字 [长度]类型{初始值} 说明:

  1. 初始值可选,长度由‘...’代替表明数组长度由初始值推断
  2. 长度构成数组类型的一部分
  3. 初始值可以直接按顺序指定,也可以像map一样指定索引关键字如: symbol := [...]string{a:"1", b:"2"}
  4. 相同类型数组可以直接用== !=比较

Slice:变长序列,底层引用一个数组对象。slice由指针、长度、容量(从Slice开始位置到底层数组的结束位置)三部分构成。 说明:

  1. Slice类型的作用就是作为数组的引用,尽可能避免生成或拷贝新的数据
  2. Slice初始化语法类似于数组,它会隐式创建一个数组
  3. Slice类型只能和nil进行== !=比较
  4. 正确使用Slice需要关注底层数组是否重新分配

map:hash表的一个引用, key必须是== 可比较对象。 声明方法: var m = map[key]val{初始值}
说明:

  1. 初始值可选
  2. 可以直接引用未添加的键(默认值),使用delete(map,key)删除元素
  3. 由于map所有键都有默认值,因此索引操作还会返回一个bool以区分键是否存在
  4. map不能使用== !=比较

结构体:和数组一样属于复合类型 类型定义方法: type 名字 struct { xx 类型 构体成员Tag(如json:"x" ) yy 类型 构体成员Tag } 说明:

  1. 结构体类型和内部字段的出现顺序有关,相同类型可以合并
  2. 结构体类型内部不能包含自身类型字段,但是可以包含它的指针
  3. 声明结构体变量时可以按字段指定初始值如 point := Point{x : 1, y : 2}
  4. 如果结构体全部成员是可比较的,那么结构体本身可以==!=比较
  5. 字符串构体成员Tag可选,一般是key:"value"键值对序列。在结构体中字段类型后面额外加上反引号字符串表示标签,同一个标签可包含多个键值对用空格分开。

结构体匿名字段:必须是命名类型或者指向一个命名类型的指针;只能有一个同类型的匿名字段 结构体中不写字段名,只写它的类型就能直接访问匿名结构体字段的字段和导出方法,主要是方便访问 结构体匿名字段的导出性质取决于该类型的导出性