美文网首页
10-Go语言数组和切片

10-Go语言数组和切片

作者: 喝酸奶要舔盖__ | 来源:发表于2018-09-23 12:33 被阅读0次

Go语言数组数组

一维数组
  • 数组定义格式: var arr [3]int
  • 数组的初始化方式
    • 先定义后初始化
      注意点:Go语言数组支持先定义后一次性初始化
    //1.先定义后初始化
          var nums [3]int
          //先定义数组再逐个初始化
          nums[0] = 1
          nums[1] = 2
          nums[2] = 3
    
          //先定义数组再一次性初始化
          nums = [3]int{2,3,4}
          fmt.Println(nums)
    
    • 定义的同时初始化
      • 注意点:给数组一次性赋值的时候一定要在值的前面加上数组的类型,而且必须要和数据类型一模一样
      • C语言中数组没有初始化保存的是垃圾数据,Go语言中数组没有初始化保存的是零值
    //var arr [3]int = [3]int{2, 3, 4}
      //定义的同时部分初始化,未初始话的元素为0
      var arr [3]int = [3]int{1,3}
      //指定元素初始化
      var arr [3]int = [3]int{2:4}
      //[...]的含义, 让编译器根据赋值的元素个数自动计算数组的元素个数
      arr := [...]int{1,3,4}
      fmt.Println(arr)
      fmt.Println(arr[0])
      fmt.Println(arr[1])
      fmt.Println(arr[2])
    

零值
  • 什么是零值
    • 数据类型未初始化,系统自动添加的数据
    • 各种数据类型零值
      • int/int8/int16/int32/int64/uint/uint8/uint16/uint32/uint64/byte/rune/uintptr的默认值是0
      • float32/float64的默认值是0.0
      • bool的默认值是false
      • string的默认值是""
      • pointer/function/interface/slice/channel/map/error的默认值是nil

值类型
  • Go语言在数组中是值类型,所以数组之间的赋值是值拷贝关系,而不是指向关系
  • 如果想让两个数组可以相互赋值, 那么两个数组的类型必须一致类型一致包括元素个数, 元素个数也是Go语言中数组类型的一部分
  • 如果数组中存储的元素类型支持== != 操作,而且两个数组的类型是一个样的, 那么数组也支持== !=操作
package main

import "fmt"

func main() {
    nums := [...]int {2,3,4}
    arr := [...]int{2,3,4}
    fmt.Println(nums == arr) //true

    nums := [3]int{1,2,3}
    res := nums
    fmt.Println(res) //[1,2,3]

    nums := [3]int{1,2,3}
    change(nums)
    fmt.Println(nums)  //[1,2,3]

}
//函数内部无法改变数组元素的值
func change(nums [3]int)  {
    nums[2] = 666
}

二维数组
  • Go语言二维数组格式: var 数组名称[一维数组个数][一维数组元素个数]数组类型
package main

func main() {
    //定义二维数组格式
    var nums [2][3]int = [2][3]int{
        {1,3,5},
        {2,5,6},
    }

    //简单定义方法
    nums := [2][3]int{
        {1,2,3},
        {4,5,6},
    }

    arr := [...][3]int{
        {12,3,5},
        {1,2,6},
    }
    fmt.Println(arr)
   //二维数组也可以省略元素个数,但是只可以省略行数,不可以省略列数
    arr := [...][3]int{
        {12,3,5},
        {1,2,6},
    }

    //遍历二维数组
    for i:=0; i< 2; i++{
        for j:=0;j < 3 ;j++  {
            fmt.Println(arr[i][j])
        }
    }
}

数组的遍历
  • Go语言数组遍历两种方法
    • 普通for循环遍历
    nums := [...]int{2, 3, 5, 1, 3, 6}
      //普通for循环遍历
      for i := 0; i < 6; i++ {
          fmt.Println("index= ", i, "value = ", nums[i])
      }
    
    • for..range遍历
    nums := [...]int{2, 3, 5, 1, 3, 6}
      //高级for循环遍历
      for key,value := range nums{
          fmt.Println(key,"-->",value)
      }
    

Go语言切片

