Golang Array和以往认知的数组有很大的。
- 数组是同一种数据类型的固定长度的序列。
- 数组定义:var a[len] int,比如:var a [5]int,数组长度必须是常量,且类型的组成部分。一旦定义,长度不能变。
- 长度是数组类型的一部分,因此,var a[5] int和var a[10] int是不同的类型。
- 数组可以通过下标进行访问,下标从0开始,最后一个元素下标是:len-1。
for i := 0; i < len(a); i++ {
}
for index, v := range a {
}
- 访问越界,如果下标在数组合法范围之外,则触发访问越界,会panic。
- 数组是值类型,赋值和传参会复制整个数组,而不是指针。因此改变副本的值,不会改变本身的值。
- 至此"==","!="操作符,因为内存总是被初始化过的。
- 指针数组 [n] *T,数组指针 *[n]T。
1.数组初始化
- 一维数组
package main
import (
"fmt"
)
// 全局变量
var arr0 [5]int = [5]int{1, 2, 3} //未初始化元素值为0
var arr1 = [5]int{1, 2, 3, 4, 5}
var arr2 = [...]int{1, 2, 3, 4, 5, 6} //通过初始化值来确定数组长度
var str = [5]string{3: "hello world", 4: "tom"} //通过引号初始化元素
func main() {
//局部变量
a := [3]int{1, 2} //未初始化元素值为0
b := [...]int{1, 2, 3, 4, 5} //通过初始化值来确定数组长度
c := [5]string{3: "hello world", 4: "tom"} //通过引号初始化元素
d := [...]struct {
name string
age uint8
}{
{"user1", 10}, //可以省略元素类型
{"user2", 20}, //不要忘记最后的逗号
}
fmt.Println(arr0, arr1, arr2, str)
fmt.Println(a, b, c, d)
}
- 多维数组
package main
import "fmt"
//全局变量
var arr0 [5][3]int
var arr1 [2][3]int = [...][3]int{{1, 2, 3}, {4, 5, 6}}
func main() {
//局部变量
a := [2][3]int{{1, 2, 3}, {4, 5, 6}}
b := [...][2]int{{1, 2}, {3, 4}, {5, 6}} //第二维度不能为...
fmt.Println(arr0, arr1)
fmt.Println(a, b)
}
2. 数组值拷贝
数组是值类型,赋值和传参会复制整个数组,而不是指针。
值拷贝行为会造成性能问题,通常会建议使用slice,或数组指针。
package main
import "fmt"
func test(a [2]int) {
fmt.Printf("test-a:%p\n", &a)
a[0] = 100
a[1] = 100
}
func main() {
var a [2]int
fmt.Printf("main-a:%p\n", &a)
test(a)
fmt.Println(a)
}
因为值拷贝,地址不同,数据有没有修改。
3. 内置函数
内置函数len和cap都返回数组长度(元素数量)
package main
import "fmt"
func main() {
var arr [2]int = [2]int{1, 2}
fmt.Println(len(arr), cap(arr))
arr2 := [...][2]int{{1, 2}, {3, 4}} //二维数组,其中一维数组是它的元素
fmt.Println(len(arr2), cap(arr2))
}
注意:string底层是byte数组([]byte),len一个string类型的遍历,得到的是byte数组的长度。
4. 多维数组遍历
package main
import "fmt"
func main() {
arr2 := [...][2]int{{1, 2}, {3, 4}} //二维数组,其中一维数组是它的元素
//使用内置函数len
for i := 0; i < len(arr2); i++ {
for j := 0; j < len(arr2[i]); j++ {
fmt.Printf("arr2[%d][%d] = %d ", i, j, arr2[i][j])
}
}
fmt.Println()
//使用range
for index1, v1 := range arr2 {
for index2, v2 := range v1 {
fmt.Printf("arr2[%d][%d] = %d ", index1, index2, v2)
}
}
}
5. 数组拷贝和传参
使用指针传参。
6. 数组练习
-
求数组所有元素之和
package main
import (
"fmt"
"math/rand"
"time"
)
func sumArr(a [10]int) int {
sum := 0
for i, v := range a {
fmt.Printf("arr[%d]=%d ", i, v)
sum += v
}
fmt.Println()
return sum
}
func main() {
//随机数种子
rand.Seed(time.Now().Unix())
var b [10]int
for i := 0; i < len(b); i++ {
b[i] = rand.Intn(1000) //产生一个0到1000的随机数
}
sum := sumArr(b)
fmt.Println(sum)
}
- 找到数组中和为给定值的两元素下标
package main
import "fmt"
func myTest(arr [6]int, val int) {
for i := 0; i < len(arr); i++ {
for j := len(arr) - 1; j > i; j-- {
if arr[i]+arr[j] == val {
fmt.Printf("(%d, %d)", i, j)
}
}
}
}
func main() {
arr := [...]int{1, 2, 3, 4, 5, 6}
myTest(arr, 8)
}