1.数组简介
数组是可以存放多个同一类型的数据。数组也是一种数据类型,在go中,数组是值类型。数组的长度也是数组类型的一部分,所以[2]int和[3]int属于不同的数据类型。
2.数组的长度也是类型的一部分
var arr1 [2]int
var arr2 [3]int
fmt.Printf("arr1数据类型:%T\narr2数据类型:%T\n", arr1, arr2)
结果:
arr1数据类型:[2]int
arr2数据类型:[3]int
3.数组的定义
语法:var 数组名 [数组大小]数据类型
示例: var a [5]int
var b [3]string
4.数组的初始化
4.1第一种方法
var intarr [3]int
intarr[0] = 1
intarr[1] = 2
intarr[2] = 3
fmt.Println(intarr)
var strarr [3]string
strarr[0] = "js"
strarr[1] = "java"
strarr[2] = "go"
fmt.Println(strarr)
结果:
[1 2 3]
[js java go]
4.2第二种方法
var intarr = [3]int{1, 2, 3}
var strarr = [3]string{"java", "go", "javascript"}
fmt.Println(intarr)
fmt.Println(strarr)
结果:
[1 2 3]
[java go javascript]
4.3第三种方法
[...]让编译器自动根据初始化值的个数自行推断数组的长度。
var intarr = [...]int{1, 2, 3, 4, 5, 6, 7, 8, 9}
var strarr = [...]string{"golang", "java", "php"}
fmt.Println(intarr)
fmt.Println(strarr)
fmt.Printf("intarr数据类型:%T\nstrarr数据类型:%T\n", intarr, strarr)
结果:
[1 2 3 4 5 6 7 8 9]
[golang java php]
intarr数据类型:[9]int
strarr数据类型:[3]string
4.4第四种方法
可以根据指定索引来初始化数组。
intarr := [...]int{1: 1, 0: 3, 2: 5, 9: 9}
fmt.Println(intarr)
strarr := [3]string{1: "a", 2: "b", 0: "c"}
fmt.Println(strarr)
结果:
[3 1 5 0 0 0 0 0 0 9]
[c a b]
5.数组的内存布局
数组是值类型,更改副本的值,不会改变本身的值。
var arr = [...]int{1, 2, 3, 4, 5, 6, 7, 8, 9}
arr2 := arr
arr[0] = 10
fmt.Println("arr=", arr)
fmt.Println("arr2=", arr2)
结果:
arr= [10 2 3 4 5 6 7 8 9]
arr2= [1 2 3 4 5 6 7 8 9]
内存分布
var intarr = [3]int{1, 2, 3}
fmt.Println(intarr)
fmt.Printf("intarr的地址=%p intarr[0]地址%p intarr[1]地址%p intarr[2]地址%p\n", &intarr, &intarr[0], &intarr[1], &intarr[2])
结果:
[1 2 3]
intarr的地址=0xc000014120 intarr[0]地址0xc000014120 intarr[1]地址0xc000014128 intarr[2]地址0xc000014130
有结果可以看出:
1.数组的地址可以通过数组名获取&intarr。
2.数组的第一元素的地址,就是数组的首地址。(intarr的地址=0xc000014120 intarr[0]地址0xc000014120)
3.数组的各个元素的地址间隔一句数组的类型决定,比如int64 -> 8 int32->4.
6.数组的遍历
6.1常规方法
var arr1 = [3]int{1, 2, 3}
for i := 0; i < len(arr1); i++ {
fmt.Println(arr1[i])
}
结果:
1
2
3
6.2for-range结构遍历
var arr1 = [3]int{1, 2, 3}
for index, value := range arr1 {
fmt.Printf("下标:%v--值:%v\n", index, value)
}
结果:
下标:0--值:1
下标:1--值:2
下标:2--值:3
7.数组使用的注意事项和细节
7.1数组是多个相同类型的组合,一个数组一旦声明/定义了。其长度是固定的,不能动态变化。
7.2数组中的元素可以是任意数据类型,包括值类型和引用类型,但是不能混用。
7.3数组创建后,如果没有赋值,则默认值(零值),数值默认0,字符串默认”“,bool默认false
var intarr [3]int
fmt.Println(intarr)
结果:
[0 0 0]
7.4使用数组步骤
1.声明数组并开辟空间
2.给数组各个元素赋值(默认零值)
3.使用数组
7.5数组的下标是从0开始的。
7.6数组下标必须在指定范围内使用,否则包panic:数组越界。
var arr [5]int 则有效下标为0-4
7.7go的数组类型属于值类型,在默认情况下是值传递,因此会进行只拷贝。数组间不会相互影响。
7.8如果想在其他函数中,去修改原来的数组,可以使用引用传递(指针传递)
func test(arr *[3]int) {
(*arr)[0]=12
}
7.9长度是数组的一部分,在传递函数参数时,需要考虑数组的长度。
8.练习
练习一求平均值
var arr = [...]int{98, 68, 78, 99, 98, 76, 90, 88}
var sum = 0
for i := 0; i < len(arr); i++ {
sum += arr[i]
}
fmt.Println(float32(sum) / float32(len(arr)))
结果:86.875
练习二:求最大值和对应的下标
var arr = [...]int{98, 68, 78, 99, 98, 76, 90, 88}
maxkey := 0
maxvalue := arr[0]
for key, value := range arr {
if value > maxvalue {
maxkey = key
maxvalue = value
}
}
fmt.Printf("最大值::%d,下标:%d\n", maxvalue, maxkey)
结果:最大值::99,下标:3
练习三:创建一个byte类型的数组,分别存放'A'-'Z',使用for循环遍历.
var mychars [26]byte
for i := 0; i < 26; i++ {
mychars[i] = 'A' + byte(i)
}
for i := 0; i < len(mychars); i++ {
fmt.Printf("%c", mychars[i])
}
结果:ABCDEFGHIJKLMNOPQRSTUVWXYZ
10.多维数组(了解)
var 数组变量名称 [元素数量][元素数量]T
var strarr = [3][2]string{
{"a", "b"},
{"b", "c"},
{"d", "e"},
}
fmt.Println(strarr)
fmt.Println(strarr[1])
for i := 0; i < len(strarr); i++ {
for j := 0; j < len(strarr[i]); j++ {
fmt.Println(strarr[i][j])
}
}
结果:
[[a b] [b c] [d e]]
[b c]
a
b
b
c
d
e
注意事项:注意多维数组只有第一层可以用[...]让编译器退到数组的长度
a:=[...][2]string{} 支持
a:=[3][...]string{} 不支持