3.9 Go Slice切片
3.9 Go Slice切片
- Go语言切片(Slice)
- 切片是
可动态变化的序列,是对数组的引用,引用类型,遵循引用传递的机制 - slice类型写作[ ]T,T是slice元素类型,
var s1 []int,s1就是切片变量
package main import "fmt" func main() {
//创建一个数组
var array1 [5]int = [...]int{11, 22, 33, 44, 55}
/*
创建切片,通过对数组的索引切片
s1 是切片名
array1[1:3]代表slice引用数组区间,索引1到索引3的值,注意取头不取尾,
*/
s1 := array1[1:4]
fmt.Println(array1)
fmt.Println(s1)
fmt.Println(len(s1))
fmt.Println(cap(s1))
}
运行结果
[11 22 33 44 55] //原本数组
[22 33 44] //切片的值
3 //切片元素长度
4 //切片容量
2. 切片原理
slice是一个轻量级数据结构,提供访问数组子序列元素的功能。
slice由三个部分构成,指针、长度、容量
指针:指针指向slice第一个元素对应的数组元素的地址。
长度:slice元素的数量,不得超过容量。
容量:slice开始的位置到底层数据的结尾。

package main import "fmt" func main() {
//创建数组,Months月份,1月份到12月份
months:=[...]string{"","January","February","March","April","May","June","July","August","September","October","November","December"}
//创建切片,对数组的引用
s1:=months[4:7]//[April May June]
s2:=months[6:9]//[June July August]
fmt.Println(s1)
fmt.Println(s2) //指针:指针指向slice`第一个元素`对应的`数组元素`的地址。
fmt.Printf("slice第一个元素地址%p\n",&s1[0])
fmt.Printf("对应数组元素的地址%p\n",&months[4])
}
对切片读写
package main import (
"fmt"
) func main() {
//创建数组data
data := [...]int{0, 1, 2, 3, 4, 5}
//切片s [2,3]
s := data[2:4]
//切片读写操作目标是底层数组data
s[0] += 100
s[1] += 200
fmt.Println(s)
fmt.Println(data)
}
运行结果
[102 203]
[0 1 102 203 4 5]
2.1. 创建切片的方式
- 定义切片,然后引用已经创建好的数组,数组可见
- 内置make函数创建切片,底层数组看不见,只能通过slice访问元素
make创建切片内存分配图

