go-数组 切片

本文详细介绍了Go语言中的数组和切片的概念、使用方法、内存布局、遍历、初始化、动态扩展以及注意事项。通过实例展示了如何创建、操作数组和切片,以及它们之间的区别。此外,还探讨了数组和切片在内存中的表示以及如何通过索引访问和修改元素。
摘要由CSDN通过智能技术生成

go-数组 切片

数组

  1. 数组可以存放多个同一类型数据,数组也是一种数据类型,在go中属于值类型
func main() {
	chicken := [6]float32{3, 5, 5.3, 2.1, 2.6, 6.3}
	var sum float32 = 0
	for _, temp := range chicken {
		sum += temp
	}
	fmt.Printf("sum: %v\n", sum)                       // sum: 24.3
	fmt.Printf("avg: %v\n", sum/float32(len(chicken))) // avg: 4.0499997
}

数组定义和内存布局

  1. 数组的地址可以通过数组名来获取&arr
  2. 数组的第一个元素的地址,就是数组的首地址(也不一定)
  3. 数组各个元素的地址间隔是依据数组的类型决定的,比如:int64是 -->8个字节
func main() {
	// 定义方式1
	var arr1 [3]int

	// arr1的地址: 0xc00012c018         arr1[0]:0xc00012c018    arr1[1]:0xc00012c020
	fmt.Printf("arr1的地址: %p\t arr1[0]:%p\t arr1[1]:%p\t \n", &arr1, &arr1[0], &arr1[1])

	fmt.Printf("arr1: %v\n", arr1) // arr1: [0 0 0]
	var arr4 []int
	fmt.Printf("arr4: %v\n", arr4) // arr4: []
	// 定义方式2
	var arr2 = [5]int{1, 2, 3}
	fmt.Printf("arr2: %v\n", arr2) // arr2: [1 2 3 0 0]
	var arr5 = []int{1, 2, 3}
	fmt.Printf("arr5: %v\n", arr5) // arr5: [1 2 3]
	// 定义方式3
	arr3 := []int{1, 2, 3, 4}
	fmt.Printf("arr3: %v\n", arr3) // arr3: [1 2 3 4]

	// arr3的地址: 0xc00011c030         arr3[0]:0xc000130020    arr3[1]:0xc000130028
	fmt.Printf("arr3的地址: %p\t arr3[0]:%p\t arr3[1]:%p\t \n", &arr3, &arr3[0], &arr3[1])

}

数组的使用

func main() {
	var score [5]float32
	for i := 0; i < 5; i++ {
		fmt.Println("请输入score : ")
		fmt.Scanln(&score[i])
	}

	fmt.Printf("score: %v\n", score)

	// 四种初始化数组方式
	var numArr1 [3]int = [3]int{1, 2, 3}
	fmt.Printf("numArr1: %v\n", numArr1) // numArr1: [1 2 3]

	var numArr2 = [3]int{3, 4, 5}
	fmt.Printf("numArr2: %v\n", numArr2) // numArr2: [3 4 5]

	var numArr3 = [...]int{5, 6, 7}
	fmt.Printf("numArr3: %v\n", numArr3) // numArr3: [5 6 7]

	var numArr4 = [...]int{1: 800, 0: 900, 3: 999} // numArr4: [900 800 0 999]
	fmt.Printf("numArr4: %v\n", numArr4)

	strArr5 := [...]string{1: "tom", 3: "jack", 2: "wxy"}
	fmt.Printf("strArr5: %q\n", strArr5) // strArr5: ["" "tom" "wxy" "jack"]

}

数组for-range遍历

  1. 第一返回值index是数组的下标
  2. 第二个value是该下标位置的值
  3. 他们都是仅在for循环内部可见的局部变量
  4. 遍历数组元素时,若不想使用下标index,可以用占位符_代替
  5. index和value的名称不是固定的,可以自定义
