Go 语言基础

一、标识符与关键字

go变量、常量、自定义类型、包、函数的命名方式必须遵循以下规则:

  1. 首字符可以是任意Unicode字符或下划线;
  2. 首字符之外的部分可以是Unicode字符、下划线或数字;
  3. 名字的长度无限制;

理论上名字里可以有汉字,甚至可以全是汉字,但实际中不要这么做

1.1 关键字

https://golang.google.cn/ref/spec

break,default,func,interface,select,case,defer,go,map,struct,chan,else,goto,package,switch,const,if,range,type,continue,for,import,return,fallthrough,var

1.2 常量

true,false,iota,nil

1.3 数据类型

int,int8,int16,int32,int64,uint,uint8,uint16,uint32,uint64,uintptr,float32,float64,complex128,complex64,bool,byte,rune,string,error

1.4 函数

make,len,cap,new,append,copy,close,delete,complex,real,imag,panic,recover

二、运算符与表达式

2.1 算数运算符

运算符描述
+相加
-相减
*相乘
/相除取商
%求余

2.2 关系运算符

运算符描述
==检查两个值是否相等,如果相等返回True否则返回False
!=检查两个值是否不相等,如果不相等返回True否则返回False
>检查左边值是否大于右边值,如果是返回True否则返回False
>=检查左边值是否大于或等于右边值,如果是返回True否则返回False
<检查左边值是否小于右边值,如果是返回True否则返回False
<=检查左边值是否小于或等于右边值,如果是返回True否则返回False

2.3 逻辑运算符

运算符描述
&&逻辑AND运算符;如果两边的操作数都是True,则为True,否则为False
||逻辑OR运算符;如果两边的操作数有一个是True,则为True,否则为False
!逻辑NOT运算符;如果条件为False,则为True,否则为True

2.4 位运算符

运算符描述
&参与运算的两数各对应的二进位相与(两位均为1才为1)
|参与运算的两数各对应的二进位相或(两位有一个为1就为1)
^参与运算的两数各对应的二进位相异或,当两对应的二进位相同时为0,不同是为1。作为一元运算符时表示按位取反,符号位也跟着变
<<左移n位就是乘以2的n次方。a<<b是把a的各二进位全部左移b位,高位丢弃,低位补0。通过左移,符号位可能会变
>>右移n位就是除以2的n次方。a>>b是把a的各二进位全部右移b位,正数高位补0,负数高位补1

2.5 赋值运算符

运算符描述
=简单的赋值运算符,将一个表达式的值赋给一个左值
+=相加后再赋值
-+相减后再赋值
*=相乘后再赋值
/=相除后再赋值
%=求余后再赋值
<<=左移后再赋值
>>=右移后再赋值
&=按位与后赋值
!=按位或后赋值
^=按位异或后赋值

2.6 优先级

分类描述关联性
Postfix后缀() [] -> . ++ - -Left to right
Unary单目+ - ! ~ ++ - - (type)* & sizeofRight to left
Multiplicative乘除* / %Left to right
Additive加减+ -Left to right
Shift移位<< >>Left to right
Relational关系< <= > >=Left to right
Equality相等== !=Left to right
Bitwise AND&Left to right
Bitwise XOR^Left to right
Bitwise OR|Left to right
Logical AND&&Left to right
Logical OR||Left to right
Assignment赋值= += -= *= /= %=>>= <<= &= ^= |=Right to left
Comma逗号运算符,Left to right

优先级由高到低
单目运算符 > 算术运算符 > 位移运算符 > 关系运算符 > 位运算符 > 逻辑运算符 > 赋值运算符
其中,将 “位运算符” 大分支 分为了 位移运算符 <<、>> 和 位运算符 |、^、&。

三、变量、常量、字面量

3.1 变量类型

类型go变量类型缺省格式符常用格式符
整型int,int8,int16,int32,int64%d%d,%b,%x
无符号整型uint,uint8,uint16,uint32,uint64%d,如果使用%#v就等周%#x%d,%b,%x
浮点型float32,float64%g%f,%e
复数complex128,complex64%g
布尔型bool%t%t
指针uintptr%p
引用map slice channel%v
字节byte%c%c,%d
任意字符rune%c%c,%d
字符串string%s%s
索引0元素地址slice%p
错误error%v

3.1.1 变量声明

1
2
3
4
5
6
7
8
9
10
11
//标准声明
var name string
var age int
var isOK bool

//批量声明
var (
name string
age int
isOK bool
)

3.1.2 变量初始化

  • 如果声明后未显式初始化,数值型初始化0,字符串初始化为空字符串,布尔型初始化为false,引用类型、函数、指针、接口初始化为nil

    1
    2
    3
    4
    5
    //比如以下几种变量初始化方式
    var a string="china"
    var a,b int=3,7
    var a="china" //类型推断,通过赋值数据类型反推变量类型
    var a,b="china",7
  • 函数内部的变量(非全局变量)可以通过:=声明并初始化

    1
    a:=3
  • 下划线表示匿名变量

    1
    _=2+4

    匿名变量不占命名空间,不会分配内存,因此可以重复使用

3.2 常量

常量在定义时必须赋值,且程序运行期间其值不能改变

1
2
3
4
5
6
7
8
9
10
11
12
13
//常量的几种常见赋值方式
const PI float32=3.14

const (
PI = 3.14
E = 2.7
)

const (
a = 100
b //值是100,跟上一行的值相同
c //值是100,跟上一行的值相同
)

