共计 3326 个字符,预计需要花费 9 分钟才能阅读完成。
复合数据类型
数组
数组是具有相同类型的一组 已知编号 且长度固定 的数据项序列,这个序列可以是有序的也可以是无序的,组成数组的各个变量称为数组的元素。数组的长度必须是一个 非负整数的 常量(或常量表达式),数组长度也是数组类型的一部分,所以[4]int 和[10]int 不是同一种类型。
-
声明数组
声明数组需要指定元素的 数据类型 和数组长度(存储元素的数量)
// 声明一个长度为 20 的整型数组 var array [20]int
数组一旦声明,它的数据类型和数组长度都不能再更改了。所以,如果需要存储更多的元素,就必须先创建一个更长的数组,然后再把原来数组里的值复制到新数组里。
数组初始化时候,它的每个元素都被初始化为对应类型的零值。
-
使用数组字面量创建并初始化数组
// 声明一个包含 5 个元素的整型数组 // 用字面量初始化每个数据元素 array := [5]int{2,3,9,8,1}
-
使用 … 替代数组的长度(根据初始化时数组元素的数列确定数组长度)
// 声明一个整型数组 // 用具体值初始化每个元素 // 容量由初始化值的数量决定 array := [...]int{10,20,30,40,70}
-
使用索引值指定具体值创建并初始化数组
// 声明一个有 5 个元素的数组 // 用具体值初始化索引为 2 和 5 的元素 // 其余元素保持零值 array := [5]int{2:20, 5:10}
-
示例代码
// 声明数组(没有初始化)// 必须指定长度和类型 // 数组长度也是类型的一部分,即长度相同,数组类型才是相同 func main() {var array [3]bool var arrayInt [3]int var arrayString [4]string // 初始化 testArray := array testArray = [3]bool{true,false,true} testInt := arrayInt testInt = [...]int{10,20,30} // 语法糖,使用可变参数 "..." 替代声明数组长度 testString := arrayString testString = [...]string{"完","满","主","任"} idx := testString idx = [...]string{0:"小",1:"马",3:"哥"} // 根据索引初始化,未被初始化元素为零值(索引值 4)// 打印数组类型 fmt.Printf("%T %T\n",array,arrayInt) // 打印数组未初始化,默认打印类型零值(int 型:0,bool 型:false,string 型:"") fmt.Println(array,arrayInt,arrayString) // 打印初始化数组值 fmt.Println(testArray,testInt,testString,idx) } /* [3]bool [3]int [false false false] [0 0 0] [ ] [true false true] [10 20 30] [完 满 主 任] [小 马 哥] */
-
### 遍历数组
Go 语言数组通过下标(索引位置)来读取或者修改数组元素,下标(索引)从 0 开始,第一个元素为 0,则第 i 个元素 的索引值为 i-1
func main(){
//index 遍历
var array [3]string
array = [...]string{"钓","鱼","城"}
for i,v := range array{fmt.Println(i,v)
}
//range 遍历
var array1 [4]string
array1 = [...]string{"完","满","主","任"}
for i := 0 ; i<len(array1) ; i++ {fmt.Println(i,array1[i])
}
}
/*
0 钓
1 鱼
2 城
0 完
1 满
2 主
3 任
*/
for 循环中的条件非常重要:i < len (arr1),如果写成
i < = len(arr1) 的话会产生越界错误。元素的数目(长度或者数组大小)必须是 固定的并且在声明数组时就指定的(编译需要指定数组长度以便分配内存),数组长度最大为 2GB
可变参数 “…” 其实是 Go 语言的一种语法糖,它可以用于两种情况:
- 第一种表示可以接收或传递任意参数的意思(在前面的函数章节就已经提到了可变参数的概念)
-
第二种表示切片 (slice) 可以被打散进行传递(请看以下例子)
func main (){var strss= []string{ "钓", "鱼", "城", } var strss2= []string{ "完", "满", "主", "任", } strss = append(strss,strss2...) // 使用 append 函数连接字符串,... 代表可以传递任意数量的参数 fmt.Println(strss) } /* [钓 鱼 城 完 满 主 任] */
因为数组在内存分配中是连续的,要访问数组某个元素,可以 使用 [] 运算符并将其元素值更改
func main () {arr := [5]int{1, 2, 3, 4} // 按照索引初始化数组元素 arr[4] = 88 // 修改索引为 4 的值为 88 for i := 0; i < len(arr); i++ {fmt.Printf("Arrar at index %d is %d\n", i, arr[i]) } } /* Arrar at index 0 is 1 Arrar at index 1 is 2 Arrar at index 2 is 3 Arrar at index 3 is 4 Arrar at index 4 is 88 */
多维数组
多维数组用于管理 具有依赖关系的数据,例如坐标系等。
// 使用数组字面量来声明并初始化一个二维整型数组 array := [3][2]int{{2,5},{1,7},{9,8}} // 声明并初始化外层数组中索引为 0 和 1 的元素 array := [3][2]int{0:{2,5},1:{1,7}} // 声明并初始化外层数组和内层数组的单个元素 待补充,需要敲代码验证
值类型
在 Go 语言里,数组是一个类型值,意味着数组也可以像函数一样用在赋值操作中,变量名代表整个数组,因此,同样类型的数组可以赋值给另一个数组。
// 声明第一个包含 5 个元素的字符串数组
var array1 [5]string
// 声明第二个包含 5 个元素的字符串数组
// 用名字初始化数组
array2 := [5]string{"完","满","大","法","好"}
// 只有数据类型和数组长度都相同,才能进行复制,将 array2 的值复制到 array
array = array2
数组的值也可以是指针,声明一个所有元素都指针变量的数组,使用 * 运算符就可以访问元素指针所指向的值
// 声明一个包含 5 个元素的指向整数的数组
// 用整型指针初始化索引为 0 和 1 的数组元素
array := [5]*int{0: new int}
// 为索引为 0 和 1 的元素赋值
*array[0] = 10
*array[1] = 20
如果复制数组指针,只会复制数组的值,而不会复制指针所指向的值。
// 声明第一个包含 3 个元素的指向字符串类型的指针数组
var array1 [3]*string
// 声明第二个包含 3 个元素的指向字符串类型的指针数组
// 使用字符串指针初始化这个数组
array2 := [3]*string{new(string),new(string),new(string)}
// 使用名字为第二个数组元素赋值
*array2 [0] = "完"
*array2 [1] = "满"
*array2 [2] = "人"
// 复制完成后,两个数组指向同一组字符串 → ("完","满","人")
array1 = array2
### 练习(demo)
编写一个函数,实现数组元素并累加求和的功能
func main(){var a1 = [...]int{1,5,3,6,2}
sum := 0
for _,v := range a1{sum += v}
fmt.Println(sum)
}
/*
17
*/
编写一个函数,遍历数组求第 i 个元素和第 j 个元素相加和为 8 的值
func main(){var a1 = [...]int{1,5,3,6,2}
// 两层 for 循环求索引
for i:= 0 ; i<len(a1) ; i++ {for j:=0 ; j<len(a1) ; j++ {if a1[i] + a1 [j] == 8{ // 第 i 个元素值 + 第 j 个元素值 == 8
fmt.Printf("(%d, %d)\n",i,j)
}
}
}
}
/*
(1, 2)
(2, 1)
(3, 4)
(4, 3)
*/