Golang(五)[引用类型]

引用类型包括指针(point)、切片(slice)、字典(map)、函数(func)、通道(channel),虽然数据种类很多,但它们都是对程序中一个变量或状态的间接引用。这意味着对任一引用类型数据的修改都会影响所有该引用的拷贝。

1.指针(point)

2.切片(slice)

Golang的Slice源码位于src/runtime/slice.go

src/runtime/slice.go

1.简介

  • Slice(切片)代表变长的序列,序列中每个元素都有相同的类型。一个slice类型一般写作[]T,其中T代表slice中元素的类型;slice的语法和数组很像,只是没有固定长度而已。

  • Go 语言切片是对数组的抽象

  • 切片(slice)是对数组一个连续片段的引用(该数组我们称之为相关数组,通常是匿名的),所以切片是一个引用类型(和数组不一样)

  • slice是一个轻量级的数据结构,提供了访问数组子序列(或者全部)元素的功能,而且slice的底层确实引用一个数组对象

  • slice由三个部分构成:指针、长度和容量指针指向第一个slice元素对应的底层数组元素的地址slice的第一个元素并不一定就是数组的第一个元素

  • 长度对应slice中元素的数目;长度不能超过容量

  • 容量一般是从slice的开始位置到底层数据的结尾位置。内置的len和cap函数分别返回slice的长度和容量。

      长度是slice索引操作的上界
      容量是slice分割操作的上界
    
  • 多个slice之间可以共享底层的数据,并且引用的数组部分区间可能重叠。

  • slice不会实际复制一份数据,它只是创建一个新的数据结构,包含了另外的一个指针,一个长度和一个容量数据。 如同分割一个字符串,分割数组也不涉及复制操作:它只是新建了一个结构来放置一个不同的指针,长度和容量。

  • 切片提供了计算容量的函数 cap() 可以测量切片最长可以达到多少:它等于切片的长度 + 数组除切片之外的长度。

  • 优点

因为切片是引用,所以它们不需要使用额外的内存并且比使用数组更有效率,所以在 Go 代码中切片比
数组更常用。

  • 注意

绝对不要用指针指向 slice,切片本身已经是一个引用类型,所以它本身就是一个指针!
声明切片的格式是: var identifier []type(不需要说明长度)。
一个切片在未初始化之前默认为 nil,长度为 0。
go语言源码对slice的定义

2.定义

2.1.方式1

var slice []data_type 
释义:
slice:切片名称
data_type:切片的数据类型
注意:
此时切片中的[]是空的,切片的长度和容量均为0
func main() {
	var slice []int
	fmt.Println(slice)
	fmt.Println("len = ",len(slice),",cap = ",cap(slice))
}

此时切片中的[]是空的,切片的长度和容量均为0

2.2.方式2

slice := []data_type{}
释义:
slice:切片名称
data_type:切片的数据类型
注意:
此时切片中的[]是空的,切片的长度和容量均为0
func main() {
	slice := []int{}
	fmt.Println(slice)
	fmt.Println("len = ", len(slice), ",cap = ", cap(slice))
}

此时切片中的[]是空的,切片的长度和容量均为0

2.3.方式3

slice := make([]data_type,len,cap) 
释义:
slice:切片名称
data_type:切片的数据类型
len:切片的长度
cap:切片的容量
func main() {
	slice := make([]int, 0, 0)
	fmt.Println(slice)
	fmt.Println("len = ", len(slice), ",cap = ", cap(slice))
}

通过make创建切片

2.4.方式4

通过数组切割得到切片

var array_name = [size]type{}
slice := array_name[:]
释义:
array_name:数组名称
size:数组长度/大小
slice:切片名称
data_type:切片的数据类型
注意:
此时的切片的元素不是[],长度和容量根据数组的大小来确定,此时的切片长度=容量
func main() {
	var array = [10]int{}
	slice := array[:]
	fmt.Println(slice)
	fmt.Println("len = ", len(slice), ",cap = ", cap(slice))
}

通过切割数组得到切片

3.初始化

3.1.先定义后初始化

var slice = []data_type
slice = append(slice,data1,data2)
或者:
slice := []data_type
slice = append(slice,data1,data2)
释义:
slice:切片名字
data_type:数据类型
append():添加数据的函数
data1,data2:数据

3.2.定义并初始化

var slice = []data_type{data1,data2}
或者:
slice := []data_type{data1,data2}

4.访问

slice[index]

5.遍历

5.1.索引遍历

索引范围为:0len(array)-1

func main() {
	var slice = []int{1, 2, 3, 4, 5,}
	for index := 0; index < len(slice); index++ {
		fmt.Println(slice[index])
	}
}

5.2.使用范围range进行遍历

func main() {
	var slice = []int{1, 2, 3, 4, 5,}
	for index, value := range slice {
		fmt.Printf("slice[%d] = %d \n",index,value)
	}
}

6.下标越界

6.1.正向越界

引发panic异常

func main() {
	var slice = []int{1, 2, 3, 4, 5,}
	slice[6] = 0
	fmt.Println(slice)
}

引发panic异常

func main() {
	var slice = []int{1, 2, 3, 4, 5,}
	for index := 0; index <= len(slice); index++ {
		fmt.Println(slice[index])
	}
}

引发panic异常

6.2.反向越界

操作时候,编译不通过,提示索引必须为非负,遍历时候,负索引会导致panic异常

func main() {
	var slice = []int{1, 2, 3, 4, 5,}
	slice[-1] = 100
	fmt.Println(slice)
}

反向索引越界

func main() {
	var slice = []int{1, 2, 3, 4, 5,}
	for index := -1; index < len(slice); index++ {
		fmt.Println(slice[index])
	}
}

反向越界引发panic异常

7.函数参数传递

8.比较[==或!=]

11.斐波那契数列

12.底层实现

13.len( )

14.cap( )

15.append()

16.copy()

14.多维切片

15.元素/逆置

16.注意事项

3.字典(map)

4.函数(func)

5.通道(channel)

发布了48 篇原创文章 · 获赞 14 · 访问量 4153

猜你喜欢

转载自blog.csdn.net/weixin_42366378/article/details/105102721