Go语言中切片slice的声明与使用

一、切片slice的定义

    Go语言中的切片,是一种动态数组,它是对数组的扩展。

  • 与数组相⽐,切⽚的⻓度是不固定的,可以追加元素,在追加时可能使切⽚的容量增⼤。
  • 切⽚本身没有任何数据,它们只是对现有数组的引⽤。
  • 切⽚与数组相⽐,不需要设定⻓度,在[]中不⽤设定值,相对来说⽐较⾃由。
  • 从概念上⾯来说slice像⼀个结构体,这个结构体包含了三个元素:
    1)指针,指向数组中slice指定的开始位置;
    2)⻓度,即slice的⻓度;
    3)最⼤⻓度,也就是slice开始位置到数组的最后位置的⻓度。

二、切片的语法

2.1 声明切片

    2.1.1 声明⼀个未指定⻓度的数组来定义切⽚

  • var identifier []type
  • 切⽚不需要说明⻓度;
  • 该声明⽅式,且未初始化的切⽚为空切⽚。该切⽚默认为 nil,⻓度为 0。

    2.1.2 使⽤make()函数来创建切⽚:

  • var slice1 []type = make([]type, len)
  • 可以简写为: slice1 := make([]type, len)
  • 可以指定容量,其中capacity为可选参数: make([]T, length, capacity)

//mySlice.go

package main

import (
	"fmt"
)

func main() {
	//fmt.Println("Hello World!")
	//1)切片
	var numbers = make([]int, 3, 5)
	fmt.Printf("%T\n", numbers)
	fmt.Printf("len=%d cap=%d slice=%v\n", len(numbers), cap(numbers), numbers)
}

效果如下:

图(1) 打印切片的长度、容量和数据元素

2.2 初始化

2.2.1 直接初始化切片

    s :=[] int {1,2,3 }

2.2.2 通过数组截取来初始化切片

   数组: arr := [5]int {1,2,3,4,5}
  • 1)s := arr[:]
    切⽚中包含数组所有元素
  • 2)s := arr[startIndex:endIndex]
    将arr中从下标startIndex到endIndex-1 下的元素创建为⼀个新的切⽚(前闭后开),⻓度为endIndex-startIndex
  • 3)s := arr[startIndex:]
    缺省endIndex时将表示⼀直到arr的最后⼀个元素;
  • 4)s := arr[:endIndex]
    缺省startIndex时将表示从arr的第⼀个元素开始。

2.2.3 通过切片截取来初始化切片

    可以通过设置下限及上限来设置截取切⽚ [lower-bound:upper-bound]
//mySlice2.go

package main

import (
	"fmt"
)

func printSlice(x []int) {
	fmt.Printf("len=%d cap=%d slice=%v\n", len(x), cap(x), x)
}

func main() {
	//fmt.Println("Hello World!")
	//1)切片
	// var numbers = make([]int, 3, 5)
	// fmt.Printf("%T\n", numbers)
	// fmt.Printf("len=%d cap=%d slice=%v\n", len(numbers), cap(numbers), numbers)

	//2)截取切片
	numbers := []int{0, 1, 2, 3, 4, 5, 6, 7, 8}
	printSlice(numbers)

	//打印原始切片
	fmt.Println("numbers== ", numbers)

	//打印子切片,从索引1到索引4,左闭右开,[1,4)
	fmt.Println("numbers[1:4]== ", numbers[1:4])

	//默认下限为0,[0,3)
	fmt.Println("numbers[:3]== ", numbers[:3])

	//默认上限为len(s),[4,len(s))
	fmt.Println("numbers[4:]== ", numbers[4:])

	//打印子切片,[0,2)
	number2 := numbers[:2]
	printSlice(number2)

	//打印子切片,[2,5)
	number3 := numbers[2:5]
	printSlice(number3)
}

    效果如下:

图(2) 通过截取方法,来获取切片

三、切片里的len()和cap()函数

  • 切⽚的⻓度是切⽚中元素的数量。
  • 切⽚的容量是从创建切⽚的索引开始的底层数组中元素的数量。
  • 切⽚是可索引的,并且可以由 len() ⽅法获取⻓度, 切⽚提供了计算容量的⽅法 cap(), 可以测量切⽚最⻓可以达到多少。 [数组计算cap()结果与len()相同]。
  • 切⽚实际的是获取数组的某⼀部分, len切⽚<=cap切⽚<=len数组。
  • cap()的结果决定了切⽚截取的注意细节。
    //mySlice02.go
// mySliceCap project main.go
package main

import (
	"fmt"
)

func main() {
	sliceCap()
}

func sliceCap() {
	arry := [...]string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"}
	fmt.Println("cap(arry)= ", cap(arry), arry)

	//截取数组,形成切片
	sli01 := arry[2:8]
	fmt.Printf("%T\n", sli01)
	fmt.Println("cap(sli01)= ", cap(sli01), sli01)

	sli02 := arry[4:7]
	fmt.Println("cap(sli02)= ", cap(sli02), sli02)

	//截取切片,形成切片
	sli03 := sli01[3:9]
	fmt.Println("截取sli01[3:9]后形成sli03: ", sli03)

	sli04 := sli02[4:7]
	fmt.Println("截取sli02[4:7]后形成sli04: ", sli04)

	//切片是引用类型
	sli04[0] = "x"
	fmt.Print(arry, sli01, sli02, sli03, sli04)

}


    运行结果如下:

图(3) 切片里的cap()函数

四、切片是引用类型

  • slice没有⾃⼰的任何数据,它只是底层数组的⼀个引⽤,对slice所做的任何修改都将反映在底层数组中。
  • 数组是值类型,⽽切⽚是引用类型。

    修改数组的案例,如下:
//mySlice04.go

// mySliceCmp project main.go
package main

import (
	"fmt"
)

func main() {
	a := [4]float64{67.7, 89.8, 21, 78}
	b := []int{2, 3, 5}
	fmt.Printf("变量a -- 地址: %p, 类型: %T, 数值: %v, 长度: %d\n", &a, a, a, len(a))
	fmt.Printf("变量b -- 地址: %p, 类型: %T, 数值: %v, 长度: %d\n", &b, b, b, len(b))
	c := a
	d := b
	fmt.Printf("变量c -- 地址: %p, 类型: %T, 数值: %v, 长度: %d\n", &c, c, c, len(c))
	fmt.Printf("变量d -- 地址: %p, 类型: %T, 数值: %v, 长度: %d\n", &d, d, d, len(d))
	a[1] = 200
	fmt.Println("a= ", a, " c= ", c)
	d[0] = 100
	fmt.Println("b= ", b, " d= ", d)
}

    运行结果如下:

图(4)修改数组里的值
  • 修改切⽚数值
        当多个⽚共享相同的底层数组时,每个元素所做的更改将在数组中反映出来。
        修改切片里的值,案例如下:
    //mySlice04.go
// mySliceChg project main.go
package main

import (
	"fmt"
)

func main() {
	//定义数组
	arry := [3]int{1, 2, 3}

	//根据数组截取切片
	nums1 := arry[:]
	nums2 := arry[:]
	fmt.Println("arry= ", arry)

	nums1[0] = 100
	fmt.Println("arry= ", arry)

	nums2[1] = 200
	fmt.Println("arry= ", arry)

	fmt.Printf("变量arry  --地址: %p\n", &arry)
	fmt.Printf("变量nums1 --地址: %p\n", &nums1)
	fmt.Printf("变量nums2 --地址: %p\n", &nums2)
}

    运行结果如下:

图(5) 修改切片里的值
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页