package main import (
"fmt"
)
/*
内置make函数,参数(类型,len,cap),注意cap大于len,容量可以省略,默认等于长度
切片有默认值
*/
var slice0 []int = make([]int, 10)
var slice1 = make([]int, 10)
var slice2 = make([]int, 10, 10) func main() {
fmt.Printf("make全局slice0 :%v\n", slice0)
fmt.Printf("make全局slice1 :%v\n", slice1)
fmt.Printf("make全局slice2 :%v\n", slice2)
fmt.Println("--------------------------------------")
slice3 := make([]int, 10)
slice4 := make([]int, 10)
slice5 := make([]int, 10, 10)
slice5[0] = 11
slice5[1] = 22
fmt.Printf("make局部slice3 :%v\n", slice3)
fmt.Printf("make局部slice4 :%v\n", slice4)
fmt.Printf("make局部slice5 :%v\n", slice5)
}
- 定义切片直接对应数组,如同make方式
package main import "fmt" func main() {
//第三种方式,原理类似make,数组看不见,由make维护
var s1 []int = []int{1, 2, 3, 4, 5}
fmt.Println(s1)
fmt.Println(len(s1))
fmt.Println(cap(s1))
}
4.遍历切片
package main import "fmt" func main() {
var arr [5]int = [...]int{11, 22, 33, 44, 55}
s1 := arr[1:4]
//for循环遍历
for i := 0; i < len(s1); i++ {
fmt.Printf("s1[%v]=%v\n", i, s1[i])
}
fmt.Println() //for range方式遍历切片
for i, v := range s1 {
fmt.Printf("索引i=%v 值v=%v\n", i, v)
}
}
5.切片案例
package main import "fmt" func main() {
var array1 = [...]int{11, 22, 33, 44}
slice1 := array1[1:4] //11,22,33
slice2 := array1[1:] //22,33,44
slice3 := array1[:] //11,22,33,44
slice4 := slice3[:2] //slice4=[11,22] 切片再切片
fmt.Println(slice1)
fmt.Println(slice2)
fmt.Println(slice3)
fmt.Println(slice4)
}
6.cap是内置函数,统计切片容量,最大存放多少元素
7.切片扩容,append内置函数,向尾部添加数据,返回新的slice对象
package main import "fmt" func main() {
//创建切片
var slice1 []int = []int{100, 200, 300}
fmt.Printf("slice1容量=%v 长度=%v\n", cap(slice1), len(slice1))
//给切片追加新元素
//容量扩容机制是2倍扩容
slice1 = append(slice1, 400)
fmt.Printf("slice1扩容后容量=%v 长度=%v\n", cap(slice1), len(slice1))
fmt.Println(slice1) //切片扩容切片,slice1... 语法糖代表展开切片元素
slice1=append(slice1,slice1...)
fmt.Println(slice1)
}
/*
append原理就是对底层数组扩容,go会创建新的数组,将原本元素拷贝到新的数组中
slice重新引用新的数组
这个数组不可见
*/
8.切片拷贝
package main import "fmt" func main() {
//创建切片
var slice1 []int = []int{11, 22, 33, 44}
//make创建切片,长度是10
var slice2 = make([]int, 10)
copy(slice2, slice1) //把slice1的值拷贝给slice2
fmt.Println(slice1) //[11 22 33 44]
fmt.Println(slice2) //[11 22 33 44 0 0 0 0 0 0]
//slice1和slice2数据独立,互不影响
slice1[0] = 123
fmt.Println(slice1)
fmt.Println(slice2)
}
9.全切片表达式
array[x:y:z]
x切片内容 [x:y]
Y切片长度: y-x
Z切片容量:z-x
package main import (
"fmt"
) //官网资料
// https://golang.google.cn/ref/spec#Slice_expressions
func main() {
//10:2代表索引10的元素是2
data := [...]int{0, 1, 2, 3, 4, 10: 2}
fmt.Println(data)
s := data[1:2:3] //data[start:end:数字-start] 这个s容量是3-1=2
fmt.Printf("扩容前s的容量是:%v\n", cap(s))
s = append(s, 100, 200) // 一次 append 两个值,超出 s.cap 限制。
fmt.Println(s, data) // 重新分配底层数组,与原数组无关。
fmt.Printf("扩容后s的容量=%v\n", cap(s)) //二倍扩容
fmt.Println(&s[0], &data[0]) // 比对底层数组起始指针。
}
3. string和slice的联系
1)string底层就是byte数组,因此string同样可以进行切片处理
package main import "fmt" func main() {
str1 := "yugo niubi"
//对str1进行切片
s1 := str1[:4]
fmt.Println(s1)//yugo
}
2)string修改的两种方式
package main import (
"fmt"
) func main() {
str1 := "yugo niubi"
//string是不可变的,也无法通过切片修改值
//str1[0] = 's' 编译器失败 //修改string的方法,需要string转化为[]byte,修改后转为string
arr1 := []byte(str1) //类型强转
arr1[0] = 'g'
str1 = string(arr1)
fmt.Printf("str1=%v\n", str1) //[]byte只能处理英文和数字,不能处理汉字,汉字3个字节,会出现乱码
//将string转为[]rune,按字符处理,兼容汉字
arr2 := []rune(str1)
arr2[0] = '于'
str1 = string(arr2)
fmt.Printf("str1=%v\n", str1)
}
3.9 Go Slice切片的更多相关文章
- golang:slice切片
一直对slice切片这个概念理解的不是太透彻,之前学习python的就没搞清楚,不过平时就用python写个工具啥的,也没把这个当回事去花时间解决. 最近使用go开发又遇到这个问题,于是打算彻底把这个 ...
- golang slice切片的原理以及内置函数cap, len
golang中slice(切片)是常用的类型, slice是对数组进行封装 package main import ( "fmt" "strconv") fun ...
- python定制类(1):__getitem__和slice切片
python定制类(1):__getitem__和slice切片 1.__getitem__的简单用法: 当一个类中定义了__getitem__方法,那么它的实例对象便拥有了通过下标来索引的能力. c ...
- golang基础---Slice切片
切片Slice在go语言中是单独的类型(指向底层的数组),不同于python(对可迭代对象操作的工具),注意区分数组和slice的区别 定义一个空slice,格式var s []int,这种既没有长度 ...
- Go语言核心之美 3.2-slice切片
Slice(切片)是长度可变的元素序列(与之相应,上一节中的数组是不可变的),每一个元素都有同样的类型.slice类型写作[]T.T是元素类型.slice和数组写法非常像,差别在于slice没有指定长 ...
- Go - Slice 切片
概述 切片是一种动态数组,比数组操作灵活,长度不是固定的,可以进行追加和删除. len() 和 cap() 返回结果可相同和不同. 声明切片 //demo_7.go package main impo ...
- Go(03) slice切片的使用
原文链接 http://www.limerence2017.com/2019/05/08/golang05/#more golang 的引用类型和内置类型变量 golang 中变量类型分为引用类型和值 ...
- [日常] Go语言圣经-Slice切片习题
1.Slice(切片)代表变长的序列,序列中每个元素都有相同的类型,一个slice类型一般写作[]T,其中T代表slice中元素的类型:slice的语法和数组很像,只是没有固定长度而已,slice的底 ...
- golang 数组以及slice切片
老虞学GoLang笔记-数组和切片 数组 Arrays 数组是内置(build-in)类型,是一组同类型数据的集合,它是值类型,通过从0开始的下标索引访问元素值.在初始化后长度是固定的,无法修改其 ...
随机推荐
- application/x-www-form-urlencoded ,multipart/form-data, text/plain
APPLICATION/X-WWW-FORM-URLENCODED MULTIPART/FORM-DATA TEXT/PLAIN 后台返回的数据响应的格式类型 application/x-www-fo ...
- SQLI-LABS学习笔记(二)
逼话少说,如有错误,烦请指出,谢谢 这两天生病,效率很低 第5关 打开页面 发现跟前几题不同,没有直接返回数据.. 加个单引号 You have an error in your SQL syntax ...
- Linux 文件常用权限
-rw------- (600) 只有所有者才有读和写的权限 -rw-r--r-- (644) 只有所有者才有读和写的权限,组群和其他人只有读的权限 -rwx------ (700) 只有所有者才有读 ...
- Qt 用户通过对话框选择文件
void class::on_pushButton_clicked() { fileFullPath = QFileDialog::getOpenFileName(this, tr("Sel ...
- docker中安装nginx,部署前端代码
最近在学习docker,初次接触,难免遇到磕磕碰碰,遂将其整理成博客,以便日后查看. 1.拉取nginx镜像 直接从官方镜像库拉取简单粗暴: docker pull nginx 2.运行 docker ...
- 解决Vue-cli3.0下scss文件编译过慢、卡顿问题
在使用Vue-cli 3.0构建的项目中,可能存在项目编译过慢的问题,具体表现在编译时会在某一进度比如40%时停顿,等好一会儿才能够编译完成.这使得浏览器中的实时预览也会卡顿,不利于我们快速查看效果, ...
- mycat入门部署安装
mycat是一种比较简单的中间件产品,可以帮助mysql进行分库,同时统一在一个逻辑库. 硬件环境:系统:centos 7.6数据库版本:5.7.19mycat:1.6..6.1 github上下载m ...
- Mysql使用规范及建议
MySQL数据库使用规范一.建表规约1.[强制]表达是与否概念的字段,必须使用is_xxx的方式命名,数据类型是unsigned tinyint (1表示是,0表示否) 说明:任何字段如果为非负数,必 ...
- 深入实践Spring Boot1.4 运行与发布
1.4 运行与发布 本章实例工程的完整代码可以使用IDEA直接从GitHub的https://github.com/chen-fromsz/spring-boot-hello.git中检出,如图1-1 ...
- 啃算法:归并排序及JavaScript实现
在学习归并排序之前,有必要了解分治法,因为归并排序正是应用了分治模式.(基本定义摘自<算法导论>) 一.分治法 1.思想: 将原问题分解为几个规模较小但类似于原问题的子问题,递归地求解这些 ...