一、数组
- 使用方法:
- 声明数组
var <variableName> [<length>]<elementType>
,一定要加长度!否则就变成切片了! - 数组初始化
= [<length>/...]<elementType>{[value] , ...]}
数组长度省略为...时,编译器会自动计算数组长度 - 数组取值赋值同其他语言一样
- 声明数组
- 注意事项:
- Go数组大小不可变更,数组大小是数组的固有属性之一
- [3]int和[5]int是不一样的类型,不兼容!
- 数组变量并不像C一样,是指向数组第一个元素所在的地址,更像是一种特殊的结构体
二、切片(重要)
-
切片的概念:
切片就是一个描述某一个数组的某一段连续序列的特殊结构,由一个指向对应数组的指针,一个描述当前表示的连续序列的长度(length)和一个描述当前序列能够最大达到的长度(capacity)的三个变量组成。
假设有数组
a := [5]byte{"a","b","c","d","e"}
,则切片s := a[2,4]
表示的是{"c","d"}
,长度为2,容量为3,指针指向对应数组的第三个元素 -
切片用法:
- 切片初始化
- 对数组操作
a := [5]byte{"a","b","c","d","e"} s := a[2,4] // s => {"c","d"}
- 直接初始化(和数组不同在于中括号中不定义长度)
q := []int{2, 3, 5, 7, 11, 13} // q => {2, 3, 5, 7, 11, 13}
- 使用make函数(func make([]T, len, cap) []T)
s := make([]byte, 5, 5) // s => {0,0,0,0,0}
- 读取切片中指定元素,索引不能等于或超过切片长度,即使容量比长度大
primes := [6]int{2, 3, 5, 7, 11, 13} s := primes[1:4] fmt.Println(s[2]) //fmt.Println(s[3]) error!!!
- 切片可以在切片的基础上再分配
a := [5]byte{"a","b","c","d","e"} s := a[2,4] // s => {"c","d"} s = s[0,1] // s => {"c"}
- 切片的开始和结束索引都可以省略,结束索引省略时默认为切片的长度且最大不可以超过切片的容量,开始索引省略时默认为从指针指向的那个元素开始,所以不要把开始索引设为负数(对,那种想法不可以)
a := [5]byte{"a","b","c","d","e"} s := a[:] // s => {"a","b","c","d","e"} s = s[1:3] // s => {"b","c"} s = s[:] // s => {"b","c"} s = s[1:4] // s => {"c","d","e"}
- 切片记录的是地址,所以如果更改某一个元素的值,则所有有关这篇区域的数组和切片的值都会变动!
- 切片的长度由
len(slice)
,容量由cap(slice)
来得知 - 只声明不赋值的切片类型变量为nil
var s []int // s => nil
- 切片也支持多维的,且不必保持子数组长度一样
board := [][]string{ []string{"_", "_", "_"}, []string{"_", "_", "_"}, []string{"_", "_", "_"}, } // The players take turns. board[0][0] = "X" board[2][2] = "O" board[1][2] = "X" board[1][0] = "O" board[0][2] = "X" /* board => X _ X O _ X _ _ O */
- 使用内置append函数为切片添加新的值(func append(s []T, vs ...T) []T)
primes := [6]int{2, 3, 5, 7, 11, 13} s := primes[1:4] // s => {3,5,7} s = append(s,5)// s => {3,5,7,5} primes => {2,3,5,7,5,13}
如果需要操作的切片,容量足够,则相当于扩大切片的length,并且修改那些扩大范围内元素的值为指定的值
如果容量不够,则会生成一个新的数组,并将原有元素和新增元素放在里面,并返回一个新的对应切片,容量会以2的倍数增加,长度则为实际切片的长度 - 切片初始化
参考文档:
[1] Go Slices: usage and internals
网友评论