go基础 slice切片

go基础 slice切片,第1张

slice切片的定义初始化方法

go的切片有三种定义和初始化的方法,此外注意,数组的传递是值传递,但切片是引用传递:

程序:

package main

import "fmt"

func main() {
	// 数组的问题在于大小确定,不能修改,而切片是一个动态数组
	// 切片定义方法1:
	s1 := [] string {"C", "C++", "GO", "python"}
	fmt.Printf("%T\n", s1)	// []string是切片类型
	fmt.Println(len(s1))	// 4
	fmt.Println(s1)		// [C C++ GO python]


	//切片的定义方法2:make
	// make定义切片需要有长度,但长度是可变的
	s2 := make([]string, 5)
	fmt.Printf("%T\n", s2)	// []string是切片类型
	fmt.Println(len(s2))	// 5
	fmt.Println(s2)		// []

	// 方法3:数组变切片
	arr := [5] string {"C", "C++", "GO", "python", "java"}
	s3 := arr[1:4]	//成为了切片
	fmt.Printf("%T\n", s3)	// []string是切片类型
	fmt.Printf("%T\n", arr)	// [5]string是数组类型
	fmt.Println(len(s3))	// 3
	fmt.Println(s3)		// [C++ GO python]

	// 方法4:new
	s4 := new([] string)
	fmt.Printf("%T\n", s4)	// *[]string
	//fmt.Println(len(s4))	// 没有长度
	fmt.Println(s4)		// &[]
	
	// 注意,数组的传递是值传递,但切片是引用传递
}

运行结果:

 slice切片的基本 *** 作

切片的基本 *** 作增删改查、复制等需要掌握

程序:

package main

import "fmt"

func main() {
	// slice切片的基本 *** 作
	s1 := [] string {"C", "C++", "GO", "python"}

	// 1. 添加方法:append
	s1 = append(s1, "Ajax", "JQuery")
	fmt.Println(s1)

	// 2. 复制方法:copy
	s2 := [] string{}
	copy(s2, s1)
	fmt.Println(s2)		//为什么s2为空,因为没有给定义长度

	// 拷贝的时候,目标对象长度为多少就只能复制多少
	s3 := make([] string, len(s1))
	copy(s3, s1)
	fmt.Println(s3)

	// 3.两个切片合并
	s2 = append(s1, s3...)		// 省略号是规定的参数
	fmt.Println(s2)

	// 4.数组中删除元素:把数组变成切片,再将两个切片合并
	s4 := s2[:]		// 把数组变成切片
	s4 = append(s2[0:2], s2[4:]...)		// 再将两个切片合并
	fmt.Println(s4)

	//5.如何判断元素在切片中:使用循环查询


}

运行结果:

go语言slice的原理

slice有容量(cap)和长度(len)两个概念。

程序:

package main

import "fmt"

func main() {
	// 不设置cap的时候,len和cap大小一致
	s1 := [] string {"C", "C++", "GO", "python"}
	fmt.Println(len(s1))
	fmt.Println(cap(s1))

	s2 := make([] int, 5)
	fmt.Println(len(s2))
	fmt.Println(cap(s2))

	s3 := make([] int, 5, 8)	// 设置了容量cap
	fmt.Println(len(s3))	// 5
	fmt.Println(cap(s3))	// 8

	// 通过数组取切片:cap为切片起始位置之后的数组长度
	s4 := [10] int {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	s5 := s4[2: 5]
	fmt.Println(len(s5))	 // 3
	fmt.Println(cap(s5))	// 8
}

运行结果:

slice的底层是使用数组实现的,同一个数组的切片会共享内存,但如果切片扩容超过切片的原有容量cap会触发扩容机制,该切片就会自己独立开辟全新内存空间。

slice的append扩容问题:扩容阶段因为需要整体开辟全新的内存空间,因此扩容阶段会影响速度。python的list中底层实际上也是数组,也会面临扩容影响速度的问题。python的同一list中可以存不同的数据类型。

go的扩容机制:

程序示例:

运行结果:

go的数组和切片的值传递是引用传递。python的list进行切片以后返回的是全新的的list。

当append函数遇到make会产生的坑 

make创建切片的时候,如果有初始长度,则append函数后,该插入值在初始长度之后。

程序:

import "fmt"

func main() {
	s1 := make([] int, 5)
	s1 = append(s1, 6)
	fmt.Println(s1)
}

运行结果:

[0 0 0 0 0 6]

在没有初始长度的情况下,执行append函数结果如下:

程序:

package main

import "fmt"

func main() {
	s1 := make([] int, 0)
	s1 = append(s1, 6)
	fmt.Println(s1)
}

运行结果:

[6]

对比python程序

程序示例:

# python

l1 = []
print(l1)
l1.append(1)
print(l1)

运行结果:

[]
[1]

python和go的切片 *** 作对比

slice的append扩容问题:扩容阶段因为需要整体开辟全新的内存空间,因此扩容阶段会影响速度。python的list中底层实际上也是数组,也会面临扩容影响速度的问题。python的同一list中可以存不同的数据类型。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/995283.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存