切片
  • 什么是切片

    • 在Go语言中,数组的长度一旦确定就无法改变,为了解决这一问题,推出了一种数据类型切片
    • 切片简单理解就是一个可变长度的数组,底层的实现原理就是一个结构体, 结构体中有一个指针指向了一个数组
      本质上所有的数据都是保存在指向的数组中的
  • 创建切片

    • 通过数组创建切片1
      通过数组来创建
      格式: [起始位置:结束位置], 从起始位置开始截取, 直到结束位置, 但是不包括结束位置
      注意:  截取了多少个元素, len就等于几
             容量等于数组的长度 - 起始位置
      nums := [5]int{1,2,3,4,5}
      //1.通过数组创建切片
      //1.1[起始位置 : 结束位置] 从起始位置开始截取,直到结束位置,但是不包括结束位置索引对应的元素
      var sce []int = nums[2 : 4]
    
      //1.2[: 结束位置]只指定结束位置,不指定起始位置,就是从开始位置截取直到指定的位置,但是也不包括指定位置的元素
      var sce []int = nums[:3]
    
      //1.3[起始位置 : ] 从起始位置开始截取,直到末尾
      var sce []int = nums[0:]
    
      //1.4[: ]只有一个:,从开始位置截取,直到末尾结束
      var sce []int = nums[:]
      fmt.Println(sce)
      //计算切片的长度len当前保存的数据个数
      fmt.Println(len(sce))
      //计算切片的容量cap总共能够保存数据的个数
      fmt.Println(cap(sce))
    
    
    • 通过数组创建切片2
      切片的第三个参数max,不能小于第二个参数,作用是用来控制切片容量的
      //如果指定了第三个参数, 那么切片的容量就等于 第三个参数 - 第一个参数
      //注意点: 如果没有指定第三个参数,那么切片的容量 = 数组的容量 - 第一个参数值
      //        如果指定了第三个参数,那么切片的容量 = 第三个参数 - 第一个参数值
      arr := [7]int{1,2,3,4,5,6,7}
      sce := arr[1:4:4]
      fmt.Println(sce)
      fmt.Println(len(sce))
      fmt.Println(cap(sce))
    
    • 通过make()函数创建切片
     // 2.通过make函数创建切片
      // 第一个参数: 告诉系统要存储什么类型的数据
      // 注意点: 如果是创建切片一定要在传入的数据类型前面写上[]
      // 第二个参数: 告诉系统创建出来的切片len等于多少
      // 第三个参数: 告诉系统创建出来的切片cap等于多少
      // 注意点: 第三个参数可以省略, 如果省略切片的容量就等于切片的长度(等于第二个参数)
      //var sce []int = make([]int, 2, 5)
      var sce []int = make([]int, 2)
      fmt.Println(sce)
      fmt.Println(len(sce))
      fmt.Println(cap(sce))
    
    • 通过语法糖创建切片
      // 3.通过Go提供的语法糖来创建
      // 一定要注意[]里面没有值就是切片
      // 通过Go提供的语法糖来创建len等于cap
      var sce []int = []int{1, 3, 5} // 相当于make([]int, 3)
      fmt.Println(sce)
      fmt.Println(len(sce))
      fmt.Println(cap(sce))
    

切片与数组
  • [ ]没有数字就是切片,有数字就是数组,[...]这种定义格式是数组
  //定义数组
    var arr [5]int = [5]int{1,3,4,5,6}
    var arr = [5]int{1,3,4,5,6}
    arr := [5]int{1,3,4,5,6}
    arr := [...]int{1,3,4,5,6}
//定义二维数组
    var arrs [2][3]int = [2][3]int{
        {1,3,5},
        {2,4,6},
    }
    var arrs = [2][3]int{
        {1,3,5},
        {2,4,6},
    }

    arrs := [2][3]int{
        {1,3,5},
        {2,4,6},
    }

    arrs := [...][3]int{
        {1,3,5},
        {2,4,6},
    }
  //定义切片
    var sce []int = []int{1,3,5}
    var sce = []int{1,3,5}
    sce := []int{1,3,5}
//定义一个切片,切片中保存的是数组
    var sec [][3]int = [][3]int{
        {1, 3, 5},
        {2, 4, 6},
    }

    var sec = [][3]int{
        {1, 3, 5},
        {2, 4, 6},
    }

    sec := [][3]int{
        {1, 3, 5},
        {2, 4, 6},
    }
//定义一个切片,切片中保存切片
    var sec[][]int = [][]int {
        {1, 3, 5},
        {2, 4, 6},
    }

    var sec = [][]int {
        {1, 3, 5},
        {2, 4, 6},
    }
    sec := [][]int {
        {1, 3, 5},
        {2, 4, 6},
    }