func main() {
	var nums = [5]int{1, 2, 3, 4, 5}
	fmt.Printf("nums: %v\n", nums)
	for i := 0; i < len(nums); i++ {
		fmt.Printf("%v\t", nums[i]) // 1       2       3       4       5
	}
	fmt.Println("")

	for index, v := range nums {
		fmt.Printf("v%v: %v\t", index, v) // v0: 1   v1: 2   v2: 3   v3: 4   v4: 5
	}
	fmt.Println("")
	for _, v := range nums {
		fmt.Printf("v: %v\t", v) // v: 1    v: 2    v: 3    v: 4    v: 5
	}
	fmt.Println("")
}

注意事项

  1. 数组是多个相同类型数据的组合,一个数组一旦声明/定义了,其长度是固定的,不能动态变化

  2. var arr []int,这时arr就是一个slice切片

  3. 数组中的元素可以是任何数据类型,包括值类型和引用类型,但是不能混用

  4. 数组创建后,若没有赋值,有默认值

    数值类型数组 默认值为0

    字符串数字 默认值为“”

    bool数组 默认值为 false

  5. 使用数组的步骤 ① 声明数组并开辟空间 ② 给数组各个元素赋值 ③ 使用数组

  6. 数组的下标是从0开始的

  7. 数组下标必须在指定范围内使用,否则会报panic:数组越界

  8. go的数组属于值类型,在默认情况下是值传递,因此会进行值拷贝

  9. 若想在其他函数中,去修改原来的数组,可以用引用传递方式(指针方式)

  10. 若不指定长度就是切片slice,若指定长度就是数组

  11. 长度是数组类型的一部分,在传递函数参数时,需要考虑数组的长度

func test1(arr [3]int) { // 数组是值传递, 长度要写上
	arr[1] = 10
}

func test2(arr []int) { // 切片是引用传递
	arr[1] = 10
}

func test3(arr *[3]int) { // 引用指针传递
	(*arr)[1] = 20
}

func main() {
	var arr [3]int = [3]int{1, 2, 3} // 数组
	test1(arr)
	fmt.Printf("arr: %v\n", arr) // arr: [1 2 3]

	var arr2 []int = []int{1, 2, 3, 4, 5} // 切片
	test2(arr2)
	fmt.Printf("arr2: %v\n", arr2) // arr2: [1 10 3 4 5]

	var arr3 = [3]int{1, 2, 3}
	test3(&arr3)                   // 引用指针传递
	fmt.Printf("arr3: %v\n", arr3) // arr3: [1 20 3]
}

实例

func main() {
	// 1. 创建一个byte类型的26个元素的数组,存放A-Z
	var char [26]byte
	for i := 0; i < 26; i++ {
		char[i] = 'A' + byte(i)
	}
	// char: [A B C D E F G H I J K L M N O P Q R S T U V W X Y Z]
	fmt.Printf("char: %c\n", char)

	// 2. 求出一个数组的最大值及其下标
	var arr [5]float64 = [...]float64{1.5, 3.6, 10.5, 6.3, 7.2}
	var maxNum float64 = 0
	var maxNumIndex int = 0
	for index, value := range arr {
		if maxNum < value {
			maxNum = value
			maxNumIndex = index
		}
	}
	fmt.Printf("maxNum: %v\n", maxNum)           // maxNum: 10.5
	fmt.Printf("maxNumIndex: %v\n", maxNumIndex) // maxNumIndex: 2

	// 3. 求数组的总和 平平均值
	var sum float64 = 0
	var avg float64 = 0
	for _, value := range arr {
		sum += value
	}
	avg = sum / float64(len(arr))
	fmt.Printf("sum: %v\n", sum) // sum: 29.099999999999998 存在错误
	fmt.Printf("avg: %v\n", avg) // avg: 5.819999999999999 存在错误

	// 4. 数组反转
	var arrNum [5]int
	for i := 0; i < 5; i++ {
		rand.Seed(time.Now().UnixNano())
		arrNum[i] = rand.Intn(20)
	}
	fmt.Printf("arrNum: %v\n", arrNum)
	for i, j := 0, len(arrNum)-1; i < j; i++ {
		temp := arrNum[i]
		arrNum[i] = arrNum[j]
		arrNum[j] = temp
		j--
	}
	fmt.Printf("arrNum: %v\n", arrNum)
}

