go之切片


定义

  切片是由数组建立的一种方便、灵活且功能强大的包装,切片本身不拥有任何数据。他们只是对现有数组的引用。切片底层以来于数组,是对数组的引用

  底层数组如果发生变化,切片也变了;切片发生变化,层数组也变化

切片定义

  基于数组生成切片

package main

import "fmt"

func main() {
	var a [10]int
	var s = a[:]
	fmt.Println(s)

}
//[0 0 0 0 0 0 0 0 0 0]

  注意点

package main

import "fmt"

func main() {
	var a [10]int
	//var s = a[:]  // 把数组从第0个位置切到最后一个位置,赋值给s切片
	var s []int=a[:]  // 中括号中只要不放任何东西就是切片,放了数字就是数组
	fmt.Println(s)
}

切片定义并初始化

  切片只定义不初始化,默认0值为nil

  通过make初始化

package main

import "fmt"

func main() {
	var s []int=make([]int,3,4)
	fmt.Println(s)
}
//[0 0 0]

  直接定义并初始化

package main

import "fmt"

func main() {
	var s []int=[]int{3,4,5}
	fmt.Println(s)
}
//[3 4 5]

切片追加元素

  数组不允许追加元素,切片可以

package main

import "fmt"

func main() {
	var a [10]int = [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	var b []int = a[7:8]
	//b[0]=999
	//fmt.Println(a)  //[1 2 3 4 5 6 7 999 9 10]
	//fmt.Println(b)  //[999]


	b = append(b, 888)
	fmt.Println("切片b:", b) //切片b: [8 888]
	fmt.Println("数组a:", a) //数组a: [1 2 3 4 5 6 7 8 888 10]
	fmt.Println(len(b))    //切片长度是2
	fmt.Println(cap(b))    //切片容量是3


	b = append(b, 777)
	fmt.Println("切片b:", b) //切片b: [8 888 777]
	fmt.Println("数组a:", a) //数组a: [1 2 3 4 5 6 7 8 888 777]
	fmt.Println(len(b))    //切片长度是3
	fmt.Println(cap(b))    //切片容量是3

	//现在长度是3,容量是3,如果再追加666的话久超过了底层数组大小
	//如果超过底层数组大小:1.重新申请一个底层数据,把切片的值copy过去,2.切片的容量变为原来切片容量的两倍,3.现在这个切片跟原来的数组久没有关系了
	b=append(b,666)
	fmt.Println("切片b:",b)  //切片b: [8 888 777 666]
	fmt.Println("数组a:",a)  //数组a: [1 2 3 4 5 6 7 8 888 777]
	fmt.Println(len(b))  //切片长度是4
	fmt.Println(cap(b))  //切片长度是6

	//修改切片,不会影响最原来的数组
	b[0]=9
	a[9]=7
	fmt.Println("切片b:",b)  //切片b: [9 888 777 666]
	fmt.Println("数组a:",a)  //数组a: [1 2 3 4 5 6 7 8 888 7]
}

make创建切片

import "fmt"

func main() {
	var s =make([]int,3,4)
	fmt.Println(s)  //[0 0 0]
	fmt.Println(len(s))  //3
	fmt.Println(cap(s))  //4
}

切片的零值

  切片的零值为:nil

import "fmt"

func main() {
	var s []int=make([]int,2,2)  // 定义,有初始化
	fmt.Println(s[0])  //0
	if s==nil{
		fmt.Println("我是nil")
	}else {
		fmt.Println("我不是nil")  //我不是nil
	}
}
import "fmt"

func main() {
	var s []int  // 只定义,没有初始化
	fmt.Println(s)  //[]
	if s==nil{
		fmt.Println("我是nil")  //我是nil
	}else {
		fmt.Println("我不是nil")  
	}
}

切片的参数传递

  切片是引用类型,当参数传递在函数中修改会影响原来的

  go语言的参数传递都是copy传递,因为切片是个引用(地址,指针),把切片复制了一份传入了。

  由于切片是引用,在函数中根据引用改了值,改了原来的底层数组,大家都会手影响

package main

import "fmt"

func main() {
	var s []int=[]int{3,4,5}
	testS(s)
	fmt.Println("调用之后:",s)  //调用之后: [999 4 5]
}

func testS(s []int)  {  // 在函数中追加切片,一定要注意有没有超过容量,如果超过了容量,超过后再改的值,就不会影响原来的了
	fmt.Println(s)   //[3 4 5]
	s[0]=999  //[999 3 5]
	s=append(s,888,777)  //[999 4 5 888 777]
	s[1]=666  //[999 666 5 888 777]
	fmt.Println(s)  // [999 666 5 888 777]

}
package main

import "fmt"

func main() {
	var s []int = make([]int, 3, 4)
	testS(s)
	fmt.Println("调用之后:", s) //调用之后: [999 0 0]
}
func testS(s []int) { // 在函数中追加切片,一定要注意有没有超过容量,如果超过了容量,超过后再改的值,就不会影响原来的了
	fmt.Println(s)          //[0 0 0]
	s[0] = 999              //[999 0 0]  会影响原来的
	s = append(s, 888, 777) //[999 0 0 888 777],追加了超过了底层数组,不依赖于原来的数组了
	s[1] = 666              //[999 666 0 888 777]  // 不影响原来的数组了
	fmt.Println(s)          // [999 666 0 888 777]
}

copy切片

package main

import "fmt"

func main() {
	var a [100000]int
	var b =a[:3]
	fmt.Println(b)  //[0 0 0]
	b[0]=999
	b[2]=222
	fmt.Println(b)  //[999 0 222]  使用b,虽然只用3个值,但是底层数组很大,内存占用大
	//把b这个切片,copy另一个新切片上
	var c= make([]int,2,2)  // 基于的底层数组,数组大小是3
	copy(c,b)
	fmt.Println(c)  //[999 0]
}

多维切片

  每一层都要初始化

import "fmt"

func main() {
	//var s [][]int=make([][]int,2,2)
	//var s [][]int
	//fmt.Println(s[0])  //[]
	//fmt.Println(s[0][0])  // 报错,第二层没有初始化

	// 循环切片  两层for循环,跟数组一样
	var s [][]int=[][]int{{2,3},{4,4,4,5},{6,7,8}}
	fmt.Println(s)  //[[2 3] [4 4 4 5] [6 7 8]]
	fmt.Println(s[0][1])  //3
}

  

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/289820.html

(0)
上一篇 2022年9月16日
下一篇 2022年9月16日

相关推荐

发表回复

登录后才能评论