数组类型的值(以下简称数组)的长度是固定的,而切片类型的值(以下简称切片)是可变长的。
数组的长度在声明它的时候就必须给定,并且在之后不会再改变。可以说,数组的长度是其类型的一部分。
Go 语言的切片类型属于引用类型,同属引用类型的还有后面会讲到的字典类型、通道类型、函数类型等;而 Go 语言的数组类型则属于值类型,同属值类型的有基础数据类型以及结构体类型。
Go 语言中,我们判断所谓的“传值”或者“传引用”只要看被传递的值的类型。
如果传递的值是引用类型的,那么就是“传引用”。如果传递的值是值类型的,那么就是“传值”。从传递成本的角度讲,引用类型的值往往要比值类型的值低很多。
当我们用make函数初始化切片时,如果不指明其容量,那么它就会和长度一致。如果在初始化时指明了容量,那么切片的实际容量也就是它了。
怎样估算切片容量的增长?
一旦一个切片无法容纳更多的元素,Go 语言就会想办法扩容。但它并不会改变原来的切片,而是会生成一个容量更大的切片,然后将把原有的元素和新元素一并拷贝到新切片中。
在一般的情况下,你可以简单地认为新切片的容量(以下简称新容量)将会是原切片容量(以下简称原容量)的 2 倍。
但是,当原切片的长度(以下简称原长度)大于或等于1024时,Go 语言将会以原容量的1.25倍作为新容量的基准(以下新容量基准)。
新容量基准会被调整(不断地与1.25相乘),直到结果不小于原长度与要追加的元素数量之和(以下简称新长度)。最终,新容量往往会比新长度大一些,当然,相等也是可能的。
练习:
package main
import "fmt"
func main() {
var x [5]int
//通过下标修改数组
x[3] = 100
fmt.Println(x) //[0 0 0 100 0
//数组的长度:
var total float64 = 0
for i := 0; i < len(x); i++ {
total += float64(x[i]) //因为total是float64,x[i]是int,所以需要显示的进行转换:
}
fmt.Println(total / float64(len(x))) //因为total是float64,len(x)是int,所以需要显示的进行转换
fmt.Println("-------------------")
//range在数组中的使用
var total2 float64 = 0
for _, value := range x {
total2 += float64(value)
}
fmt.Println(total2 / float64(len(x)))
fmt.Println("------------------")
x2 := [5]float64{
98,
93,
77,
82,
83,
}
var total3 float64 = 0
for _, value := range x2 {
total3 += value
}
fmt.Println(total3 / float64(len(x2))) //86.6
fmt.Println("------------------")
/*
slice
*/
//通过make进行创建:
//append函数
slice1 := []int{1, 2, 3}
slice2 := append(slice1, 4, 5)
fmt.Println(slice1, slice2) //[1 2 3] [1 2 3 4 5]
//copy函数
fmt.Println("-----------------")
slice3 := []int{1, 2, 3}
slice4 := make([]int, 2)
copy(slice4, slice3)
fmt.Println(slice3, slice4) //[1 2 3] [1 2]
fmt.Println("-------------------")
// Here we create an array `a` that will hold exactly
// 5 `int`s. The type of elements and length are both
// part of the array's type. By default an array is
// zero-valued, which for `int`s means `0`s.
var a [5]int
fmt.Println("emp:", a)
// We can set a value at an index using the
// `array[index] = value` syntax, and get a value with
// `array[index]`.
a[4] = 100
fmt.Println("set:", a)
fmt.Println("get:", a[4])
// The builtin `len` returns the length of an array.
fmt.Println("len:", len(a))
// Use this syntax to declare and initialize an array
// in one line.
b := [5]int{1, 2, 3, 4, 5}
fmt.Println("dcl:", b)
// Array types are one-dimensional, but you can
// compose types to build multi-dimensional data
// structures.
var twoD [2][3]int
for i := 0; i < 2; i++ {
for j := 0; j < 3; j++ {
twoD[i][j] = i + j
}
}
fmt.Println("2d: ", twoD)
}