数组切片slice这个东西看起来很美好,真正用起来会发现有诸多的不爽。

第一,数组、数组切片混淆不清,使用方式完全一样,有时候一些特性又完全不一样,搞不清原理很容易误使用。

第二,数组切片的append操作,每次对slice append操作,都返回一个新的slice的引用,对slice的引用没法保持,这样在函数传递slice的情况下append,在调用函数的上下文中看不到slice append的效果。如果想要这种方式凑效,不得不另辟蹊径。本文主要说一下如何解决这个窘境的方法。

函数传递slice存在什么问题?

func sliceModify(slice []int) {
// slice[0] = 88
slice = append(slice, 6)
}
func main() {
slice := []int{1, 2, 3, 4, 5}
sliceModify(slice)
fmt.Println(slice)
}

输出:

[1 2 3 4 5]

问题所在:

虽然说数组切片在函数传递时是按照引用的语义传递的,比如说在sliceModify函数里面slice[0] = 88,在方法调用的上下文中,调用函数对slice引用的改表是看得见的。

但是在对slice进行append操作的时候,我们惊奇的发现,这次又不管用了。原因就是append操作会返回这个扩展了的slice的引用,必须让原引用重新赋值为新slice的引用,说白了就是,传递过来的这个指针原来指了内存中的A区域,A区域是原数组的真正所在。经过一次 append之后,要把这个指针改为指向B,B对应append后新的slice的引用。但是方法调用的上下文里的slice指针还是指向了老的A内存区域。

这个逻辑实在有些奇葩,这里我不得不再次吐槽append的设计。有人说这个问题好解决啊,只需要在sliceModify函数的返回值中把append后新的slice引用返回就好了。这样做当然是可以滴,但是像递归调用的函数就不好解决了。

下面就说一下这个问题的解决办法,方法也很简单,就是传递指针的指针。虽然有些绕,但是总算把问题解决了。当然也有其他的办法,比如按照java等语言的方式,自己实现一个ArrayList,在对可变数组扩展的时候,千万表改变引用了。

func sliceModify(slice *[]int) {
*slice = append(*slice, 6)
}
func main() {
slice := []int{1, 2, 3, 4, 5}
sliceModify(&slice)
fmt.Println(slice)
}

这次就可以输出预期的结果了:

[1 2 3 4 5 6]

递归调用的例子:

func insertTo10(arr *[]int) {
length := len(*arr)
if length == 10 {
return
}
*arr = append(*arr, length)
insertTo10(arr)
}
func main() {
arr10 := []int{}
insertTo10(&arr10)
fmt.Println(arr10)
}

还可以访问我树莓派上搭的博客地址:

http://www.codeforfun.info/

