3.9 Go Slice切片

  1. Go语言切片(Slice)
  2. 切片是可动态变化的序列,是对数组的引用引用类型,遵循引用传递的机制
  3. 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. 创建切片的方式

  1. 定义切片,然后引用已经创建好的数组,数组可见
  2. 内置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)
}
  1. 定义切片直接对应数组,如同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切片的更多相关文章

  1. golang:slice切片

    一直对slice切片这个概念理解的不是太透彻,之前学习python的就没搞清楚,不过平时就用python写个工具啥的,也没把这个当回事去花时间解决. 最近使用go开发又遇到这个问题,于是打算彻底把这个 ...

  2. golang slice切片的原理以及内置函数cap, len

    golang中slice(切片)是常用的类型, slice是对数组进行封装 package main import ( "fmt" "strconv") fun ...

  3. python定制类(1):__getitem__和slice切片

    python定制类(1):__getitem__和slice切片 1.__getitem__的简单用法: 当一个类中定义了__getitem__方法,那么它的实例对象便拥有了通过下标来索引的能力. c ...

  4. golang基础---Slice切片

    切片Slice在go语言中是单独的类型(指向底层的数组),不同于python(对可迭代对象操作的工具),注意区分数组和slice的区别 定义一个空slice,格式var s []int,这种既没有长度 ...

  5. Go语言核心之美 3.2-slice切片

    Slice(切片)是长度可变的元素序列(与之相应,上一节中的数组是不可变的),每一个元素都有同样的类型.slice类型写作[]T.T是元素类型.slice和数组写法非常像,差别在于slice没有指定长 ...

  6. Go - Slice 切片

    概述 切片是一种动态数组,比数组操作灵活,长度不是固定的,可以进行追加和删除. len() 和 cap() 返回结果可相同和不同. 声明切片 //demo_7.go package main impo ...

  7. Go(03) slice切片的使用

    原文链接 http://www.limerence2017.com/2019/05/08/golang05/#more golang 的引用类型和内置类型变量 golang 中变量类型分为引用类型和值 ...

  8. [日常] Go语言圣经-Slice切片习题

    1.Slice(切片)代表变长的序列,序列中每个元素都有相同的类型,一个slice类型一般写作[]T,其中T代表slice中元素的类型:slice的语法和数组很像,只是没有固定长度而已,slice的底 ...

  9. golang 数组以及slice切片

    老虞学GoLang笔记-数组和切片   数组 Arrays 数组是内置(build-in)类型,是一组同类型数据的集合,它是值类型,通过从0开始的下标索引访问元素值.在初始化后长度是固定的,无法修改其 ...

随机推荐

  1. 2019-2020-1 20199326《Linux内核原理与分析》第六周作业

    本周学习了庖丁解牛Linux内核分析第五章:系统调用的三层机制(下),是上一章的延续 实验内容:使用gdb跟踪分析一个系统调用内核函数 上周实验我选择的getpid这个系统系统调用,这次准备使用gdb ...

  2. Linux系统目录结构:目录层次标准、常用目录和文件

    1. 目录层次标准FHS FHS(Filesystem Hierarchy Standard)目录层次标准,是Linux的目录规范标准.   FHS定义了两层规范: 第一层:是"/" ...

  3. oracle查询当前系统时间前10天的数据

    select * from eo_c_order t where t.create_time>systimestamp-interval'1'day; 转载于:https://www.cnblo ...

  4. flex学习

            今天看视频学习的时候,发现css有一个 flex 的属性,非常的好用,为了让自己能够熟记,特意来分享一下flex的用法. 首先,采用Flex布局的元素,称为Flex容器(flex co ...

  5. P6474 [NOI Online #2 入门组] 荆轲刺秦王

    P6474 [NOI Online #2 入门组] 荆轲刺秦王 bfs+差分+卡常 本来我其实是场内选手,但是因为记错提交时间,晚了半小时才交,交不上了,就自动降级为了场外选手 题面复杂,不简述了 首 ...

  6. Python (深浅拷贝)

    1.深拷贝  -->  克隆一份,修改拷贝后的内容不对原对象内容产生影响 拷贝后修改序列中元素内容,注意:被修改的元素不能为一个序列中的某个值 a = [["北京多测师",& ...

  7. java :技巧

    如何查看安装的jdk的路径? 答: 1.情况一:已安装,且环境已配置好 在window环境下,我们先执行java -version 指令查看是否已经配置过java了,如果查到java版本则证明已经安装 ...

  8. 虚拟化云计算平台Proxmox VE

    1.虚拟化技术介绍 1.1.OpenVZ 简介 OpenVZ 是开源软件, 是基于Linux平台的操作系统级服务器虚拟化解决方案,它是基于Linux内核和作业系统的操作系统级虚拟化技术. OpenVZ ...

  9. Centos 搭建wordpress个人博客

    1.装apache.mariadb yum install httpd mariadb-server php php-mysql -ysystemctl start httpdsystemctl en ...

  10. 配置中心Apollo搭建全过程

    总体架构 用户在Portal操作配置发布 Portal调用Admin Service的接口操作发布 Admin Service发布配置后,发送ReleaseMessage给各个Config Servi ...