Go语言数组和切片(Array,Slice)
数组是Go语言自带的数据结构,数组元素可以是任意的原始类型例如整形、字符串或者自定义类型。索引从0开始。
Go语言数组定义
数组声明语法:var variable_name [SIZE] variable_type
// 声明一个具有10个int类型元素的数组
var arr1 [10] int16
// 数组初始化
var arr2 = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
// 初始化时可以不指定数组大小
var arr3 = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
// 可以直接使用下标访问数组
arr3[1] = 20.0
// 声明一个不定长的数组
var arr4 []int
Go语言多维数组
Go 语言支持多维数组,以下为常用的多维数组声明方式:var variable_name [SIZE1][SIZE2]...[SIZEN] variable_type
// 初始化二维数组
arr = [3][4]int{
{0, 1, 2, 3} , /* 第一行索引为 0 */
{4, 5, 6, 7} , /* 第二行索引为 1 */
{8, 9, 10, 11}, /* 第三行索引为 2 */
}
/* 输出数组元素 */
for i = 0; i < 5; i++ {
for j = 0; j < 2; j++ {
fmt.Printf("a[%d][%d] = %d\n", i,j, a[i][j] )
}
}
Go语言切片
Go 语言切片是对数组的抽象。Go 数组的长度不可改变,而切片长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。
切片定义时不需要声明长度:var identifier []type
也可以使用make()
函数来创建切片:var slice1 []type = make([]type, len)
,或者简写为:slice1 := make([]type, len)
,其中 len 是数组的长度并且也是切片的初始长度。
切片初始化类似于数组:s :=[] int {1,2,3 }
可以对切片进行截取:
- s := arr[:]:初始化切片s,是数组arr的引用
- s := arr[startIndex:endIndex]:将arr中从下标startIndex到endIndex-1 下的元素创建为一个新的切片
- s := arr[startIndex:]:缺省endIndex时将表示一直到arr的最后一个元素
- s := arr[:endIndex]:缺省startIndex时将表示从arr的第一个元素开始
切片容量处理函数:
- len(x): 切片长度
- cap(x): 切片容量
一个切片在未初始化之前默认为 nil,长度为 0。
切片的维护(增删改)
定义切片后可以对切片中的元素增删改。
- 定义并初始化切片:
arr := []int{1, 2, 3}
- 向切片添加元素:
arr = append(arr, 5, 6)
- 修改切片元素:
arr[0] = 10
- 删除切片最后一个元素:
arr = arr[:len(arr) - 1]
- 从切片arr拷贝元素到arr_new:
copy(arr_new, arr)
Go语言数组作为参数传递方法
数组可以作为参数传递给函数,使用方法如下:
func main() {
var array = []int{1, 2, 3, 4, 5}
/* 未定义长度的数组只能传给不限制数组长度的函数 */
setArray(array)
/* 定义了长度的数组只能传给限制了相同数组长度的函数 */
var array2 = [5]int{1, 2, 3, 4, 5}
setArray2(array2)
}
func setArray(params []int) {
fmt.Println("params array length of setArray is : ", len(params))
}
func setArray2(params [5]int) {
fmt.Println("params array length of setArray2 is : ", len(params))
}
Go语言集合(Map)
Map 是一种无序的键值对的集合,是一种非常常用的数据结构。
定义Map
可以使用内建函数 make 也可以使用 map 关键字来定义 Map:
/* 声明变量,默认 map 是 nil */
var map_variable map[key_data_type]value_data_type
/* 使用 make 函数 */
map_variable := make(map[key_data_type]value_data_type)
如果不初始化 map,那么就会创建一个 nil map。nil map 不能用来存放键值对
map的维护
先看下面的实例
package main
import "fmt"
func main() {
var countryCapitalMap map[string]string /*创建集合 */
countryCapitalMap = make(map[string]string) // 初始化map
/* map插入key - value对,各个国家对应的首都 */
countryCapitalMap [ "France" ] = "Paris"
countryCapitalMap [ "Italy" ] = "罗马"
countryCapitalMap [ "Japan" ] = "东京"
countryCapitalMap [ "India " ] = "新德里"
/*使用键输出地图值 */
for country := range countryCapitalMap {
fmt.Println(country, "首都是", countryCapitalMap [country])
}
/*查看元素在集合中是否存在 */
captial, ok := countryCapitalMap [ "美国" ] /*如果确定是真实的,则存在,否则不存在 */
if (ok) {
fmt.Println("美国的首都是", captial)
} else {
fmt.Println("美国的首都不存在")
}
}
map的维护(增删改)
- 定义一个key和value都是string的map并初始化:
var map1 = map[string]string{"test": "test", "uu": "uu"}
- 往map中插入元素:
map1["insert"] = "insert"
- 修改map中key为test的元素:
map1["test"] = "modify"
- 删除map中key为test的元素:
delete(map1, "test")
Go语言结构体
类似于C语言中的结构,Go语言中提供结构体struct
来组合一系列具有相同类型或不同类型的数据。
结构体使用type
和struct
关键字来定义。
type struct_variable_type struct {
member definition;
member definition;
...
member definition;
}
定义完结构体之后,才能使用该结构体来声明该结构体类型的变量。未初始化的结构成员值为0或者空。
// 使用结构体定义变量的两种方法
variable_name := structure_variable_type {value1, value2...valuen} // 按照结构体定义顺序依次绑定初始值
// 使用key=>value方式指定特定的成员值
variable_name := structure_variable_type { key1: value1, key2: value2..., keyn: valuen}
下面是一个简单实例:
package main
import "fmt"
type User struct {
name string
age int
gender string
}
func main() {
uu := User{"uusama", 22, "unknown"}
tom := User{name: "tom", gender: "male"}
fmt.Println(uu) // {uusama 22 unknown}
fmt.Println(tom) // {tom 0 male}
}
访问结构体成员
可以使用点.
运算符对结构体的成员进行操作。
// 定义结构体
type User struct {
name string
age int
gender string
}
// 声明一个User结构变量
var User uu
// 访问结构成员
uu.name = "uusama"
fmt.Println(uu) // {uusama 0 ""}
结构体作为函数参数
结构体类型可以像其他基本数据类型一样作为参数传递给函数,需要注意的是结构体作为参数传递时是值传递,在函数内修改结构体时,并不能作用于形参。
package main
import "fmt"
// 定义结构体User
type User struct {
name string
age int
gender string
}
func addYear(user User, year int) User{
user.age += year
return user
}
func main() {
uu := User{"uusama", 22, "unknown"}
fmt.Println(uu) // {uusama 22 unknown}
var uuModify = addYear(uu, 10)
// 修改后 uu 并没有发生改变
fmt.Println(uu) // {uusama 22 unknown}
fmt.Println(uuModify) // {uusama 32 unknown}
}
结构体指针
类似于其他指针变量你可以定义指向结构体的指针,如:var user_pointer *User
。
- 可以通过
&
取得结构体的地址并赋值给结构指针 - 可以直接通过
.
访问结构指针中的成员变量 - 可以通过传递结构的指针作为函数参数,从而达到修改形参的目的
看下面的实例:
package main
import "fmt"
type User struct {
name string
age int
gender string
}
// 定义包含结构指针的函数
func addYear(user *User, year int) User{
user.age += year
return *user
}
func main() {
uu := User{"uusama", 22, "unknown"}
fmt.Println(uu) // {uusama 22 unknown}
// 声明结构指针
var uuPointer *User
// 将uu结构的地址赋值给结构指针
uuPointer = &uu
// 通过 . 访问结构指针指向结构的成员
uuPointer.age = 30
fmt.Println(uu) // {uusama 30 unknown}
fmt.Println(uuPointer) // &{uusama 30 unknown}
// 通过结构指针参数实现修改形参
uuModify := addYear(&uu, 10)
fmt.Println(uu) // {uusama 40 unknown}
fmt.Println(uuModify) // {uusama 40 unknown}
}
遍历利器:range
Go语言中 range 关键字用于 for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。
在数组和切片中它返回元素的索引和索引对应的值,在集合中返回 key-value 对的 key 值。
nums := []int{1, 2, 3, 4}
sum := 0
// 遍历切片nums,并求和
for _, num := range nums {
sum += num
}
fmt.Println("sum: ", sum) // sum: 10
m := map[string]int{"a": 10, "b": 15, "c": 20}
for key, value := range m {
println("key:", key, "value:", value)
}