变量的声明
var v1 int
var v2 string
var v3 [10]int // 数组
var v4 []int // 数组切片
var v5 struct{
f int
}
var v6 *int // 指针
var v7 map[string]int // map,key为string类型,value为int类型
var v8 func(a int) int
变量的声明和初始化
var v1 int = 10
var v2 = 10
v3 := 10
注意:出现在 := 左边的变量不应该是已经被声明过了的,否则会导致编译错误。
变量赋值
var v1 int
v1 = 10
交换变量i和变量j的值:i, j = j, i
匿名变量
func GetName() (firstName, lastName, nickName string) {
return "May", "Chan", "Chibi Maruko"
}
若只想获得nickName,则函数调用语句可以用如下方式编写:
_, _, nickName := GetName()
常量定义
const pi float64 = 3.14159265358979323846
const zero = 0.0 // 无类型浮点常量
注意:Go的常量可以限定类型,但并非必须,若没有指定类型,则为无类型常量。此外,常量的值可以设置为在编译期间运行的表达式,运行时才能得到结果的表达式是不能作为Go中常量定义的右值的。
预定义常量、枚举
Go语言预定义了这些常量:true、false、iota
iota,一个可以被编译器修改的常量,在每一个const关键字出现时被重置为0,在下一个const出现之前、每出现一个iota,则其所代表的数字会自动增1。
const (
V1 = iota
V2 = iota
V3 = iota
)
fmt.Println(V1)
fmt.Println(V2)
fmt.Println(V3)
上面的代码等同于:
const (
V1 = iota
V2
V3
)
fmt.Println(V1)
fmt.Println(V2)
fmt.Println(V3)
是因为,如果两个const的表达式是一样的,那么可以省略后一个的赋值表达式。
上面得到的结果是:
0
1
2
枚举,指一系列相关的常量。例如:
const (
Sunday
Monday
TuesDay
Wednesday
Thursday
Friday
Saturday
numberOfDays // 这个常量没有导出
)
以大写字母开头的常量在包外可见,上例中的munberOfDays为包内私有,其它符号则可被其它包访问。
数据类型
基础类型
- 布尔类型:bool
- 整型:int8、byte、int16、int、uint、uintptr等
- 浮点类型:float32、float64
- 复数类型:complex64、complex128
- 字符串:string
- 字符类型:rune
- 错误类型:error
符合类型:指针(pointer)、数组(array)、切片(slice)、字典(map)、通道(chan)、结构体(struct)、接口(interface)
数组的声明、元素访问,关键字range
array := [5] int {1,2,3,4,5}
for i := 0; i < len(array); i++ {
fmt.Println(i, array[i])
}
或者可以这么写:
array := [5] int {1,2,3,4,5}
for i, ch := range array {
fmt.Println(i, ch)
}
注意:Go语言提供的关键字range用于便捷的遍历容器中的元素,数组和字符串都支持。range表达式有两个返回值,一个是索引,一个是元素的值。
数组切片、数组切片的动态增减元素
var array [10]int = [10] int {1,2,3,4,5,6,7,8,9,10}
var mySlice1 []int = array[:] // array中的所有元素值
var mySlice2 []int = array[:5] // array中的前面五个元素值
var mySlice3 []int = array[5:] // array中下标为5及之后的所有元素值(下标从0开始)
以上就是基于数组创建数组切片的示例。下面介绍直接常见数组切片的示例:
mySlice1 := make([]int, 5) // 创建一个初始元素个数为5的数组切片,元素初始值为0
mySlice2 := make([]int, 5, 10) // 创建一个初始元素个数为5的数组切片,元素初始值为0,并预留10个元素的存储空间
mySlice3 := []int{1,2,3,4,5} // 直接创建并初始化包含5个元素的数组切片
当然,直接创建数组切片的其实也会有一个匿名数组被创建,只是不需要我们来操心了。
下面来说关于数组切片的动态增减元素的特性,数组切片相比数组多了一个叫做存储能力(capacity)的概念,即元素个数和分配的存储空间可以是两个不同的值。
mySlice := make([]int, 5, 10)
fmt.Println(len(mySlice)) // 返回数组切片中当前存储的元素个数
fmt.Println(cap(mySlice)) // 返回数组切片分配的空间大小
mySlice = append(mySlice, 1, 2, 3) // 在数组切片末端添加三个元素
mySlice = append(mySlice, mySlice2...) // 在数组切片末端添加另外一个数组切片,省略号必须要有
数组切片会自动处理存储空间不足的问题,如果追加内容之后元素个数会超出存储空间,则数组切片会自动分配一块足够大的内存。
下面是基于数组切片创建数组切片:
oldSlice := []int{1,2,3,4,5}
newSlice := oldSlice[:3] // 基于oldSlice的前3个元素构建新数组切片
选择的oldSlice元素范围甚至可以超过其所包含的元素个数,比如newSlice可以基于oldSlice的前6个元素创建,虽然oldSlice只包含5个元素。只要这个选择的范围不超过oldSlice存储能力,那么这个创建程序就是合法的。newSlice中超出的oldSlice元素的部分都会填上0。
内容复制。数组切片支持Go语言的另外一个内置函数copy(),用于将内容从一个数组切片复制到另一个数组切片。如果两个数组切片不是一样大,就会按其中较小的那个数组切片的元素个数进行复制。如下所示:
slice1 := []int{1,2,3,4,5}
slice2 := []nit{5,4,3}
copy(slice2, slice1) // 只会复制slice1的前3个元素到slice2中
copy(slice1, slice2) // 只会复制slice2的3个元素到slice1的前3个位置