go语言中切片如何作参数 go语言的切片

golang-101-hacks(12)——切片作为函数参数传递

注:本文是对 golang-101-hacks 中文翻译。

创新互联建站是一家专注网站建设、网络营销策划、小程序设计、电子商务建设、网络推广、移动互联开发、研究、服务为一体的技术型公司。公司成立十年以来,已经为上1000+成都iso认证各业的企业公司提供互联网服务。现在,服务的上1000+客户与我们一路同行,见证我们的成长;未来,我们一起分享成功的喜悦。

在Go语言中,函数参数是值传递。使用slice作为函数参数时,函数获取到的是slice的副本:一个指针,指向底层数组的起始地址,同时带有slice的长度和容量。既然各位熟知数据存储的内存的地址,现在可以对切片数据进行修改。让我们看看下面的例子:

In Go, the function parameters are passed by value. With respect to use slice as a function argument, that means the function will get the copies of the slice: a pointer which points to the starting address of the underlying array, accompanied by the length and capacity of the slice. Oh boy! Since you know the address of the memory which is used to store the data, you can tweak the slice now. Let's see the following example:

运行结果如下

由此可见,执行modifyValue函数,切片s的元素发生了变化。尽管modifyValue函数只是操作slice的副本,但是任然改变了切片的数据元素,看另一个例子:

You can see, after running modifyValue function, the content of slice s is changed. Although the modifyValue function just gets a copy of the memory address of slice's underlying array, it is enough!

See another example:

The result is like this:

而这一次,addValue函数并没有修改main函数中的切片s的元素。这是因为它只是操作切片s的副本,而不是切片s本身。所以如果真的想让函数改变切片的内容,可以传递切片的地址:

This time, the addValue function doesn't take effect on the s slice in main function. That's because it just manipulate the copy of the s, not the "real" s.

So if you really want the function to change the content of a slice, you can pass the address of the slice:

运行结果如下

go语言中实现切片(slice)的三种方式

定义一个切片,然后让切片去引用一个已经创建好的数组。基本语法如下:

索引1:切片引用的起始元素位

索引2:切片只引用该元素位之前的元素

例程如下:

在该方法中,我们未指定容量cap,这里的值为5是系统定义的。

在方法一中,可以用arr数组名来操控数组中的元素,也可以通过slice切片来操控数组中的元素。切片是直接引用数组,数组是事先存在的,程序员是可见的。

通过 make 来创建切片,基本语法如下:

make函数第三个参数cap即容量是可选的,如果一定要自己注明的话,要注意保证cap≥len。

用该方法可以 指定切片的大小(len)和容量(cap)

例程如下:

由于未赋值系统默认将元素值置为0,即:

数值类型数组:    默认值为 0

字符串数组:       默认值为 ""

bool数组:           默认值为 false

在方法二中,通过make方式创建的切片对应的数组是由make底层维护,对外不可见,即只能通过slice去访问各个元素。

定义一个切片,直接就指定具体数组,使用原理类似于make的方式。

例程如下:

slice切片做函数参数

  再来分析一下golang中的切片slice底层的实现细节。

slice通过数组实现,类似一个结构体,其中一个字段保存的是底层数组的地址,还有长度(len) 和 容量(cap)两个字段。

    我们都知道,结构体作为函数参数时是值拷贝,同理,实际上slice作为函数参数时也是值拷贝,在函数中对slice的修改是通过slice中保存的地址对底层数组进行修改,所以函数外的silce看起来被改变了。

    当需要对slice做插入和删除时(如:append操作),由于需要更改slice结构体中的长度字段,值拷贝就行不通了,需要传slice本身在内存中的地址。

看一个值传递的例子:

```

package main

import "fmt"

func processSlice(x []int) {

x = append(x, 6)

}

func main() {

var numbers = []int{1, 2, 3, 4, 5}

processSlice(numbers)

for _, v := range(numbers) {

fmt.Println(v)

}

}

```

1 2 3 4 5

再看一个指针传递的例子:

```

package main

import "fmt"

func processSlice(x *[]int) {

*x = append(*x, 6)

}

func main() {

var numbers = []int{1, 2, 3, 4, 5}

processSlice(numbers)

for _, v := range(numbers) {

fmt.Println(v)

}

}

```

1 2 3 4 5 6

slice for 循环中删除元素

方法1:

```

chars:=[]string{"a","a","b"}

fori:=0;ilen(chars);i++{

if chars[i]=="a" {

chars=append(chars[:i],chars[i+1:]...)

i--// form the remove item index to start iterate next item

}

}

fmt.Printf("%+v",chars)

```

方式2:

```

p := []int{1, -13, 9, 6, -21, 125}

j := 0

for _, n := range p {

if n 0 {

    p[j] = n   //删除小于零的元素

    j++

}

}

```

不改原slice

```

p := []int{1, -13, 9, 6, -21, 125}

j := 0

q := make([]int, len(p))

for _, n := range p {

if n 0 {

q[j] = n   //删除小于零的元素

j++

}

}

q = q[:j]

```


当前文章:go语言中切片如何作参数 go语言的切片
网站地址:http://pwwzsj.com/article/ddipchi.html