切片

  1. 切片的英文是slice

  2. 切片是数组的一个引用,因此切片是引用类型,在进行传递时,遵守引用传递的机制

  3. 切片的使用和数组类似,遍历切片、访问切片的元素和求切片的长度len(slice)都一样

  4. 切片的长度是可以变化的,因此切片是一个可以动态变化的数组

  5. 切片的定义基本语法:

    var 变量名 []数据类型

func main() {

	var intArr [5]int = [5]int{1, 2, 3, 4, 5}
	// 引用intArr数组的下标区间[1,3)的值 1是起始下标,3是终止下标,不包含3
	sliceArr := intArr[1:3]
	fmt.Printf("sliceArr: %v\n", sliceArr) // sliceArr: [2 3]
	fmt.Println("len: ", len(sliceArr))    // len:  2
	fmt.Println("cap: ", cap(sliceArr))    // cap:  4
	/*
		func cap(v Type) int
			内建函数cap返回 v 的容量,这取决于具体类型:
				数组:v中元素的数量,与 len(v) 相同
				数组指针:*v中元素的数量,与len(v) 相同
				切片:切片的容量(底层数组的长度);若 v为nil,cap(v) 即为零
				信道:按照元素的单元,相应信道缓存的容量;若v为nil,cap(v)即为零


		func append(slice []Type, elems ...Type) []Type
			内建函数append将元素追加到切片的末尾。若它有足够的容量,其目标就会重新切片以容纳新的元素。
			否则,就会分配一个新的基本数组。append返回更新后的切片,因此必须存储追加后的结果。

			slice = append(slice, elem1, elem2)
			slice = append(slice, anotherSlice...)
			slice = append([]byte("hello "), "world"...)
	*/

	var slice []int = []int{1, 2, 3, 4, 5}
	slice = append(slice, int(6), int(7))
	fmt.Printf("slice: %v\n", slice)           // slice: [1 2 3 4 5 6 7]
	fmt.Printf("len(slice): %v\n", len(slice)) // len(slice): 7
	fmt.Printf("cap(slice): %v\n", cap(slice)) // cap(slice): 10
	slice = append(slice, sliceArr...)
	fmt.Printf("slice: %v\n", slice)           // slice: [1 2 3 4 5 6 7 2 3]
	fmt.Printf("len(slice): %v\n", len(slice)) // len(slice): 9
	fmt.Printf("cap(slice): %v\n", cap(slice)) // cap(slice): 10
}

切片的内存布局

  1. slice的确是一个引用类型

  2. slice从底层来说,其实是一个数据结构,(struct 结构体)

    Type slice struct {

    ptr *[2]int

    len int

    cap int

    }

