【Go】详解Go的数组与切片

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_30604453/article/details/82500777

11. Go 数组
数组是指包含同一类型元素的集合,Go不允许数组混合不同的数据类型
11.1 数组的诡异声明语法

     var arr [3] int  //声明但不初始化,Go会根据数据类型赋予默认初始化值0  // [0,0,0]
     var arr = [3]int{5,8,9}  //声明并且初始化  // [5,8,9]
     var arr = [...]int{5,8,9}  //声明并且初始化,忽略数组元素个数,Go根据{}内元素个数自动赋予数组长度  //[5,8,9]
     // 使用:=简洁大法
     arr := [3]int{12}  //自动将剩下的未初始化的值赋予默认值0   //[12,0,0]
     a := [...]int{12, 78, 50}


11.2 数组长度 len(arr)
11.3 使用range遍历数组

for index,value := range arr {
  ...
}
for _,value := range arr {  //忽略数组下标
  ...
}


11.4 多维数组

 arr := [3][2]string{
  {"A","B"},
  {"a","b"},
  {"1","2"},
 }


12. Go 切片
因为在Go中数组是定长的,所以不定长的切片比数组更常用。切片本身不拥有任何数据,是对现有数组的引用。
切片声明与数组类型,区别在于一个有长度一个没有长度。
12.1 切片声明
  12.1.1  

var myslice []int  //声明切片但不赋值  myslice=nil

  12.1.2  

myslice := []int{6,7,8} 
 //与数组声明类似,但不写明长度。
//此时创造了数组[6,7,8]并返回了myslice对该数组的引用  len(myslice)为3 cap(mysplice)为3


12.2 对现有数组的引用,假定现有数组 arr := [...]int{0,1,2,3,4,5,6,8}

//12.2.1  
var myslice [] int = arr[1:4]  //代表截取数组arr下标1至4-1  [1,2,3]
//12.2.2  
myslice := arr[1:4]
//12.2.2 
myslice := arr[:] //表示对arr数组的全部引用


 因为切片是对现有数组的引用,所以改变切片,被引用的数组也会改变

12.3

   len(myslice)  //表示切片的长度 例如arr[1:4] 返回值为3
   cap(myslice) //表示切片的容量 例如arr[1:4]  返回值为 len(arr) - startIndex // 7

12.4 使用make创建切片
func make([]T,len,cap) []T {...}

myslice := make([]int,5,5)  //[0,0,0,0,0] cap参数可选,默认为len

12.5 追加切片元素
func append(s[]T,x...T) []T {...}

myslice = append(myslice,10)

12.6 多维切片:与多维数组类似,只要不声明长度即可

mysplice := [][]string{
 {"A","B"},
 {"a","b"},
 {"1","2"},
}
//如何循环输出多维切片/多维数组
for _, v1 := range mysplice {
    for _, v2 := range v1 {
        fmt.Printf("%s ", v2)
    }
    fmt.Printf("\n")
}

12.7 内存优化
参考链接:https://studygolang.com/articles/12121
切片持有对底层数组的引用。只要切片在内存中,数组就不能被垃圾回收。在内存管理方面,这是需要注意的。
让我们假设我们有一个非常大的数组,我们只想处理它的一小部分。然后,我们由这个数组创建一个切片,并开始处理切片。
这里需要重点注意的是,在切片引用时数组仍然存在内存中。一种解决方法是使用 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)
}


12.8 将切片传入可变参数函数中

func find (num int,nums ...int){
 ...
}
func main(){
  mysplice := []int{5,8,9}
  find(0,mysplice...)
}

tips:在函数体内对形参切片现有的元素进行改变,实参切片也会改变,但是对形参切片进行追加元素,实参切片无变化
Go语言的参数传递都是值传递。切片包含三部分:长度,容量,指向数组的第n个元素的指针
当切片作为参数传递过去(注意是值传递),此时拷贝了一份切片副本(在函数体内使用的就是切片副本)。
然而不管是原切片还是切片副本,其内的元素是指针指向,指向同一个地址,所以我们对切片副本现有的元素做修改,原切片也会变化
但是我们对副本切片做修改,如append,并不会影响原切片
 

猜你喜欢

转载自blog.csdn.net/qq_30604453/article/details/82500777