golang学习笔记——数据和切片


一维数组赋值 package main   import (     "fmt" )   func main() {     //全部赋值     var a [5]int = [5]int{1, 2, 3, 4, 5}     fmt.Println("a = ", a)       //部分赋值     b := [...]int{3, 4, 5}     fmt.Println("b = ", b)       //指定元素赋值     c := [5]int{1: 2, 3: 4}     fmt.Println("c = ", c) }   二维数组赋值 package main   import (     "fmt" )   func main() {     a := [2][3]int{          {3, 2, 1},          {1, 2, 3},     }     fmt.Println("a = ", a) }   数组做形参 package main   import (     "fmt" )   func modify(p *[5]int) {     (*p)[0] = 100 }   func main() {     a := [5]int{1, 2, 3, 4, 5}     modify(&a)     fmt.Println("a = ", a) }   切片
  • 声明
//自动推导类型 s1 := []int{1, 2, 3, 4} fmt.Println("s1 = ", s1) //借助make函数 make(切片类型,长度,容量) s2 := make([]int, 5, 6) fmt.Printf("s2 : len(s2) = %d,cap(s2) = %d \n", len(s2), cap(s2))
  • 截取切片
        low:代表截取开始的开始下标(包含)         height:代表截取结束的下标(不包含)         max:代表原始数组的长度或原始切片的最大容量 sl := [6]int{1, 2, 3, 4, 5, 10} // sl[low:heigh:max] s := sl[2:3:6] fmt.Println("s = ",  s)
  • 切片的容量和长度
切片的长度是指切片中实际包含的元素个数,而容量是指切片能容纳的最大元素个数,为什么要设计长度和容量这两个参数而不是使用一个参数代替呢?在这里容量是可以根据切片里的元素增加而增加的,并且是成倍数增涨,切片容量的增加意味着需要重新调整分配的内存空间,也就会造成多余的性能消耗。所以初始化切片时合理的设置容量的大小,能有效地降级重新分配变量内存而带来的性能消耗 package main   import "fmt"   func main() {    array := make([]int, 1, 3)    fmt.Printf("初始化切换的长度:%d,容量 %d \n", len(array), cap(array))    for i := 0; i < 10; i++ {       array = append(array, i)       fmt.Printf("初始化切换的长度:%d,容量 %d \n", len(array), cap(array))    } } //************输出************* 初始化切换的长度:1,容量 2 初始化切换的长度:2,容量 2 初始化切换的长度:3,容量 4 初始化切换的长度:4,容量 4 初始化切换的长度:5,容量 8 初始化切换的长度:6,容量 8 初始化切换的长度:7,容量 8 初始化切换的长度:8,容量 8 初始化切换的长度:9,容量 16 初始化切换的长度:10,容量 16 初始化切换的长度:11,容量 16
  • append函数(在切片末尾添加数据)
s := []int{1, 2, 3} s = append(s, 5, 6) fmt.Println("sl = ", s)
  • append扩容时如果最终切片的长度大于原先切片的容量,则新切片的最大容量会变为原切片容量的两倍。且如果这个值扔不能满足新切片的需求时以长度2递增
s := []int{1, 2} s = append(s, 5, 6, 7, 4, 5, 6) fmt.Println("s leng = ", cap(s)) //s leng = 8 s = append(s, 4, 5, 6, 7, 8) fmt.Println("s leng = ", cap(s)) // s leng = 16
  • copy(dst,src)  将src切片复制给dst切片复制的长度以dst的容量为准直到src切片所有元素
s := []int{1, 2, 3, 4, 5, 6, 7} s2 := []int{10, 11, 12, 13, 14, 15, 16, 17} copy(s[4:], s2) fmt.Println("s = ", s) // s = [1 2 3 4 10 11 12]
  • 注意
1、切片本身不包含任何数据。它仅仅是底层数组的一个上层表示。对切片进行的任何修改都将反映在底层数组中。 2、切片的长度是指切片中元素的个数。切片的容量是指从切片的起始元素开始到其底层数组中的最后一个元素的个数。 3、切片是不声明长度的数组
  • 切片是指针变量,数组是值变量
package main   import (     "fmt" )   func modify_arr(p [6]int) {     p[0] = 123 }   func modify_slice(p []int) {     p[0] = 123 }   func main() {       numbers_arr := [6]int{1, 2, 3, 4, 5, 6}     modify_arr(numbers_arr)     fmt.Println(numbers_arr) //输出 [1 2 3 4 5 6]       numbers_slice := []int{1, 2, 3, 4, 5, 6}     modify_slice(numbers_slice)     fmt.Println(numbers_slice) //输出 [123 2 3 4 5 6]   }
  • 内存优化
/** *    切片保留对底层数组的引用。只要切片存在于内存中,数组就不能被垃圾回收。这在内存管理方面可能是值得关注的。假设我们有一个 * 非常大的数组,而我们只需要处理它的一小部分,为此我们创建这个数组的一个切片,并处理这个切片。这里要注意的事情是,数组仍然  * 存在于内存中,因为切片正在引用它。解决该问题的一个方法是使用 copy 函数 func copy(dst, src []T) int 来创建该切片的一个  * 拷贝。这样我们就可以使用这个新的切片,原来的数组可以被垃圾回收。 **/ package main   import (       "fmt" )   func countries() []string {       countries := []string{"USA", "Singapore", "Germany", "India", "Australia"}     neededCountries := countries[:len(countries)-2]     countriesCpy := make([]string, len(neededCountries))     copy(countriesCpy, neededCountries) //copies neededCountries to countriesCpy     return countriesCpy } func main() {       countriesNeeded := countries()     fmt.Println(countriesNeeded) }