广告
返回顶部
首页 > 资讯 > 后端开发 > GO >golang中的空slice案例
  • 203
分享到

golang中的空slice案例

2024-04-02 19:04:59 203人浏览 薄情痞子
摘要

golang中允许对值为 nil 的 slice 添加元素 package main func main() { var s []int s = append(s, 1)

golang中允许对值为 nil 的 slice 添加元素


package main 
func main() {
 var s []int
 s = append(s, 1)
}

运行成功~

补充:golang slice 详解

一、数组切片的使用


func main() {
	//1.基于数组创建数组切片
	var array [10]int = [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	var slice = array[1:7] //array[startIndex:endIndex] 不包含endIndex
	//2.直接创建数组切片
	slice2 := make([]int, 5, 10)
	//3.直接创建并初始化数组切片
	slice3 := []int{1, 2, 3, 4, 5, 6}
	//4.基于数组切片创建数组切片
	slice5 := slice3[:4]
	//5.遍历数组切片
	for i, v := range slice3 {
		fmt.Println(i, v)
	}
	//6.len()和cap()
	var len = len(slice2) //数组切片的长度
	var cap = cap(slice)  //数组切片的容量
	fmt.Println("len(slice2) =", len)
	fmt.Println("cap(slice) =", cap)
	//7.append() 会生成新的数组切片
	slice4 := append(slice2, 6, 7, 8)
	slice4 = append(slice4, slice3...)
	fmt.Println(slice4)
	//8.copy() 如果进行操作的两个数组切片元素个数不一致,将会按照个数较小的数组切片进行复制
	copy(slice2, slice3) //将slice3的前五个元素复制给slice2
	fmt.Println(slice2, slice3)
}

二、数组切片数据结构分析

数组切片slice的数据结构如下,一个指向真实array地址的指针ptr,slice的长度len和容量cap


// slice 数据结构
type slice struct {
	array unsafe.Pointer 
	len   int            
	cap   int            
}

当传参时,函数接收到的参数是数组切片的一个复制,虽然两个是不同的变量,但是它们都有一个指向同一个地址空间的array指针,当修改一个数组切片时,另外一个也会改变,所以数组切片看起来是引用传递,其实是值传递。

三、append()方法解析

3.1 数组切片不扩容的情况

运行以下代码思考一个问题:s1和s2是指向同一个底层数组吗?


func main() {
	array := [20]int{1, 2, 3, 4, 5, 6, 7, 8, 9}
	s1 := array[:5]
	s2 := append(s1, 10)
	fmt.Println("s1 =", s1)
	fmt.Println("s2 =", s2)
	s2[0] = 0
	fmt.Println("s1 =", s1)
	fmt.Println("s2 =", s2)
}

输出结果:

s1 = [1 2 3 4 5]

s2 = [1 2 3 4 5 10]

s1 = [0 2 3 4 5]

s2 = [0 2 3 4 5 10]

由第一行和第二行结果看来,似乎这是指向两个不同的数组;但是当修改了s2,发现s1也跟着改变了,这又表明二者是指向同一个数组。到底真相是怎样的呢?

运行以下代码:


import (
	"fmt"
	"unsafe"
)
type Slice struct {
	ptr unsafe.Pointer // Array pointer
	len int            // slice length
	cap int            // slice capacity
}
func main() {
	array := [20]int{1, 2, 3, 4, 5, 6, 7, 8, 9}
	s1 := array[:5]
	s2 := append(s1, 10)
	s2[0] = 0
	// 把slice转换成自定义的 Slice struct
	slice1 := (*Slice)(unsafe.Pointer(&s1))
	fmt.Printf("ptr:%v len:%v cap:%v \n", slice1.ptr, slice1.len, slice1.cap)
	slice2 := (*Slice)(unsafe.Pointer(&s2))
	fmt.Printf("ptr:%v len:%v cap:%v \n", slice2.ptr, slice2.len, slice2.cap)
}

输出结果:

ptr:0xc04205e0a0 len:5 cap:20

ptr:0xc04205e0a0 len:6 cap:20

由结果可知:ptr指针存储的是数组中的首地址的值,并且这两个值相同,所以s1和s2确实是指向同一个底层数组。

但是,这两个数组切片的元素不同,这个可以根据首地址和数组切片长度len来确定不同的数组切片应该包含哪些元素,因为s1和s2虽然指向同一个底层数组,但是二者的len不同。通过这个demo,也验证了数组切片传参方式也是值传递。

3.2 数组切片扩容的情况:

运行以下代码,思考与不扩容情况的不同之处,以及为什么


func main() {
	s1 := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
	s2 := append(s1, 10)
	fmt.Println("s1 =", s1)
	fmt.Println("s2 =", s2)
	s2[0] = 0
	fmt.Println("s1 =", s1)
	fmt.Println("s2 =", s2)
}

输出结果:

s1 = [1 2 3 4 5 6 7 8 9]

s2 = [1 2 3 4 5 6 7 8 9 10]

s1 = [1 2 3 4 5 6 7 8 9]

s2 = [0 2 3 4 5 6 7 8 9 10]

根据结果我们发现,修改s2后,s1并未改变,这说明当append()后,s1和s2并未指向同一个底层数组,这又是为什么呢?

同样,我们接着运行以下代码:


import (
	"fmt"
	"unsafe"
)
type Slice struct {
	ptr unsafe.Pointer // Array pointer
	len int            // slice length
	cap int            // slice capacity
}
func main() {
	s1 := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
	s2 := append(s1, 10)
	fmt.Println("s1 =", s1)
	fmt.Println("s2 =", s2)
	s2[0] = 0
	fmt.Println("s1 =", s1)
	fmt.Println("s2 =", s2)
	// 把slice转换成自定义的 Slice struct
	slice1 := (*Slice)(unsafe.Pointer(&s1))
	fmt.Printf("ptr:%v len:%v cap:%v \n", slice1.ptr, slice1.len, slice1.cap)
	slice2 := (*Slice)(unsafe.Pointer(&s2))
	fmt.Printf("ptr:%v len:%v cap:%v \n", slice2.ptr, slice2.len, slice2.cap)
}

输出结果:

s1 = [1 2 3 4 5 6 7 8 9]

s2 = [1 2 3 4 5 6 7 8 9 10]

s1 = [1 2 3 4 5 6 7 8 9]

s2 = [0 2 3 4 5 6 7 8 9 10]

ptr:0xc04207a000 len:9 cap:9

ptr:0xc04207c000 len:10 cap:18

由结果可知:append()后,s1和s2确实指向了不同的底层数组,并且二者的数组容量cap也不相同了。

过程是这样的:当append()时,发现数组容量不够用,于是开辟了新的数组空间,cap变为原来的两倍,s2指向了这个新的数组,所以当修改s2时,s1不受影响

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。如有错误或未考虑完全的地方,望不吝赐教。

您可能感兴趣的文档:

--结束END--

本文标题: golang中的空slice案例

本文链接: https://www.lsjlt.com/news/124643.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • golang中的空slice案例
    golang中允许对值为 nil 的 slice 添加元素 package main func main() { var s []int s = append(s, 1) ...
    99+
    2022-11-12
  • Golang中slice删除元素的性能实例对比分析
    本篇内容主要讲解“Golang中slice删除元素的性能实例对比分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Golang中slice删除元素的性能实例对比分析”吧!我的电脑配置:☁ &nb...
    99+
    2023-07-02
  • 一文浅析Golang中的切片(Slice)
    本篇文章带大家学习一下Golang,聊聊Go语言基础中的切片(Slice),希望对大家有所帮助。1.切片的定义从上一节我们知道,因为数组的长度是固定的并且数组长度属于类型的一部分,数组a中已经有三个元素了,我们不能再继续往数组a中添加新元素...
    99+
    2023-05-14
    切片 Golang go语言 Go
  • Golang中的Slice底层如何实现
    这篇“Golang中的Slice底层如何实现”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Golang中的Slice底层如何...
    99+
    2023-07-05
  • Golang中slice删除元素的性能对比
    目录我的电脑配置:直接上代码:Benchmark结果:解释:总结在我写的blog中,这个算是参与度比较高的,所以有必要把程序写的更加容易理解一些。 我的电脑配置: ☁  b...
    99+
    2022-11-13
  • 深入了解Golang中的Slice底层实现
    目录1 Go数组2 切片的数据结构3 创建切片3.1 方法一:make3.2 方法二:字面量4 nil和空切片5 切片扩容5.1 扩容策略5.2 底层数组是不是新地址range遍历数...
    99+
    2023-02-26
    Golang Slice实现 Golang Slice Go Slice
  • 深入了解Golang中Slice切片的使用
    目录写在前面上代码分析原因总结写在前面 周日下午在家学习,看到一个关于切片的问题,在网上找了一些资料,做个总结。 上代码 func main() { sl := make([]in...
    99+
    2023-02-27
    Golang Slice切片使用 Golang Slice切片 Golang Slice
  • Golang中Slice的分析与使用源码解析
    目录1、slice结构体2、slice初始化3、append操作4、slice截取5、slice深拷贝6、值传递还是引用传递参考文献1、slice结构体 首先我们来看一段代码 pac...
    99+
    2023-03-09
    go slice使用 go slice
  • 详解Golang中删除slice元素的几种方法
    Golang是一种流行的编程语言,因为它简单、高效和易于学习。当你在使用Golang进行编程时,你可能会遇到需要从slice中删除元素的情况。在这篇文章中,我们将会讨论在Golang中删除slice元素的几种方法。方法一:使用append函...
    99+
    2023-05-14
  • Oracle中表空间offline的三种参数对比案例
    Oracle数据库管理中,对表空间操作是基础中的基础。其中,表空间Offline是我们经常接触的。同数据文件Offline一起,构成了Oracle维护数据一致性的重要体系结构。 &n...
    99+
    2022-10-18
  • golang中的空接口怎么用
    这篇文章给大家分享的是有关golang中的空接口怎么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。1、空接口Golang 中的接口可以不定义任何方法,没有定义任何方法的接口就是空接口。空接口表示,没有任何约束,...
    99+
    2023-06-14
  • golang内存对齐的概念及案例详解
    什么是内存对齐 为保证程序顺利高效的运行,编译器会把各种类型的数据安排到合适的地址,并占用合适的长度,这就是内存对齐。 每种类型的对齐值就是它的对齐边界,内存对齐要求数据存储地址以及...
    99+
    2022-11-13
  • python 与GO中操作slice,list的方式实例代码
    python 与GO中操作slice,list的方式实例代码 GO代码中遍历slice,寻找某个slice,统计个数。 type Element interface{} func main() { ...
    99+
    2022-06-04
    实例 操作 代码
  • Oracle更改表空间中数据文件位置的案例
    这篇文章主要介绍了Oracle更改表空间中数据文件位置的案例,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。表空间概述Oracle的表空间属于...
    99+
    2022-10-18
  • Golang实现http文件上传小功能的案例
    看代码吧~ package main import ( "fmt" "io" "net/http" "os" ) func main() { http.HandleFu...
    99+
    2022-11-12
  • 【Golang】案例为基浅谈Go的变量与常量
    📓推荐网站(不断完善中):个人博客 📌个人主页:个人主页 👉相关专栏:CSDN专栏、个人专栏 🏝立志赚钱,干活想躺,瞎分享的...
    99+
    2023-08-31
    golang java 算法 后端
  • golang中的空接口使用详解
    目录1、空接口2、类型断言3、结构体值接收者和指针接收者实现接口的区别4、一个结构体实现多个接口5、接口嵌套6、Golang中空接口和类型断言使用细节1、空接口 Golang 中的接...
    99+
    2022-11-12
  • python sqlite3 判断cursor的结果是否为空的案例
    len(list(cursor))若是0则为空 举例: import sqlite3 # CREATE db = sqlite3.connect("E:/Pycharm/w...
    99+
    2022-11-11
  • Golang接口的定义与空接口及断言的使用示例
    目录1. Golang中的接口2. 为什么要使用接口3. 定义一个Usber接口(从下往上转换)4. 空接口1. 空接口说明2. 空接口作为函数的参数3. 切片实现空接口4. map...
    99+
    2023-05-15
    Go接口的定义 Go空接口 Go断言
  • java 定义长度为0的数组/空数组案例
    如下: int[] array = new int[0]; // 定义一个长度为 0 的数组 / 空数组 Sring[] arr = new String[0]; // 定义...
    99+
    2022-11-11
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作