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 main
import "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 f
f(*arr1)
fp(arr1)
//fp(&arr1) //cannot use &arr1 (type **[5]int) as type *[5]int in argument to fp
f(arr2)
//fp(arr2) //cannot use arr2 (type [5]int) as type *[5]int in argument to fp
fp(&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:
```go
package main
import(
"fmt"
"bytes"
)
var strings = []string{"aaa","bbb","ccc"}
var flag = 0
func main(){
var buffer bytes.Buffer
for {
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 5
a = 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 main
import "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。