Go语言自学笔记
Go语言变量
声明变量一般形式是使用var关键字,可一次声明多个变量
Go语言变量名由字母、数字、下划线组成,其中首字符不能为数字
var identifier type
var identifier1, identifier2 type
变量声明
第一种,指定变量类型,如果没有初始化,则变量默认为零值
var v_name v_type
v_name = value
第二种,根据值自行判定变量类型
var v_name = value
第三种,省略var,*:=*左侧如果没有声明新变量,就产生编译错误,所声明变量的类型由编译器自动推断
v_name := value
多变量声明
//类型相同多个变量, 非全局变量
var vname1, vname2, vname3 type
vname1, vname2, vname3 = v1, v2, v3
var vname1, vname2, vname3 = v1, v2, v3 // 和 python 很像,不需要显示声明类型,自动推断
vname1, vname2, vname3 := v1, v2, v3 // 出现在 := 左侧的变量不应该是已经被声明过的,否则会导致编译错误
// 这种因式分解关键字的写法一般用于声明全局变量
var (
vname1 v_type1
vname2 v_type2
)
值类型和引用类型
值类型的变量直接指向存在内存中的值,当将一个变量的值复制给另一个变量时,实际上是将内存中变量a的值进行了拷贝。可以通过&i来获取变量i的内存地址。值类型的变量的值存储在栈中
引用类型的变量存储的是i的值所在的内存地址(数字),或内存地址中第一个字所在的位置,这个内存地址称之为指针,这个指针实际上也被存在另外的某一个值中。同一个引用类型的指针指向的多个字可以是在连续的内存地址中(内存布局是连续的),这也是计算效率最高的一种存储形式;也可以将这些字分散存放在内存中,每个字都指示了下一个字所在的内存地址。当使用赋值语句时,只有引用被复制。
Go语言常量
常量的数据类型只能是布尔型、数字型、字符串型
定义格式
const identifier [type] = value
可以省略类型说明符号[type]
多个相同类型的声明可以简写为
const c_name1, c_name2 = value1, value2
常量也可以用作枚举
const (
Unknown = 0
Female = 1
Male = 2
)
常量可以用len(), cap(), unsafe.Sizeof()函数计算表达式的值。常量表达式中,函数必须是内置函数,否则编译不过
iota
特殊常量,可以认为是一个可以被编译器修改的常量
iota在const关键字出现时将被重置为0(const 内部的第一行之前),const 中每新增一行常量声明将使 iota 计数一次(iota 可理解为 const 语句块中的行索引)。
第一个 iota 等于 0,每当 iota 在新的一行被使用时,它的值都会自动加 1
const (
a = iota
b = iota
c = iota
)
Go语言运算符
算术运算符
假定A值为10,B值为20
关系运算符
逻辑运算符
位运算符
赋值运算符
其他运算符
Go语言条件语句
go语言除了常见的if,if…else…,if嵌套,switch,还有一个select语句,select 语句类似于 switch 语句,但是select会随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。
select语句
select {
case communication clause :
statement(s);
case communication clause :
statement(s);
/* 你可以定义任意数量的 case */
default : /* 可选 */
statement(s);
}
select 语句的语法:
-
每个 case 都必须是一个通信
-
所有 channel 表达式都会被求值
-
所有被发送的表达式都会被求值
-
如果任意某个通信可以进行,它就执行,其他被忽略。
-
如果有多个 case 都可以运行,Select 会随机公平地选出一个执行。其他不会执行。
否则:1. 如果有 default 子句,则执行该语句。 2. 如果没有 default 子句,select 将阻塞,直到某个通信可以运行;Go 不会重新对 channel 或值进行求值。
Go语言循环语句
for循环
语法
Go 语言的 For 循环有 3 种形式,只有其中的一种使用分号。
和 C 语言的 for 一样:
for init; condition; post { }
和 C 的 while 一样:
for condition { }
和 C 的 for(;😉 一样:
for { }
- init:一般为赋值表达式,给控制变量赋初值;
- condition:关系表达式或逻辑表达式,循环控制条件;
- post:一般为赋值表达式,给控制变量增量或减量。
嵌套循环
for [condition | ( init; condition; increment ) | Range]
{
for [condition | ( init; condition; increment ) | Range]
{
statement(s);
}
statement(s);
}
Go语言函数
函数是基本的代码块,用于执行一个任务。Go 语言最少有个 main() 函数。
函数定义格式
func function_name( [parameter list] ) [return_types] {
函数体
}
函数定义解析:
- func:函数由 func 开始声明
- function_name:函数名称,参数列表和返回值类型构成了函数签名。
- parameter list:参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,这个值被称为实际参数。参数列表指定的是参数类型、顺序、及参数个数。参数是可选的,也就是说函数也可以不包含参数。
- return_types:返回类型,函数返回一列值。return_types 是该列值的数据类型。有些功能不需要返回值,这种情况下return_types 不是必须的。
- 函数体:函数定义的代码集合。
函数返回:Go语言可以返回多个值
函数参数:
值传递:值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。
引用传递:引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。
Go语言数组
声明数组
Go 语言数组声明需要指定元素类型及元素个数,语法格式如下:
var variable_name [SIZE] variable_type
初始化数组
var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
// 通过字面量在声明数组的同时快速初始化数组
balance := [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
// 如果数组长度不确定,可以使用 ... 代替数组的长度,编译器会根据元素个数自行推断数组的长度
var balance = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
或
balance := [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
// 如果设置了数组的长度,可以通过指定下标来初始化元素
// 将索引为 1 和 3 的元素初始化
balance := [5]float32{1:2.0,3:7.0}
多维数组
var variable_name [SIZE1][SIZE2]...[SIZEN] variable_type
向函数传递数组
方法一:形参设定数组大小
void myFunction(param [10]int)
{
.
.
.
}
方法二:形参未设定数组大小
void myFunction(param []int)
{
.
.
.
}
指针
声明
var var_name *var-type
结构体
声明
type struct_variable_type struct {
member definition
member definition
...
member definition
}
Go语言切片
切片的使用与Python的列表相似
定义
var identifier []type
切片不需要说明长度或者使用**make()**函数来切片
var slice1 []type = make([]type, len)
// 也可以简写为
slice1 := make([]type, len)
// 也可以指定容量,其中capacity是可选参数
make([]T, length, capacity)
Go语言接口
/* 定义接口 */
type interface_name interface {
method_name1 [return_type]
method_name2 [return_type]
method_name3 [return_type]
...
method_namen [return_type]
}
/* 定义结构体 */
type struct_name struct {
/* variables */
}
/* 实现接口方法 */
func (struct_name_variable struct_name) method_name1() [return_type] {
/* 方法实现 */
}
...
func (struct_name_variable struct_name) method_namen() [return_type] {
/* 方法实现*/
}