image-20220420111234324
func main() {

	var intArr [5]int = [5]int{1, 2, 3, 4, 5}
	// 引用intArr数组的下标区间[1,3)的值 1是起始下标,3是终止下标,不包含3
	sliceArr := intArr[1:3]
	fmt.Printf("sliceArr: %v\n", sliceArr) // sliceArr: [2 3]
	fmt.Println("len: ", len(sliceArr))    // len:  2
	fmt.Println("cap: ", cap(sliceArr))    // cap:  4

	fmt.Printf("&sliceArr: %p\n", &sliceArr)       // &sliceArr: 0xc0000a4018
	fmt.Printf("&sliceArr[0]: %p\n", &sliceArr[0]) // &sliceArr[0]: 0xc0000aa038 存放地址
	fmt.Printf("&intArr[1]: %v\n", &intArr[1])     // &intArr[1]: 0xc0000aa038  本身地址
	sliceArr[0] = 10
	fmt.Printf("sliceArr: %v\n", sliceArr) // sliceArr: [10 3]  改变
	fmt.Printf("intArr: %v\n", intArr)     // intArr: [1 10 3 4 5]  跟着改变
	/*
		func cap(v Type) int
			内建函数cap返回 v 的容量,这取决于具体类型:
				数组:v中元素的数量,与 len(v) 相同
				数组指针:*v中元素的数量,与len(v) 相同
				切片:切片的容量(底层数组的长度);若 v为nil,cap(v) 即为零
				信道:按照元素的单元,相应信道缓存的容量;若v为nil,cap(v)即为零


		func append(slice []Type, elems ...Type) []Type
			内建函数append将元素追加到切片的末尾。若它有足够的容量,其目标就会重新切片以容纳新的元素。
			否则,就会分配一个新的基本数组。append返回更新后的切片,因此必须存储追加后的结果。

			slice = append(slice, elem1, elem2)
			slice = append(slice, anotherSlice...)
			slice = append([]byte("hello "), "world"...)
	*/

	var slice []int = []int{1, 2, 3, 4, 5}
	slice = append(slice, int(6), int(7))      // 在后面添加m个元素
	fmt.Printf("slice: %v\n", slice)           // slice: [1 2 3 4 5 6 7]
	fmt.Printf("len(slice): %v\n", len(slice)) // len(slice): 7
	fmt.Printf("cap(slice): %v\n", cap(slice)) // cap(slice): 10
	slice = append(slice, sliceArr...)         // 在后面添加slice
	fmt.Printf("slice: %v\n", slice)           // slice: [1 2 3 4 5 6 7 2 3]
	fmt.Printf("len(slice): %v\n", len(slice)) // len(slice): 9
	fmt.Printf("cap(slice): %v\n", cap(slice)) // cap(slice): 10

	fmt.Printf("&slice: %p\n", &slice)       // &slice: 0xc00000c048
	fmt.Printf("&slice[0]: %p\n", &slice[0]) // &slice[0]: 0xc00001e050
	fmt.Printf("&slice[1]: %p\n", &slice[1]) // &slice[1]: 0xc00001e058 与上面相差8个字节
	fmt.Printf("slice[1]: %v\n", slice[1])   // slice[1]: 2
}

切片的三种方式

  1. 定义一个切片,然后让切片去引用一个已经创建好的数组

  2. 通过make来创建切片

    var 切片名 []type = make([]type, len, cap)

    参数说明:type是数据类型

    ​ len是大小

    ​ cap是指定切片容量,可选,若分配了cap,则需要cap >= len

  3. 定义一个切片,直接指定具体数组,使用原理类似make方式

func main() {
	// 1. 引用一个数组 指向所引向的地址空间 通过数组也能访问切片
	var arr [5]int = [5]int{1, 2, 3, 5, 7}
	var slice1 []int = arr[0:5]
	slice2 := arr[0:5]
	fmt.Printf("slice1: %v\n", slice1) // slice1: [1 2 3 5 7]
	fmt.Printf("slice2: %v\n", slice2) // slice2: [1 2 3 5 7]

	// 2. make 自己开辟一个地址空间
	var slice3 []int = make([]int, 5, 10)
	fmt.Printf("slice3: %v\n", slice3) // slice3: [0 0 0 0 0]
	slice3 = []int{3: 33}
	fmt.Printf("slice3: %v\n", slice3) // slice3: [0 0 0 33]
	slice3[1] = 11
	slice3[0] = 22
	slice3[3] = 55
	fmt.Printf("slice3: %v\n", slice3)           // slice3: [22 11 0 55]
	fmt.Printf("len(slice3): %v\n", len(slice3)) // len(slice3): 4
	fmt.Printf("cap(slice3): %v\n", cap(slice3)) // cap(slice3): 4
	// (1) 通过make方式创建切片可以指定切片的大小和容量
	// (2) 若没有给切片的各个元素赋值,那么就会使用默认值int float ... 0 0
	// (3) 通过make方式创建的切片对应的数组是由make底层维护,对外不可见,即只能通过slice去访问各个元素

	// 3. 直接指定具体数组
	var slice4 []int = []int{11, 33, 55, 66}
	fmt.Printf("slice4: %v\n", slice4)           // slice4: [11 33 55 66]
	fmt.Printf("len(slice4): %v\n", len(slice4)) // len(slice4): 4
	fmt.Printf("cap(slice4): %v\n", cap(slice4)) // cap(slice4): 4
}

