大橙子网站建设,新征程启航
为企业提供网站建设、域名注册、服务器等服务
再来分析一下golang中的切片slice底层的实现细节。
成都创新互联专注于企业成都营销网站建设、网站重做改版、万柏林网站定制设计、自适应品牌网站建设、H5技术、商城系统网站开发、集团公司官网建设、成都外贸网站建设、高端网站制作、响应式网页设计等建站业务,价格优惠性价比高,为万柏林等各大城市提供网站开发制作服务。
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]
```
背景: 切片当参数传递时,无法append
原因: go语言中切片是地址传递,test函数添加的1,2,3后被分配了新的地址,s切片还是指向原来的地址,a和s内存地址不一样
解决方法:推荐方法2
1.在test函数返回新的切片,main函数接受返回结果
注:本文是对 golang-101-hacks 中文翻译。
在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:
运行结果如下