我的编程空间,编程开发者的网络收藏夹
学习永远不晚

深入了解Golang中Slice切片的使用

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

深入了解Golang中Slice切片的使用

写在前面

周日下午在家学习,看到一个关于切片的问题,在网上找了一些资料,做个总结。

上代码

func main() {
	sl := make([]int, 0, 10)
	var appenFunc = func(s []int) {
		s = append(s, 10, 20, 30)
		fmt.Println(s, len(sl), cap(sl))
	}
	fmt.Println(sl, len(sl), cap(sl))
	appenFunc(sl)
	fmt.Println(sl, len(sl), cap(sl))
	fmt.Println(sl[:10], len(sl), cap(sl))

	fmt.Println(sl[:], len(sl), cap(sl))
}

你觉得会输出什么?思考一下再往下看。

有的人觉得可能是

[] 0 10
[10 20 30] 3 10  
[] 0 10
[] 0 10
[] 0 10

实际结果是

[] 0 10
[10 20 30] 0 10
[] 0 10
[10 20 30 0 0 0 0 0 0 0] 0 10
[] 0 10

是不是差别很大?这里的差别主要是第四行、第五行的结果。

第一行:比较好理解,切片没有做任何修改,值应该是:[] 0 10

第二行:也很好理解,在appendFunc函数中打印sl,结果是:[10 20 30] 3 10 第三行:由于go都是值传递,所以传到appendFunc函数中的sl其实是切片复制了一份,对原sl没有影响,所以输出结果是:[] 0 10

第四行:sl[:10]这个应该会报数组越界错误才对?怎么没有报错,而且还输出了10 20 30,但是len(sl)等于0,很奇怪

第五行:如果第四行能输出整个数组的内容,这里的sl[:]应该也能输出内容,但是为什么是空的?

分析原因

这里有2个问题:

  • 为什么sl[0:10]能输出10个元素,并且打印出了函数中添加的元素?但是len(sl)等于0
  • 为什么sl[:]输出空数组?

大家都知道,slice(切片)的底层实现,slice 底层存储的数据结构指向了一个 array(数组),如下图:

slice结构体定义如下

type SliceHeader struct {  
    Data uintptr  
    Len  int  
    Cap  int  
}
  • Data:指向具体的底层数组。
  • Len:代表切片的长度。
  • Cap:代表切片的容量。

核心要记住的是:slice 真正存储数据的地方,是一个数组。slice 的结构中存储的是指向所引用的数组指针地址

看到这里你应该明白了,传入到appendFunc函数的sl虽然是外层定义的sl的一个值拷贝,它的修改不会影响原sl的内容,但是由于Data是个指针,appendFunc函数对Data的修改自然就影响了原sl的Data,这个很好理解。

要记住一个关键点:如果传过去的值是指向内存空间的地址,是可以对这块内存空间做修改的

对于第一个问题:为什么sl[0:10]能输出10个元素?

这里跟切片访问的一个优化有关,当用s[low : high]访问切片的时候,表达式 s[low : high] 中的 high,最大的取值范围对应着切片的容量(cap),不是单纯的长度(len) 。因此调用 fmt.Println(sl[:10]) 时可以输出容量范围内的值,不会出现越界。

相对的 fmt.Println(sl), fmt.Println(sl[:]) 因为该切片 len 值为 0,没有指定最大索引值,high 则取 len 值,导致输出结果为空。

总结

本文主要涉及到切片在函数中的值传递和修改对原切片的影响,但是并没有考虑切片扩展的问题。这里有一篇文章专门介绍了一下扩容的情况下对原数组的影响,可以看看Go Slice底层实现

到此这篇关于深入了解Golang中Slice切片的使用的文章就介绍到这了,更多相关Golang Slice切片内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

深入了解Golang中Slice切片的使用

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

下载Word文档

猜你喜欢

深入了解Golang中Slice切片的使用

本文主要为大家详细介绍了Golang中Slice切片的使用,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
2023-02-27

Golang中Slice切片如何使用

