Go 语言 数组的使用
一、数组的介绍:
数组可以存放多个同一类型的数据。数组也是一种数据类型,在Go 中,数组是值类型
。
举个简单栗子:
package main
import "fmt"
func main() {
// 数组的快速使用
// 1. 定义一个数组
var array [6]float64
// 2.给数组每个元素赋值, 元素下标是从0开始的
array[0] = 1.0
array[1] = 2.0
array[2] = 3.0
array[3] = 4.0
array[4] = 5.0
array[5] = 6.0
// 3.遍历求出数组的总数量
total := 0.0
for i := 0; i < len(array); i++ {
total += array[i]
}
// 4.求出平均值
avg := fmt.Sprintf("%.2f", total / float64(len(array))) // 因为数组定义的是float类型, 运算时类型应相同
fmt.Printf("数组的总值:%v, 数组的平均值:%v", total, avg)
}
// 输出结果:
数组的总值:21, 数组的平均值:3.50
二、数组的定义、布局:
数组的定义:
var 数组名 [数组大小]数据类型
栗子如下:
var arrayName [6]int
// 定义一个数组, 名为 arrayName;数组大小为6;数据类型为int;
赋初值:数组名[下标] = 值
栗子如下:
arrayName[0] = 1
arrayName[1] = 2
…
// 赋初
值:数组名为:arrayName 下标为0, 赋值为1,以此类推
当我们定义完数组后,如果没有赋初值,那么数组各个元素都有默认值 0
举个栗子:
package main
import "fmt"
func main() {
// 当我们定义完数组后,如果没有赋初值, 那么数组各个元素的默认值都为0
var intArray[3]int
fmt.Println("数组的默认值:", intArray)
}
// 输出结果:
数组的默认值: [0 0 0]
数组在内存布局:
举个栗子:
package main
import "fmt"
func main() {
// 数组在内存中布局的讲解
var intArray[3]int64
intArray[0] = 10
intArray[1] = 20
intArray[2] = 30
fmt.Println(intArray)
fmt.Printf("intArray的地址是:%p; intArr[0] 地址是:%p; intArr[1] 地址是:%p; intArr[2] 地址是:%p; ",
&intArray, &intArray[0], &intArray[1], &intArray[2])
}
// 输出结果:
[10 20 30]
intArray的地址是:0xc00000e360; intArr[0] 地址是:0xc00000e360; intArr[1] 地址是:0xc00000e368; intArr[2] 地址是:0xc00000e370;
如图所示:
总结:
- 数组的地址可通过数组名来获取,
&intArray
; - 数组的
第一个元素地址,就是数组首地址
; - 数组的每个元素地址间隔,是根据
数组的类型决定
,比如int64占用8个字节等;
三、初始化数组方式:
package main
import "fmt"
func main() {
// 初始化数组的方式
// 第一种方式
var numArr01 [3]int64 = [3]int64{1, 2, 3}
fmt.Println("numArr01:", numArr01)
// 第二种方式
var numArr02 = [3]int64{4, 5, 6}
fmt.Println("numArr02:", numArr02)
// 第三种方式
var numArr03 = [...]int64{7, 8, 9}
fmt.Println("numArr03:", numArr03)
// 第四种方式, 指定数组中下标的数值
var numArr04 = [...]int64{1: 11, 0: 10, 2: 12}
fmt.Println("numArr04:", numArr04)
// 第五种方式, 类型推导
strArr05 := [...]string{1: "_", 0: "fe", 2: "cow"}
fmt.Println("strArr05:", strArr05)
}
// 输出内容如下:
numArr01: [1 2 3]
numArr02: [4 5 6]
numArr03: [7 8 9]
numArr04: [10 11 12]
strArr05: [fe _ cow]
四、数组for-range 的使用:
基本语法:
for index,value := range 数组 {
…
}
详细说明:
- 第一个 index 是数组的下标;
- 第二个 value 是该下标位置的值;
- 它们仅在for 循环内部使用的局部变量;
- 遍历数组时,若不想使用下标或值,可使用
_
进行忽略; - index、value 的命名不是固定的,通常起名为
index、value
;
举个栗子:
package main
import "fmt"
func main() {
// 使用for-range 结构 遍历数组
myArr := [...]string{"python", "java", "golang"}
for index, value := range myArr{
fmt.Printf("index=%v value=%v\n", index, value)
}
// 使用下划线, 进行忽略
for _, v := range myArr{
fmt.Printf("值为:%v\n", v)
}
}
// 输出结果:
index=0 value=python
index=1 value=java
index=2 value=golang
值为:python
值为:java
值为:golang
五、数组注意事项与细节:
- 数组是多个相同类型数据的组合,一个数组声明(定义)了,长度是固定的,不能动态变化:
package main
import (
"fmt"
)
func main() {
// 注意查看报错地方
var myArr [3]int
myArr[0] = 1
myArr[1] = 1.6 # 报错,因为myArr 定义的数据类型为int 而不是浮点型
myArr[2] = 2
myArr[3] = 3 # 报错,数据不能动态增长,因为myArr 数组长度为3,超出数组长度,不可动态生长
fmt.Println("myArr", myArr)
}
- 数组中的元素可以是
任意数据类型
,包括值类型和引用类型,但是不能混用
; - 数组创建后,若没有赋值,有默认值(零值):
package main
import "fmt"
func main() {
// 数组创建后, 没有赋值, 则使用的是数据类型的默认值
// int 类型的默认值:0
var intArr [3]int
// string 类型的默认值: ""
var strArr [3]string
// bool 类型的默认值: false
var boolArr [3]bool
fmt.Printf("int类型默认值:%v; string类型默认值:%v; bool类型的默认值:%v;",
intArr, strArr, boolArr)
}
// 输出结果:
int类型默认值:[0 0 0]; string类型默认值:[ ]; bool类型的默认值:[false false false];
- 使用数组的步骤:
a.声明数组时,此空间已被开辟;
b.给数组每个元素赋值(默认零值);
c.使用数组;
package main
import "fmt"
func main() {
// 使用数组步骤
// 1.声明数组, 此时空间已经开辟
var myArr [3]int
// 2.给数组赋值
myArr[0] = 10
myArr[1] = 20
myArr[2] = 30
// 3.使用数组
for index, value := range myArr{
fmt.Printf("index=%v value=%v\n", index, value)
}
}
- 数组的下标是从0开始;
- 数组下标必须在指定范围内使用,否则
报panic,数组越界
; - go的数组属于值拷贝,在默认情况下是值传递,因此会进行值拷贝。数组间不会相互影响;
package main
import "fmt"
func test(arr [3]int) {
arr[0] = 100
fmt.Println("test函数栈, arr=", arr)
}
func main() {
// go 中,数组属于值拷贝,数组间并不会相互影响
myArr := [3]int{10, 20, 30}
test(myArr)
fmt.Println("main 函数栈, arr=", myArr)
}
// 输出结果:
test函数栈, arr= [100 20 30]
main 函数栈, arr= [10 20 30]
流程图如下:
- 若在其它函数中,修改原数组的值,可以使用引用传递(指针方式):
package main
import "fmt"
func test(arr *[3]int) {
fmt.Printf("arr指针的地址是:%p\n", &arr)
(*arr)[0] = 666 // 注意 *arr 取到的就是myArr 数组; [0] 就是取到下标为0的空间
}
func main() {
// go 中 在其它函数中, 修改main函数中的数组的值
myArr := [3]int{11, 22, 33}
fmt.Printf("myArr数组的内存地址:%p\n", &myArr)
test(&myArr)
fmt.Println("main函数栈, myArr=", myArr)
}
//输出结果:
myArr数组的内存地址:0xc00000e360
arr指针的地址是:0xc000006030
main函数栈, myArr= [666 22 33]
流程图如下:
- 长度是数组类型的一部分,在
传递函数参数时,需要考虑数组长度
,如下是错误示例:
func test(arr []int) {
arr[0] = 100
fmt.Printf("test函数栈 arr=%v", arr)
}
func main() {
// 长度错误示例
var myArr = [...]int{11, 22 ,33}
test(myArr)
}
错误原因
:不能把[3]int 传递给[ ]int;
func test(arr [6]int) {
arr[0] = 100
fmt.Printf("test函数栈 arr=%v", arr)
}
func main() {
// 长度错误示例
var myArr = [...]int{11, 22 ,33}
test(myArr)
}
错误原因
:不能把[3]int 传递给 [6]int;