切片的遍历

func main() {
	var slice []int = []int{1, 2, 3, 4, 5}
	// 1. 遍历方式for
	// slice[i]: 1     slice[i]: 2     slice[i]: 3     slice[i]: 4     slice[i]: 5
	for i := 0; i < len(slice); i++ {
		fmt.Printf("slice[i]: %v\t", slice[i])
	}
	fmt.Println("")
	// 2. 遍历方式for-range
	// value0: 1       value1: 2       value2: 3       value3: 4       value4: 5
	for index, value := range slice { // index 可以用 占位符 代替
		fmt.Printf("value%v: %v\t", index, value)
	}
	fmt.Println("")
}

注意事项

  1. 切片初始化时,var slice = arr[startIndex : endIndex]

    从arr数组下标为startIndex,取到下标为endIndex的元素(不含arr[endIndex])

    1. var slice = arr[0:end] 可以简写成 var slice = arr[:end]
    2. var slice = arr[start:len(arr)] 可以简写成 var slice = arr[start:]
    3. var slice = arr[0:len(arr)] 可以简写成 var slice = arr[:]
  2. cap是内置函数,用于统计切片的容量,即最大可以存放多少个元素

  3. 切片定义后,还不能使用,因为本身是一个空的,需要让其引用到一个数组,或者make一个空间供切片来使用

  4. 切片可继续切片var slice2 = slice1[1:3]

  5. append内置函数的使用

    1. 切片append操作的本质就是对数组扩容
    2. go底层会创建一下新的数组newArr(安装扩容后大小)
    3. 将slice原来包含的元素拷贝到新的数组newArr
    4. slice重新引用到newArr
    5. 注意:newArr是在底层来维护的,程序员不可见
image-20220420143257791
  1. copy内置函数
func main() {
	// 1 - 4 案例
	var arr [5]int = [...]int{1, 2, 3, 4, 5}
	var slice1 []int = arr[2:]
	var slice2 = slice1[:]
	fmt.Printf("slice1: %v\n", slice1) // slice1: [3 4 5]
	fmt.Printf("slice2: %v\n", slice2) // slice2: [3 4 5]
	slice2[1] = 999
	fmt.Printf("arr: %v\n", arr)       // arr: [1 2 3 999 5]
	fmt.Printf("slice1: %v\n", slice1) // slice1: [3 999 5]
	fmt.Printf("slice2: %v\n", slice2) // slice2: [3 999 5]

	// 5 append
	var slice []int = []int{100, 200, 300}
	slice = append(slice, 400)
	fmt.Printf("slice: %v\n", slice) // slice: [100 200 300 400]
	slice = append(slice, 500, 600)
	fmt.Printf("slice: %v\n", slice) // slice: [100 200 300 400 500 600]
	slice = append(slice, slice2...) // slice: [100 200 300 400 500 600 3 999 5]
	fmt.Printf("slice: %v\n", slice)

	// 6. copy 拷贝, 拷贝的两个切片是相互独立,相互不影响,
	// 			对其中一个修改,不会影响其他的修改
	var newSlice1 []int = make([]int, 5)
	updateNum := copy(newSlice1, slice)
	fmt.Printf("newSlice1: %v\n", newSlice1) // newSlice: [100 200 300 400 500]
	fmt.Printf("updateNum: %v\n", updateNum) // updateNum: 5
	var newSlice2 []int = make([]int, 15)
	updateNum = copy(newSlice2, slice)
	fmt.Printf("newSlice2: %v\n", newSlice2) // newSlice2: [100 200 300 400 500 600 3 999 5 0 0 0 0 0 0]
	fmt.Printf("updateNum: %v\n", updateNum) // updateNum: 5
	newSlice1[1] = 999999
	fmt.Printf("newSlice1: %v\n", newSlice1) // newSlice1: [100 999999 300 400 500] 相互独立
	fmt.Printf("slice: %v\n", slice)         // slice: [100 200 300 400 500 600 3 999 5]
}
  1. 切片是引用类型,所以在传递时,遵守引用传递机制