今天小编给大家分享一下Golang中Slice切片如何使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。上代码func ma
2023-07-05

深入了解Rust的切片使用

除了引用,Rust 还有另外一种不持有所有权的数据类型:切片(slice),切片允许我们引用集合中某一段连续的元素序列,而不是整个集合。本文让我们来深入了解Rust的切片
2022-11-13

深入了解Golang中的Slice底层实现

本文主要为大家详细介绍了Golang中slice的底层实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
2023-02-26

你真的了解Golang中的切片吗?深入剖析

Golang是一门功能强大且高效的编程语言,其内置的切片(slice)类型是非常常用的数据结构之一。切片在Golang中扮演着重要的角色,可以方便地处理不定长度的数据集合。然而,对于很多开发者来说,对切片的理解可能还不够深入。本文将从基本概
你真的了解Golang中的切片吗?深入剖析
2024-03-02

深入了解Golang切片:探秘切片与数组的差异与应用场景

Golang切片原理揭秘:切片与数组的异同及使用场景在Golang编程语言中,数组和切片都是常见的数据结构。它们在很多情况下被用于存储和操作数据。然而,切片和数组之间存在一些重要的区别。本文将深入探讨Golang切片的原理,以及切片与数组
深入了解Golang切片:探秘切片与数组的差异与应用场景
2024-01-24

深入了解Golang中占位符的使用

在写 golang 的时候,也是有对应的格式控制符,也叫做占位符,写这个占位符,需要有对应的数据与之对应,不能瞎搞。本文就来和大家聊聊Golang中占位符的使用,希望对大家有所帮助
2023-03-11

深入了解Golang中reflect反射的使用

这篇文章主要介绍了深入了解Golang中reflect反射的使用,Go语言中的反射是一种机制,可以在运行时动态地获取类型信息和操作对象,以及调用对象的方法和属性等,需要详细了解可以参考下文
2023-05-20

使用工具深入了解 golang 函数

通过 go tool objdump 命令可深入了解 go 函数的汇编代码,从而洞察其内部工作原理。例如,查看 strconv.parseint 源代码,了解其如何将字符串转换为 int64,包含以下步骤:1. 查找非空格字符起始位置。2.
使用工具深入了解 golang 函数
2024-05-06

Golang中的切片怎么定义使用

这篇文章主要介绍了Golang中的切片怎么定义使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Golang中的切片怎么定义使用文章都会有所收获,下面我们一起来看看吧。1.切片的定义从上一节我们知道,因为数组的
2023-07-04

你真的理解 Golang 切片吗?全切片表达式及切片使用技巧

Golang 的切片不仅仅是带长度的指针,它们还有一个 \"容量 \"字段,因为增加动态分配的数组是一个很常见的任务。分片的容量也作为分片表达式 a[low:high] 的边界检查器——切片的末端不能超过其容量。

切片是Golang中的利器还是绊脚石?深入探讨

切片是Golang中的利器还是绊脚石?这个问题一直困扰着很多Golang开发者。切片(Slice)作为Golang语言中非常重要的数据类型之一,具有灵活性和便利性,但同时也存在一些容易被忽视的细节,甚至可能导致一些难以排查的bug。本文将深
切片是Golang中的利器还是绊脚石?深入探讨
2024-03-02

深入了解Golang中的同名方法

标题:Golang中的同名方法详解在Golang中,同名方法是指在同一个类型中定义了多个方法,方法名相同但是参数列表不同的情况。这种特性可以让我们更灵活地根据不同参数类型来实现不同的逻辑。本文将详细解释Golang中同名方法的使用方法,并
深入了解Golang中的同名方法
2024-02-26

深入了解Golang中的数据类型

在计算机编程中,数据类型是非常重要的一个概念。这篇文章将详细介绍Golang中的数据类型,包括基本类型、复合类型、引用类型以及自定义类型,希望对大家有所帮助
2023-05-18

Golang中Slice的分析与使用源码解析

这篇文章主要介绍了Golang中Slice的分析与使用(含源码),本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
2023-03-09

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录