1.定义
数组var identifier [len]type
切片var identifier []type
2.长度
Go 语言中的数组是一种 值类型(不像 C/C++ 中是指向首元素的指针),所以可以通过 new() 来创建: var arr1 = new([5]int)。 数组长度len(arr1)
切片(slice)是对数组一个连续片段的引用(该数组我们称之为相关数组,通常是匿名的),所以切片是一个引用类型
切片提供了计算容量的函数 cap() 可以测量切片最长可以达到多少:它等于切片的长度 + 数组除切片之外的长度。0 <= len(s) <= cap(s)
3.var arr1 = new([5]int) 和 var arr2 [5]int的区别
arr1 的类型是 *[5]int,而 arr2的类型是 [5]int
package mainimport "fmt"func main(){var arr1 = new([5]int)var arr2 [5]int// f(arr1) //cannot use arr1 (type *[5]int) as type [5]int in argument to f//f(&arr1) //cannot use &arr1 (type **[5]int) as type [5]int in argument to ff(*arr1)fp(arr1)//fp(&arr1) //cannot use &arr1 (type **[5]int) as type *[5]int in argument to fpf(arr2)//fp(arr2) //cannot use arr2 (type [5]int) as type *[5]int in argument to fpfp(&arr2)}func f(a [5]int){fmt.Println(a)}func fp(a *[5]int){fmt.Println(a)}/**[0 0 0 0 0]&[0 0 0 0 0][0 0 0 0 0]&[0 0 0 0 0]**/
4.数组常量,切片初始化
var arrKeyValue = [5]string{3: "Chris", 4: "Ron"}var arrAge = [5]int{18, 20, 15, 22, 16}var arrLazy = [...]int{5, 6, 7, 8, 22} ... 可以忽略
切片的初始化格式是:var slice1 []type = arr1[start:end]
var slice1 []type = arr1[:] 那么 slice1 就等于完整的 arr1 数组
arr1[2:] 和 arr1[2:len(arr1)] 相同,都包含了数组从第三个到最后的所有元素。
arr1[:3] 和 arr1[0:3] 相同,包含了从第一个到第三个元素(不包括第三个)。
一个由数字 1、2、3 组成的切片可以这么生成:s := [3]int{1,2,3}[:] 甚至更简单的 s := []int{1,2,3}。
5.多维数组、切片
数组通常是一维的,但是可以用来组装成多维数组,例如:[3][5]int,[2][2][2]float64。
和数组一样,切片通常也是一维的,但是也可以由一维组合成高维。通过分片的分片(或者切片的数组),长度可以任意动态变化,所以 Go 语言的多维切片可以任意切分。而且,内层的切片必须单独分配(通过 make 函数)。
6.将数组传递给函数
传递数组的指针
func main() {array := [3]float64{7.0, 8.5, 9.1}x := Sum(&array)}func Sum(a *[3]float64){}
使用数组的切片 ``` func sum(a []int) int { s := 0 for i := 0; i < len(a); i++ {
s += a[i]
} return s }
func main() { var arr = [5]int{0, 1, 2, 3, 4} sum(arr[:]) }
<a name="yoVYg"></a>#### 7.使用make创建切片,与new的区别make 的使用方式是:func make([]T, len, cap),其中 cap 是可选参数。<br />简写为 slice1 := make([]type, len)<br />s2 := make([]int, 10),那么 cap(s2) == len(s2) == 10
make([]int, 50, 100) new([100]int)[0:50]
- new(T) 为每个新的类型T分配一片内存,初始化为 0 并且返回类型为*T的内存地址:这种方法 **返回一个指向类型为 T,值为 0 的地址的指针**,它适用于值类型如数组和结构体;它相当于 &T{}。- make(T) **返回一个类型为 T 的初始值**,它只适用于3种内建的引用类型:切片、map 和 channel<a name="WvIpg"></a>#### 8.bytes包类型 []byte 的切片十分常见,Go 语言有一个 bytes 包专门用来解决这种类型的操作方法。<br />**通过 buffer 串联字符串**<br />类似于 Java 的 StringBuilder 类。<br />在下面的代码段中,我们创建一个 buffer,通过 buffer.WriteString(s) 方法将字符串 s 追加到后面,最后再通过 buffer.String() 方法转换为 string:```gopackage mainimport("fmt""bytes")var strings = []string{"aaa","bbb","ccc"}var flag = 0func main(){var buffer bytes.Bufferfor {if value, ok := getNextString(); ok {buffer.WriteString(value)} else {break}}fmt.Println(buffer.String())}func getNextString() (string, bool){if flag < len(strings){defer func (){ flag++ }()return strings[flag],true}return "",false}
9.for-range结构
for ix, value := range slice1 {...}//第一个返回值 ix 是数组或者切片的索引,第二个是在该索引位置的值
10.切片重组(reslice)
我们的切片在达到容量上限后可以扩容。改变切片长度的过程称之为切片重组 reslicing,做法如下:slice1 = slice1[0:end],其中 end 是新的末尾索引(即长度)
//将切片扩展 1 位可以这么做sl = sl[0:len(sl)+1]
var ar = [10]int{0,1,2,3,4,5,6,7,8,9}var a = ar[5:7] // reference to subarray {5,6} - len(a) is 2 and cap(a) is 5a = a[0:4] // ref of subarray {5,6,7,8} - len(a) is now 4 but cap(a) is still 5
11.切片的复制与追加
拷贝切片的 copy 函数和向切片追加新元素的 append 函数
func append(s[]T, x …T) []T 其中 append 方法将 0 个或多个具有相同类型 s 的元素追加到切片后面并且返回新的切片;追加的元素必须和原切片的元素同类型。如果 s 的容量不足以存储新增元素,append 会分配新的切片来保证已有切片元素和新增元素的存储。
package mainimport "fmt"func main() {sl_from := []int{1, 2, 3}sl_to := make([]int, 10)n := copy(sl_to, sl_from)fmt.Println(sl_to)fmt.Printf("copied %d elements\n", n)sl3 := []int{1,2,3}sl3 = append(sl3, 4, 5, 6)fmt.Println(sl3)}
func copy(dst, src []T) int copy 方法将类型为 T 的切片从源地址 src 拷贝到目标地址 dst,覆盖 dst 的相关元素,并且返回拷贝的元素个数。源地址和目标地址可能会有重叠。拷贝个数是 src 和 dst 的长度最小值。如果 src 是字符串那么元素类型就是 byte。如果你还想继续使用 src,在拷贝结束后执行 src = dst。
