脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Golang - Golang 字符串切片与 Python 列表的不同

Golang 字符串切片与 Python 列表的不同

2021-05-25 00:44未闻Codekingname Golang

最近在粉丝交流群里面看到不少学 Python 的同学都在学习 Golang,那么今天我们来看一个非常基础的数据结构:Python中的列表和 Golang 中的切片(Slice)。

最近在粉丝交流群里面看到不少学 Python 的同学都在学习 Golang,那么今天我们来看一个非常基础的数据结构:Python中的列表和 Golang 中的切片(Slice)。

这两个数据结构从形式上来说,非常相似。我们今天来对比一个只包含字符串的列表和一个字符串切片。

Golang 字符串切片与 Python 列表的不同

相同点

 

在 Python 里面,我们定义一个有初始值的字符串列表:

  1. a = ['kingname', 'pm', 'xxx'] 

在 Golang 里面,我们定义一个有初始值的字符串切片:

  1. := []string{"kingname", "pm", "xxx"} 

接下来,我们分别往字符串列表和字符串切片末尾增加几个元素:

  1. a.append("address") 
  2. a.append("shanghai") 

在 Golang 里面:

  1. a = append(a, "address") 
  2. a = append(a, "shanghai") 

我们也可以赋值给其他的变量,看看修改一个,另一个是否会发生修改:

  1. b = a 
  2. a[0] = 'superman' 
  3. print(b) 

运行效果如下图所示:

Golang 字符串切片与 Python 列表的不同

我们再来看看在 Golang 的效果:

  1. :a 
  2. a[0] = "superman" 
  3. fmt.Println(b) 

运行效果如下图所示:

Golang 字符串切片与 Python 列表的不同

那么,我们是不是可以说,Golang 的切片就相当于 Python 里面元素数据类型相同的列表?

不同点

 

现在,我们再往列表和字符串切片里面各加一个元素,来看看运行效果:

在 Python 里面,运行效果如下图所示:

Golang 字符串切片与 Python 列表的不同

进一步实验你会发现,a 和 b 两个列表是完全一样的,只要修改任何一个列表,另一个都会随之发生变化。

但是 Golang 里面并不是这样,如下图所示:

Golang 字符串切片与 Python 列表的不同

你修改任何一个切片,另一个切片都不会改变。

看到这里,你可能会觉得 Golang 里面,是不是append添加新的数据,每次都会生成新的切片,所以才导致添加数据以后两个切片就不一样了。

但实际上并不是这样,我们用另外一种初始化切片的方式来做一个测试:

Golang 字符串切片与 Python 列表的不同

在这个例子里面,我生成了一个长度为5,容量为20的字符串切片。根据第15-19行的运行结果可以看到,此时,无论是根据索引修改里面的元素,还是使用 append 添加新的元素,两个切片的变化都相同。如果我们把切片的容量调小,调整到6,再看看效果:

Golang 字符串切片与 Python 列表的不同

从这里可以看到,b 跟着 a 变了半截。a 新增的test字符串同时也能在 b 里面找到。但是 a里面新增的abcde却没有出现在 b 中。并且对a[0]的修改,也没有出现在 b 中。

原因

 

Golang 的切片之所以会出现这个现象,这需要从数组与切片的区别来说起。在 Golang 里面,字符串数组和字符串切片非常像,但他们有一个根本的区别,就是数组是需要一开始就声明长度的,并且不能扩容。而切片不需要声明长度,所以:

  1. [5]string{"xx", "yy"}  // 这是长度为5的字符串数组 
  2. []string{"xx", "yy"} // 字符串切片   

而切片底层依然是数组,切片有一个容量的概念,指的就是它底层的数组的长度。如果切片中的数据数量等于了切片的容量,那么下一次再添加一个新的数据的时候,切片底层就会创建一个原来长度2倍(数据量小于1024的时候是2倍,大于1024的时候是1.25倍)的数组,然后把已有数据按顺序拷贝进去,接着再插入新的数据。

所以,回到上面的代码。当我们使用a := make([]string, 5, 6)创建一个容量为6的字符串切片的时候,它底层会初始化一个长度为6的字符串数组。当代码执行到b := a[0: 6]的时候,虽然这里的 b 是另外一个切片,它跟 a 拥有不同的内存地址,但他们共用了同一个底层数组。只要数据小于6,那么对其中一个切片的数据进行修改,本质上就是对它底层数组的修改,而另一个切片也使用这个数组,所以也能看到这个修改。

但是当a数据容量超过6以后,a 切片底层会重新生成一个长度为12的数组,并把原有的老数据都拷贝到新的数组里面,接下来的所有修改都是对这个新的数组进行修改。而此时 b 切片底层还是老的长度为6的数组,所以此时对 a 切片的修改就不会反映到 b 上面了。

原文链接:https://mp.weixin.qq.com/s?__biz=MzI2MzEwNTY3OQ==&mid=2648980919&idx=1&sn=96e14dd9d9c19d5a4911344ed1965001&chksm=f2506057c527e941f8ccef89b3acbc2b465e8e4fc359293ac6d7b146b4f2cc84d8fc723d850c&mpshare=1&s

延伸 · 阅读

精彩推荐
  • Golanggo语言制作端口扫描器

    go语言制作端口扫描器

    本文给大家分享的是使用go语言编写的TCP端口扫描器,可以选择IP范围,扫描的端口,以及多线程,有需要的小伙伴可以参考下。 ...

    脚本之家3642020-04-25
  • Golanggolang如何使用struct的tag属性的详细介绍

    golang如何使用struct的tag属性的详细介绍

    这篇文章主要介绍了golang如何使用struct的tag属性的详细介绍,从例子说起,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看...

    Go语言中文网11352020-05-21
  • GolangGolang通脉之数据类型详情

    Golang通脉之数据类型详情

    这篇文章主要介绍了Golang通脉之数据类型,在编程语言中标识符就是定义的具有某种意义的词,比如变量名、常量名、函数名等等,Go语言中标识符允许由...

    4272021-11-24
  • Golanggo日志系统logrus显示文件和行号的操作

    go日志系统logrus显示文件和行号的操作

    这篇文章主要介绍了go日志系统logrus显示文件和行号的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    SmallQinYan12302021-02-02
  • Golanggolang json.Marshal 特殊html字符被转义的解决方法

    golang json.Marshal 特殊html字符被转义的解决方法

    今天小编就为大家分享一篇golang json.Marshal 特殊html字符被转义的解决方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧 ...

    李浩的life12792020-05-27
  • Golanggolang 通过ssh代理连接mysql的操作

    golang 通过ssh代理连接mysql的操作

    这篇文章主要介绍了golang 通过ssh代理连接mysql的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    a165861639710342021-03-08
  • Golanggolang的httpserver优雅重启方法详解

    golang的httpserver优雅重启方法详解

    这篇文章主要给大家介绍了关于golang的httpserver优雅重启的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,...

    helight2992020-05-14
  • GolangGolang中Bit数组的实现方式

    Golang中Bit数组的实现方式

    这篇文章主要介绍了Golang中Bit数组的实现方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    天易独尊11682021-06-09