string和slice

  1. string底层是一个byte数组,因此string也可以进行切片处理

  2. string和切片在内存的形式

    image-20220420145712055
  3. str[1] = ‘a’ 方式来修改字符串

  4. 若需要修改字符串,可以先将string – > []byte 或者 []rune --> 修改 --> 重新转成 string

  5. string属于值类型

func main() {

	// 1. 认识
	str := "hello@go"
	var slice = str[5:]
	fmt.Printf("slice: %v\n", slice)      // slice: @go
	fmt.Printf("slice Type: %T\n", slice) // slice Type: string

	// 2. 修改转变
	var sliceByte []byte = []byte(str)
	fmt.Printf("sliceByte: %c\n", sliceByte) // sliceByte: [h e l l o @ g o]
	sliceByte[1] = 'A'
	fmt.Printf("str: %v\n", str)             // str: hello@go 不会改变
	fmt.Printf("slice: %v\n", slice)         // slice: @go    不会改变
	fmt.Printf("sliceByte: %c\n", sliceByte) // sliceByte: [h A l l o @ g o]  改变
	str = string(sliceByte)
	fmt.Printf("str: %v\n", str)             // str: hAllo@go  改变
	fmt.Printf("slice: %v\n", slice)         // slice: @go     不会改变
	fmt.Printf("sliceByte: %c\n", sliceByte) // sliceByte: [h A l l o @ g o]

	// 3. 处理中文
	str1 := "你好 大连 hello DL"
	var sliceRune []rune = []rune(str1)
	fmt.Printf("sliceRune: %c\n", sliceRune) // sliceRune: [你 好   大 连   h e l l o   D L]
	sliceRune[0] = '您'
	str1 = string(sliceRune)
	fmt.Printf("str1: %v\n", str1)           // str1: 您好 大连 hello DL
	fmt.Printf("sliceRune: %c\n", sliceRune) // sliceRune: [您 好   大 连   h e l l o   D L]
}

练习

func main() {
	var n int = 0
	fmt.Print("请输入 n : ")
	fmt.Scanln(&n)
	slice := flib(n)
	fmt.Printf("slice: %v\n", slice)
}

func flib(n int) (slice []int) {
	if n == 0 {
		slice = []int{1}
		return
	}
	if n == 1 {
		slice = []int{1, 1}
		return
	}
	slice = make([]int, n+1)
	slice[0] = 1
	slice[1] = 1
	for i := 2; i <= n; i++ {
		slice[i] = slice[i-1] + slice[i-2]
	}
	return
}

数组排序

冒泡排序

// 冒泡排序
func bubbleSort(arr *[8]int) {
	var flag bool = true
	for i := len(arr); i > 0 && flag; i-- {
		flag = false
		for j := 1; j < i; j++ {
			if arr[j] < arr[j-1] {
				temp := arr[j]
				arr[j] = arr[j-1]
				arr[j-1] = temp
				flag = true
			}
		}
		if flag {
			fmt.Printf("%v : arr: %v\n", len(arr)-i+1, arr)
		}
	}
}

顺序查找

// 顺序查找
func find(arr [8]int, target int) int {
	for index, value := range arr {
		if value == target {
			return index
		}
	}
	return -1
}

二分查找

// 二分查找
func binFind(arr [8]int, target int) int {
	// 1. 排序
	bubbleSort(&arr)
	// 2. 查找
	left := 0
	right := len(arr) - 1
	for left < right {
		mid := (right-left)>>1 + left
		if arr[mid] == target {
			return mid
		} else if arr[mid] > target {
			right = mid - 1
		} else {
			left = mid + 1
		}
	}
	return -1
}