go递归函数如何传递数组切片slice的更多相关文章

  1. go 数组(array)、切片(slice)、map、结构体(struct)

    一 数组(array) go语言中的数组是固定长度的.使用前必须指定数组长度. go语言中数组是值类型.如果将数组赋值给另一个数组或者方法中参数使用都是复制一份,方法中使用可以使用指针传递地址. 声明 ...

  2. go语言之---数组(array)和切片(slice)

    一.数组 1.什么是数组? 1.数组是一系列同一类型数据的集合 2.数组中包含的每个数据被称为数组元素 3.一个数组中包含的元素个数成为数组长度 4.数组的长度是固定的 5.一个数组可以由零个或者多个 ...

  3. Go 数组(array) & 切片(slice)

    数组 数组是一组固定长度的序列 数组类型 数组的类型不仅和储存元素的类型有关,还和数组长度有关,不同长度的数组是不同的类型 不同类型的数组不能共用一个函数 func main() { var a [1 ...

  4. Go语言学习之4 递归&闭包&数组切片&map&锁

    主要内容: 1. 内置函数.递归函数.闭包2. 数组与切片3. map数据结构4. package介绍 5. 排序相关 1. 内置函数.递归函数.闭包 1)内置函数 (1). close:主要用来关闭 ...

  5. go语言 类型:数组切片

    初看起来,数组切片就像一个指向数组的指针,实际上它拥有自己的数据结构,而不仅仅是个指针.数组切片的数据结构可以抽象为以下3个变量: 1.一个指向原生数组的指针: 2.数组切片中的元素个数: 3.数组切 ...

  6. go语言中的数组切片:特立独行的可变数组

    go语言中的数组切片:特立独行的可变数组 初看go语言中的slice,觉得是可变数组的一种很不错的实现,直接在语言语法的层面支持,操作方面比起java中的ArrayList方便了许多.但是在使用了一段 ...

  7. Go语言学习笔记(三)数组 & 切片 & map

    加 Golang学习 QQ群共同学习进步成家立业工作 ^-^ 群号:96933959 数组 Arrays 数组是同一种数据类型的固定长度的序列. 数组是值类型,因此改变副本的值,不会改变本身的值: 当 ...

  8. Golang 入门 : 切片(slice)

    切片(slice)是 Golang 中一种比较特殊的数据结构,这种数据结构更便于使用和管理数据集合.切片是围绕动态数组的概念构建的,可以按需自动增长和缩小.切片的动态增长是通过内置函数 append( ...

  9. Go 灵活多变的切片Slice

    我们知道数组定义好之后其长度就无法再修改,但是,在实际开发过程中,有时候我们并不知道需要多大的数组,我们期望数组的长度是可变的, 在 Go 中有一种数据结构切片(Slice) 解决了这个问题,它是可变 ...

随机推荐

  1. jmeter --上传文件

    jmeter-场景-上传文件-send-a-file 简要说就3点: POST请求 Request的参数都写在路径内,不写在表单里 上传的文件写在表单里 只要记住以上3点,也就避免了在设计脚本的时候走 ...

  2. python 如何将md5转为16字节

    python的hashlib库中提供的hexdigest返回长度32的字符串. md5sum是128bit,也就是16字节,如何将python生成字符串的转为16字节呢? 请看下面代码 import ...

  3. 【shell】正则表达式语法

    一个正则表达式就是由普通字符(例如字符 a 到 z)以及特殊字符(称为元字符)组成的文字模式.该模式描述在查找文字主体时待匹配的一个或多个字符串.正则表达式作为一个模板,将某个字符模式与所搜索的字符串 ...

  4. gdb 调试(查看运行时数据)(五)

    查看栈信息 当程序被停住了,首先要确认的就是程序是在哪儿被断住的.这个一般是通过查看调用栈信息来看的.在gdb中,查看调用栈的命令是backtrace,可以简写为bt. (gdb) bt    #0 ...

  5. Delphi调用网页美化SQL

    百度搜索在线美化SQL语句的网站,为了加快解析速度,这里已下载到本地. 然后delphi用webbrowse载入本地的网页,然后把sql传进去,美化后取出来. 效果如下图 点击下载源码

  6. springMVC学习(3)-springMVC和mybatis整合

    一.需求:使用springmvc和mybatis完成商品列表查询. 二.整合思路:springMVC+mybaits的系统架构: 1步):整合dao层 mybatis和spring整合,通过sprin ...

  7. ASP.NET Web Pages:全局页面

    ylbtech-.Net-ASP.NET Web Pages:全局页面 1.返回顶部 1. ASP.NET Web Pages - 全局页面 本章介绍全局页面 AppStart 和 PageStart ...

  8. zclip复制到剪切板插件有个bug

    今天发现zclip复制到剪切板插件有个bug,就是在遨游和360浏览器的兼容模式下,点击复制没响应,后来我看了页面代码,发现在这两个浏览器的兼容模式下,生成的是<object>,其他浏览器 ...

  9. 共享存储(ISCSI网络存储)

    server端:(192.168.100.11) 分区sdb 分别为10G和5G #fdisk /dev/dab …… 同步分区表 #partprobe /dev/sdb # yum install ...

  10. php 数组函数实例

    数组的概念 数组(array)是 PHP 中一个非常重要的概念,我们可以把数组看做一系列类似的数据的集合,实际上数组是一个有序图. PHP 还提供了超过 70 个内建函数来操作数组. 由于数组在php ...