append函数
  • append函数格式 :append(切片,数据)
  • append函数作用: 追加切片中的数据
  • append函数注意点
    • 如果通过append函数追加数据之后超过了原有的容量, 那么系统内部会自动按照当前容量*2的方式重新定义一个数组作为切片保存数据的模型
    • 在扩容的时候会重新定义一个新的切片, 所以需要返回一个切片
    • 扩容问题
      • 容量小于1024的时候扩容, 会按照原有容量的2倍扩容
      • 容量大于1024的时候扩容,会按照原有的1/4进行扩容
    sec := make([]int, 1024, 1024)
    sec = append(sec, 6)
    fmt.Println(len(sec))
    fmt.Println(cap(sec))//1280

切片的使用
  • 定义切片
sec := []int{1,3,5,7,9,11}
  • 修改切片中的数据
sec[2] = 666
  • 增加切片中的数据
sec = append(sec, 7)
fmt.Println(sec)
  • 删除切片中指定的数据
//5.删除切片中的指定索引对应的数据
    index := 3
    //不仅可以利用数组获取切片,还可以用切片获取切片
    //sec = sec[:index]
    //fmt.Println(sec) //[1 3 5]
    //sec = sec[index +1 :]
    //fmt.Println(sec) //[9 11]
    //将第二个切片追加到第一个切片后面即可
    sec = append(sec[:index], sec[index +1 :]...)
    fmt.Println(sec) //[1 3 5 9 11]

切片的内存地址
package main

import "fmt"

func main() {
    /*
    通过切片生成切片的注意点
    */

    //1.创建一个数组
    var arr  = [3]int{1,2,3}
    //Go语言中不能通过数组名称获取数组的地址
    //fmt.Printf("%p\n", arr)
    fmt.Printf("%p\n", &arr) //0xc0420500a0
    fmt.Printf("%p\n", &arr[0]) //0xc0420500a0

    //2.通过数组创建一个切片
    //直接打印sce打印的是sce中指针保存的地址,也就是底层指向的那个数组的地址
    sce := arr[:]
    fmt.Printf("%p\n", sce) //0xc0420500a0

    //3.通过切片创建切片
    //通过切片创建一个切片, 新的切片和老的切片底层指向同一个数组
    sce2 := sce[:]
    fmt.Printf("%p\n", sce2) //0xc0420500a0

    //修改数组中的值
    arr[2] = 666
    sce[2] = 666
    sce2[2] = 666
    fmt.Println(arr)
    fmt.Println(sce)
    fmt.Println(sce2)
}
copy函数
package main

import "fmt"

func main() {
    /*
    copy函数的作用是将源切片的值拷贝到目标切片当中
    函数格式 copy(目标切片, 源切片)

     */
    sec1 := []int{1, 2, 3, 6, 9, 10}
    sec2 := make([]int, 2, 5)
    fmt.Println(sec2)
    //将源切片的值拷贝到目标切片当中
    //注意点: 拷贝的时候是以目标切片为准,目标切片中长度为多少将来只能拷贝多少个值进来
    copy(sec2, sec1)
    fmt.Println(sec2)
}

切片与字符串

注意点: 切片和数组不同, 切片不支持== !=操作

package main

import "fmt"

func main() {
    /*
    1.切片可以再生成新的切片, 两个切片底层指向同一个数组
    2.切片和数组不同, 切片不支持== !=操作
    3.在Go语言中字符串的底层实现就是切片, 所以可以通过字符串来生成切片
    */

    //数组可以使用== !=操作
    //arr := [3]int{1,2,3}
    //arr2 := [3]int{4,5,6}
    //arr = arr2
    //fmt.Println(arr)


    var str string = "www.it666.com"
    sec := make([]byte, len(str))
    copy(sec,str)
    fmt.Println(len(str))
    fmt.Printf("%s\n",sec) //www.it666.com
}
切片与数组注意点
  • 数组定义后不初始化,可以使用,切片定义后可以一次性初始化,但是不能逐个初始化,但是可以使用append函数添加数据
  • 数组定义后直接使用