// 二分查找-递归
func binaryFind(arr [8]int, left int, right int, target int) int {
	if left > right {
		return -1
	}
	mid := (right-left)>>1 + left
	if arr[mid] > target {
		mid = binaryFind(arr, left, mid-1, target)
	} else if arr[mid] < target {
		mid = binaryFind(arr, mid+1, right, target)
	} else {
		return mid
	}
	return mid
}
// 主函数
func main() {
	var arr [8]int = [...]int{2, 99, 7, 6, 9, 1, 3, 50}
	bubbleSort(&arr)

	var arr1 [8]int = [...]int{2, 99, 7, 6, 9, 1, 3, 50}
	index := find(arr1, 99)
	if index == -1 {
		fmt.Println("No Find")
	} else {
		fmt.Printf("Find index: %v\n", index)
	}

	index = binFind(arr1, 6)
	if index == -1 {
		fmt.Println("No BinFind")
	} else {
		fmt.Printf("BinFind index: %v\n", index)
	}

}

二维数组

二维数组介绍

func main() {
	var arr [3][5]int = [3][5]int{{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}, {11, 12, 13, 14, 15}}
	fmt.Printf("arr: %v\n", arr)
	for i := 0; i < len(arr); i++ {
		for j := 0; j < len(arr[i]); j++ {
			fmt.Printf("%v\t", arr[i][j])
		}
		fmt.Println("")
	}

	fmt.Printf("&arr[0]: %p\n", &arr[0])       // &arr[0]: 0xc000022080  相差40个字节,5 * 8 = 40
	fmt.Printf("&arr[1]: %p\n", &arr[1])       // &arr[1]: 0xc0000220a8
	fmt.Printf("&arr[0][0]: %p\n", &arr[0][0]) // &arr[0][0]: 0xc0000c0000 与 &arr[0] 相同
	fmt.Printf("&arr[0][1]: %p\n", &arr[0][1]) // &arr[0][1]: 0xc000022088 与 &arr[0][0] 相差8个字节
  
  
  	// 四种初始化方式

	// 1.
	var arr1 [2][3]int = [2][3]int{{1, 2, 3}, {4, 5, 6}}
	fmt.Printf("arr1: %v\n", arr1)

	// 2.
	var arr2 [2][3]int
	fmt.Printf("arr2: %v\n", arr2)

	// 3.
	var arr3 = [...][3]int{{1, 2, 3}, {3, 4, 5}, {5, 6, 7}}
	fmt.Printf("arr3: %v\n", arr3)

	// 4.
	var arr4 = [2][3]int{{1, 2, 3}, {1, 2, 3}}
	fmt.Printf("arr4: %v\n", arr4)

	// 5.
	arr5 := [2][3]int{{1, 2, 3}, {1, 2, 3}}
	fmt.Printf("arr5: %v\n", arr5)

	// 下面是切片
	arr6 := [][]int{{1, 2, 3}, {4, 5}, {11, 22, 33, 44, 55}}
	fmt.Printf("arr6: %v\n", arr6)
}
image-20220420213021097

二维数组遍历

func main() {
	var arr = [2][3]int{{1, 2, 3}, {11, 22, 33}}

	for i := 0; i < len(arr); i++ {
		for j := 0; j < len(arr[i]); j++ {
			fmt.Printf("arr[i][j]: %v\t", arr[i][j])
		}
		fmt.Println("")
	}

	for _, value := range arr {
		for _, val := range value {
			fmt.Printf("val: %v\t", val)
		}
		fmt.Println("")
	}
}

实例

func main() {
	var classScore [3][5]float64
	for i := 0; i < len(classScore); i++ {
		for j := 0; j < len(classScore[i]); j++ {
			fmt.Printf("input class %v student %v : ", i+1, j+1)
			fmt.Scanln(&classScore[i][j])
		}
	}
	fmt.Printf("classScore: %v\n", classScore)
	var classVag [3]float64
	var allVag float64 = 0
	for i := 0; i < len(classScore); i++ {
		sum := 0.0
		for j := 0; j < len(classScore[i]); j++ {
			sum += classScore[i][j]
		}
		allVag += sum
		classVag[i] = sum / float64(len(classScore[i]))
	}
	fmt.Printf("classVag: %v\n", classVag)
	vag := allVag / float64(len(classScore)*len(classScore[0]))
	fmt.Printf("allVag: %v\n", vag)
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SoaringW

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值