Go语言中数组和切片的用法

主要讲解Go语言中数组、切片(Slice) 的使用

主要知识点:

  • 熟悉定义数组的几种方式
  • 二维数组的用法
  • 数组是值类型(默认情况下 Go中所有的参数传递都是值传递)
  • [3]int 、[5]int 长度不一样,被认为是不同的数据类型
  • Go语言中 一般不直接使用数组,也不直接使用带指针的数组,而是使用切片(Slice)
  • 切片是对数组的一个视图,虽然Slice本身是值类型,但是它内部使用了对数组的指针引用,所以修改切片数据,会将数组原有数据修改掉
  • Slice可以向后扩展,不能向前扩展,扩展规则为:s[i] 不可以超越len(s),向后扩展不可以超过cap(s)
  • 向 Slice 添加元素

以下通过代码进行示例:

package main

import "fmt"


//数组的集中定义方式,数量要写在类型的前面
func array(){
	var arr1 [5]int  //普通定义方法,不定义初始值
	arr2:=[3]int{1,2,3} //定义数组时设置初始值
	arr3:=[...]int{2,4,6,8,10}//不指定长度,运行时让系统自己计算
	var grid [4][5]int //定义二维数组
	fmt.Println(arr1,arr2,arr3)//[0 0 0 0 0] [1 2 3] [2 4 6 8 10]
	fmt.Println(grid) //[[0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0]]

	//遍历数组的方式 1 :普通用法
	for i:=0;i<len(arr2);i++{
		fmt.Println(arr2[i]) //分别输出 1,2,3
	}

	//遍历数组的方式 1 :推荐用法用法(使用 range 关键字)
	for i,v:=range arr2 {
		fmt.Println(i,v)
		//0 1
		//1 2
		//2 3
	}
}
//[]int 参数中没有指定数组长度,此时代表为 Slice
func updateSlice(s []int) {
	s[0] = 100
}


func slice()  {
	arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
	//获取数组的中括号中使用区间,被称为切片 (Slice)
	//以下为切片的基础使用方式
	//获取下标 2-6 之间的数值
	fmt.Println("arr[2:6] =", arr[2:6]) //[2 3 4 5]
	//获取下标从开始到第6位的值
	fmt.Println("arr[:6] =", arr[:6]) //[0 1 2 3 4 5]
	//获取下标从2到最后的值
	fmt.Println("arr[2:] =", arr[2:]) //[2 3 4 5 6 7]
	//获取全部数据
	fmt.Println("arr[:] =", arr[:]) //[0 1 2 3 4 5 6 7]


	//以下为Slice更多用法

	s1 := arr[2:]
	fmt.Println("s1 =", s1) //s1 = [2 3 4 5 6 7]
	s2 := arr[:]
	fmt.Println("s2 =", s2) //s2 = [0 1 2 3 4 5 6 7]

	fmt.Println("After updateSlice(s1)")
	updateSlice(s1) //Slice 将原有数组的数据修改掉了
	fmt.Println(s1) //[100 3 4 5 6 7]
	fmt.Println(arr) //[0 1 100 3 4 5 6 7]

	fmt.Println("After updateSlice(s2)")
	updateSlice(s2) //Slice 将原有数组的数据修改掉了
	fmt.Println(s2) //[100 1 100 3 4 5 6 7]
	fmt.Println(arr) //[100 1 100 3 4 5 6 7]

	//对 Slice 再次进行 Slice 操作
	fmt.Println("Reslice")
	fmt.Println(s2) //[100 1 100 3 4 5 6 7]
	s2 = s2[:5]
	fmt.Println(s2) //[100 1 100 3 4]
	s2 = s2[2:]
	fmt.Println(s2)  //[100 3 4]

	//Slice 的扩展用法
	fmt.Println("Extending slice")
	arr[0], arr[2] = 0, 2 //将数据复原
	fmt.Println("arr =", arr) //arr = [0 1 2 3 4 5 6 7]
	s1 = arr[2:6]
	s2 = s1[3:5] // [s1[3], s1[4]] //此处通过扩展可以取到后面一个值
	fmt.Printf("s1=%v, len(s1)=%d, cap(s1)=%d\n",
		s1, len(s1), cap(s1)) //s1=[2 3 4 5], len(s1)=4, cap(s1)=6
	fmt.Printf("s2=%v, len(s2)=%d, cap(s2)=%d\n",
		s2, len(s2), cap(s2)) //s2=[5 6], len(s2)=2, cap(s2)=3

	s3 := append(s2, 10)
	s4 := append(s3, 11)
	s5 := append(s4, 12)
	//添加元素时如果超过cap,系统会重新分配更大的底层数组
	//由于值传递 的关系,必须手动接受 append 的返回值
	fmt.Println("s3, s4, s5 =", s3, s4, s5)
	//s3, s4, s5 = [5 6 10] [5 6 10 11] [5 6 10 11 12]

	// s4 and s5 no longer view arr.
	fmt.Println("arr =", arr) //arr = [0 1 2 3 4 5 6 10]

}


func main() {
	array()
	slice()
}

切片(Slice)的扩展

通过下图可以更好的理解 Slice的扩展功能,扩展后 s2=[5,6]。

Slice可以向后扩展,但不能向前扩展

Slice的底层实现包含了三个变量,分别是 

ptr :代表当前Slice第一个数据在原数组中的指针

len:代表当前Slice的长度

cap:代表向后扩展后的总数据

猜你喜欢

转载自my.oschina.net/ruoli/blog/1815476