var arr [4]int
    //数组定义后可以直接使用
    arr[0] = 1
    arr[1] = 3
    arr[2] = 5
    arr[3] = 7

    fmt.Println(arr)
  • 切片定义后不能直接使用
    var sce []int
    //不能逐个初始化,会报错
    //sce[0] = 1
    //sce[1] = 3
    //sce[2] = 5

    //可以使用append函数添加数据
    sce = append(sce,1)
    sce = append(sce,3)
    sce = append(sce,5)
    sce = append(sce,7)
    sce = append(sce,9)

    //打印切片
    fmt.Println(sce)
    fmt.Println(len(sce))
    fmt.Println(cap(sce))
  • 计算数组的长度方式
    //计算数组长度的方式
    //第一种方式(推荐)使用len函数
    arr := [4]int{1,3,5,7}
    //length := len(arr)
    //fmt.Println(length)

    //第二种方式,使用unsafe.Sizeof函数计算(不推荐)
    length1 := unsafe.Sizeof(arr)
    length2 := unsafe.Sizeof(arr[0])
    fmt.Println(length1 / length2)
  • 计算切片的长度
    //计算切片的长度
    //第一种方式(推荐)使用len函数
    //注意点: 切片的长度不能使用unsafe.Sizeof函数计算
    //由于切片本质是结构体,所以unsafe.Sizeof计算的是结构体的字节数,不是指向数组的字节数
    sce := []int{1,3,5,6}
    length := len(sce)
    fmt.Println(length)
  • 切片与数组的传递
    • 数组传递是值传递
    • 切片传递是地址(指针)传递
package main

import "fmt"

func main() {
    /*
    1.数组作为函数参数是值传递,在函数内部修改形参是不会影响外部实参的值
    2.切片作为函数的参数是地址传递(指针), 在函数内修改形参, 会影响到函数外的实参
    */
    //arr := [4]int{1,3,4,5}
    //fmt.Println(arr)
    //change1(arr)
    //fmt.Println(arr)

    sce := []int{1,2,3,4}
    fmt.Println(sce)
    change2(sce)
    fmt.Println(sce)
    
}
//数组是值传递
func change1(arr [4]int)  {
arr[0] = 666
}

//切片是地址传递指针
func change2(sce []int)  {
    sce[0] = 666
}


可变参数

  • 可变参数底层实现就是切片
package main

import "fmt"

func main() {
    /*
    可变参数,底层其实就是一个切片
    */
    res := sum(10,20,30)
    fmt.Println(res)

}
//可变参数底层就是一个切片
//注意点: 当一个函数中定义可变参数时候,可变参数只能放在形参列表的最后面
func sum(nums ...int) (res int) {
    for _, value := range nums {
        res += value
    }
    return
}

相关文章

  • 10-Go语言数组和切片

    Go语言数组数组 一维数组 数组定义格式: var arr [3]int 数组的初始化方式先定义后初始化注意点:G...

  • Go 切片和数组

    数组 go创建数组和 c 语言类似,有如下两种方式: 切片 切片声明和数组类似,只是没有传递长度 创建二维切片,并...

  • Go语言切片

    // //Go语言切片 // /* // go语言切片是对数组的抽象 // Go 数组的长度不可改变,在特定场景中...

  • <>

    数组和切片 切片和数组的区别 数组是属于值类型。结构体,基础类型数据也属于值类型。 注意GO语言对于“传值和传引用...

  • go语言 数组和切片

    新手对于数组和切片要如何区分,概念比较模糊,看看下面的说明就懂了 记住,如果在[]运算符里指定了一个值,那么创建的...

  • Go语言数组和切片

    数组 数组概念 数组就是用于保存一组相同类型的数据 定义格式 操作数组的格式 数组的初始化 (赋值) 先定义再初...

  • Go语言数组和切片

    此处数组只讲Go语言中和C语言不一样的地方 格式不同:Go语言定义数组的格式:var ages [3]int 定义...

  • Go语言-数组和切片

    1 数组的定义 定义数组常规格式是:var 数组名 [元素数量] 元素类型 = {各元素},实际使用中,可以有很多...

  • Go语言--数组和切片

    一.数组1)定义: 2)初始化 二.切片1)定义: 2)初始化: 三.区别 数组是固定大小; 切片可以扩容 四.举...

  • golang入门到放弃:3.数组、切片、map

    数组 切片 数组和切片的区别 数组必须要指定长度,如果定义时不指定长度,go语言也会根据元素中的个数自动设置值数组...

网友评论

      本文标题:10-Go语言数组和切片

      本文链接:https://www.haomeiwen.com/subject/sowfoftx.html