常量中的iotaiota是go语言的常量计数器,只能在常量的表达式中使用

使用iota时只需要记住以下两点

1.iotaconst关键字出现时将被重置为0。
2.const中每新增一行常量声明将使iota计数一次(iota可理解为const语句块中的行索引)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
//常量的几种iota常见赋值方式
const (
a = iota //值是0
b //值是1
c //值是2
d //值是3
)

const (
a = iota //值是0
b //值是1
_ //值是2,不想要这个值可以使用匿名变量
d //值是3
)

const (
a = iota //值是0
b = 20 //值是20
c = iota //值是2
d //值是3
)

const ( //计算KB,MB,GB,TB
_ = iota
KB = 1 << (10 * iota) //iota=0 //<<移位操作,速度比乘除法快
MB = 1 << (10 * iota) //iota=1 //1<<3 相当于1*2*2*2 0001 -> 1000
GB = 1 << (10 * iota) //iota=2
TB = 1 << (10 * iota) //iota=3
)

const ( //赋值多个变量
a, b = iota + 1, iota + 2 //值是1,2 iota=0
c, d //值是2,3 iota=1
e, f //值是3,4 iota=2
)

3.3 字面量

字面量:没有出现变量名,直接出现了值。基础类型的字面量相当于是常量

3.3.1 整型字面量

整型字面量使用特定的字符序列表示具体的整型数值。常用于整型变量或常量的初始化。例如:

1
fmt.Printf("%d\n", 4)

3.3.2 浮点型字面量

浮点型字面量使用特定字符序列来表示一个浮点数值。它支持两种格式:一种是标准的数学小数形式,例如0.23;另一种是科学计数法,例如1E6。

1
fmt.Printf("%d\n", 0.23)

3.3.3 复数类型字面量

复数类型字面量使用特定的字符序列来表示复数类型的常量值。

1
fmt.Printf("%v\n", .4i) //0.4i

3.3.4 字符型字面量

Go的源码采用UTF-8的编码方式,UTF-8字符占用1~4个字节。Go的字符采用一对单引号包裹。

1
fmt.Printf("%d %d\n", '\u4f17', '众')

3.3.5 字符串字面量

Go中的字符串字面量表现形式是采用一对双引号或一对”`”包裹的字符字面量或其编码值。

1
fmt.Printf("Hello\nWorld\n!\n")

四、变量作用域

Go 语言 中的一个 变量(常量、类型或 函数)在程序中都有一定的作用范围,我们称之为作用域。Go 语言变量作用域分为局部作用域和全局作用域

4.1 局部变量

在函数内部声明/定义的变量叫局部变量,局部变量的作用域仅限于函数内部。在函数内部定义的变量,函数的 参数 和 返回值,if 和 for 结构内部使用的变量等都是局部变量。

下面的 main() 函数中使用到了局部变量 a、b、c

1
2
3
4
5
6
7
8
9
10
11
12
package main
import (
"fmt"
)
func main() {
//声明局部变量 a 和 b 并赋值
var a int = 3
var b int = 4
//声明局部变量 c 并计算 a 和 b 的和
c := a + b
fmt.Printf("a = %d, b = %d, c = %d\n", a, b, c)
}

运行结果如下所示:

1
a = 3, b = 4, c = 7

4.2 全局变量

在函数外部声明/定义的变量叫全局变量。如果首字母为大写,则作用域在整个程序有效,如果为小写,作用域在整个包中有效。

下面代码中,第 3 行定义了全局变量 c

1
2
3
4
5
6
7
8
9
10
11
package main
import "fmt"
var c int //声明全局变量
func main() {
var a, b int //声明局部变量
//初始化参数
a = 3
b = 4
c = a + b
fmt.Printf("a = %d, b = %d, c = %d\n", a, b, c)
}

运行结果如下所示:

1
a = 3, b = 4, c = 7

全局变量与局部变量名称可以相同,但是函数体内的局部变量会被优先考虑

1
2
3
4
5
6
7
8
9
package main
import "fmt"
//声明全局变量
var a float32 = 3.14
func main() {
//声明局部变量
var a int = 3
fmt.Printf("a = %d\n", a)
}

运行结果如下所示:

1
a = 3

五、注释与godoc

5.1 注释的形式

  • 单行注释,以//开头
  • 多行注释,连续多行以//开头 或者在段前使用/* 段尾使用*/
  • 多行注释之间不能出现空行
  • NOTE:引人注意,TODO:将来需要优化,Deprecated:变量或函数强烈建议不要使用
  • 注释行前加缩进即可写go代码
  • 包注释,在package xxx的上方。一个包只需要在一个地方写包注释,通常会专门写一个doc.go,里面只有一行package xxx和关于包的注释
  • 结构休注释,在type xxx struct上方
  • 函数注释,在func xxx()
  • 行注释,在行上方或右侧

5.2 go doc

go doc是go自带命令,可以打印附于Go语言程序实体上的文档

go doc package

例如:获取某个函数在某个包中的文档注释

1
go doc fmt Printf //会显示有关 fmt.Printf() 的使用说明。

5.3 godoc

godoc可以为项目代码导出网页版的注释文档

  1. 需要先安装:go install golang.org/x/tools/cmd/godoc@latest
  2. 本机启动http端口:godoc -http=:6060
  3. 用浏览器访问:http://127.0.0.1:6060 查看go标准库的文档
-------------本文结束感谢您的阅读-------------