arr5 := [5]int{1,2,3,4,5}
arr6 := baseStruct.Modify1(arr5)
fmt.Println(arr5)//打印结果:[1 2 3 4 5]
fmt.Println(arr6)//打印结果:[300 2 3 4 5]
/*
所用函数
func Modify1(array [5]int) [5]int{
array[0] = 300
return array
}
*/
arr7 := []int{1,2,3,4,5}
arr8 := baseStruct.Modify2(arr7)
fmt.Println(arr7)//打印结果:[300 2 3 4 5]
fmt.Println(arr8)//打印结果:[300 2 3 4 5]
/*
所用函数
func Modify2(array []int) []int {
array[0] = 300
return array
}
*/
根据楼上3楼的说法,我写了个例子进行测试
```golang
package main
import (
"fmt"
)
// 先改变slice元素,再增加长度 ---- 原slice元素改变,新slice改变
func Modify3(array []int) []int {
array[0] = 300
t1 := append(array, 6)
return t1
}
// 先改变slice元素,再缩小长度 ---- 原slice元素改变,新slice改变
func Modify4(array []int) []int {
array[0] = 300
t1 := array[0:3]
return t1
}
// 先增加长度,再改变新slice元素值 ---- 原slice元素不改变,新slice改变
func Modify5(array []int) []int {
t1 := append(array, 6)
t1[0] = 300
return t1
}
// 先增加长度,再改变原slice元素值 ---- 原slice元素改变,新slice不改变
func Modify6(array []int) []int {
t1 := append(array, 6)
array[0] = 300
return t1
}
// 先缩小长度,再改变原slice元素值 ---- 原slice元素改变,新slice改变
func Modify7(array []int) []int {
t1 := array[0:3]
array[0] = 300
return t1
}
// 先缩小长度,再改变新slice元素值 ---- 原slice元素改变,新slice改变
func Modify8(array []int) []int {
t1 := array[0:3]
t1[0] = 300
return t1
}
func main() {
arr1 := []int{1, 2, 3, 4, 5}
arr2 := Modify3(arr1)
fmt.Println("arr1:", arr1) // 打印结果:[300 2 3 4 5]
fmt.Println("arr2:", arr2) // 打印结果:[300 2 3 4 5 6]
arr3 := []int{1, 2, 3, 4, 5}
arr4 := Modify4(arr3)
fmt.Println("arr3:", arr3) // 打印结果: [300 2 3 4 5]
fmt.Println("arr4:", arr4) // 打印结果: [300 2 3]
arr5 := []int{1, 2, 3, 4, 5}
arr6 := Modify5(arr5)
fmt.Println("arr5:", arr5) // 打印结果: [1 2 3 4 5]
fmt.Println("arr6:", arr6) // 打印结果: [300 2 3 4 5 6]
arr7 := []int{1, 2, 3, 4, 5}
arr8 := Modify6(arr7)
fmt.Println("arr7:", arr7) // 打印结果: [300 2 3 4 5]
fmt.Println("arr8:", arr8) // 打印结果: [1 2 3 4 5 6]
arr9 := []int{1, 2, 3, 4, 5}
arr10 := Modify7(arr9)
fmt.Println("arr9:", arr9) // 打印结果: [300 2 3 4 5]
fmt.Println("arr10:", arr10) // 打印结果: [300 2 3]
arr11 := []int{1, 2, 3, 4, 5}
arr12 := Modify8(arr11)
fmt.Println("arr11:", arr11) // 打印结果: [300 2 3 4 5]
fmt.Println("arr12:", arr12) // 打印结果: [300 2 3]
}
```
```golang
输出结果:
$ go run main.go
arr1: [300 2 3 4 5]
arr2: [300 2 3 4 5 6]
arr3: [300 2 3 4 5]
arr4: [300 2 3]
arr5: [1 2 3 4 5]
arr6: [300 2 3 4 5 6]
arr7: [300 2 3 4 5]
arr8: [1 2 3 4 5 6]
arr9: [300 2 3 4 5]
arr10: [300 2 3]
arr11: [300 2 3 4 5]
arr12: [300 2 3]
$ go version
go version go1.13 linux/amd64
```
#### 实验总结
```golang
|----------------------------------------------------------------------------|
| |
| Modify3 先改变slice元素,再增加长度 ---- 原slice元素改变,新slice改变 |
| Modify4 先改变slice元素,再缩小长度 ---- 原slice元素改变,新slice改变 |
| |
| Modify5 先增加长度,再改变新slice元素值 ---- 原slice元素不改变,新slice改变 |
| Modify6 先增加长度,再改变原slice元素值 ---- 原slice元素改变,新slice不改变 |
| |
| Modify7 先缩小长度,再改变原slice元素值 ---- 原slice元素改变,新slice改变 |
| Modify8 先缩小长度,再改变新slice元素值 ---- 原slice元素改变,新slice改变 |
| |
|---------------------------------------------------------------------------|
原slice append 扩容后,原始slice与新slice脱离关系
原slice 缩小后,原始slice与新slice保持关系
```
#### 实验结论
当函数内部发生slice扩容后,会导致底层数组改变,就不会影响外部作用域的底层数组,经以上代码证明是正确的
但是当函数内部发生slice发生减少的时候,则不会导致底层数组改变,会影响外部作用域的底层数组
感谢楼上指出我的错误
#### 剩余疑问
```golang
我全文搜索go源码文件,没有发现3楼的slice结构定义,发现没有找到
// 3楼的slice结构定义
type _slice struct {
elements unsafe.Pointer // 引用着底层存储在间接部分上的元素
len int // 长度
cap int // 容量
}
// 我的slice结构定义--位于源码位置/**/go/src/go/types/type.go
type Slice struct {
Elem *Type // element type
}
```
我不确定我是否找对地方,还是我们两者的go版本不一致
我的go版本为go version go1.13 linux/amd64
希望对楼主有点帮助
#4
更多评论
#### 这是一个关于array与slice的问题
这两个看起来长得差不多,刚开始的确挺容易弄混淆的
```golang
package main
import (
"fmt"
)
// 数组array-值传递
func Modify1(array [5]int) [5]int {
array[0] = 300
return array
}
// slice-地址传递
func Modify2(array []int) []int {
array[0] = 300
return array
}
func main() {
// 数组-需要明确指定大小
arr5 := [5]int{1, 2, 3, 4, 5}
arr6 := Modify1(arr5)
fmt.Println("arr5:", arr5) // 打印结果:[1 2 3 4 5]
fmt.Println("arr6:", arr6) // 打印结果:[300 2 3 4 5]
// slice-不需要明确指定大小
arr7 := []int{1, 2, 3, 4, 5}
arr8 := Modify2(arr7)
fmt.Println("arr7:", arr7) // 打印结果:[300 2 3 4 5]
fmt.Println("arr8:", arr8) // 打印结果:[300 2 3 4 5]
/*
// 数组-大小不可以变化
// 此处报错: ./main.go:32:16: first argument to append must be slice; have [5]int
arr9 := append(arr5, 6)
fmt.Println("arr9:", arr9) // 此处报错
*/
// slice-大小可以变化
arr10 := append(arr7, 6)
fmt.Println("arr10:", arr10) // 打印结果:[300 2 3 4 5 6]
}
```
<br/>
明确指定大小即固定长度的为**array** <br/>
动态改变大小即不固定长度的为**slice** <br/>
在函数传递中,array是**值传递**,slice是**地址传递** <br/>
<br/>
明确这个就应该很容易理解啦 <br/>
arr5 是 array --- 值传递 --- 不改变<br/>
arr7 是 slice --- 地址传递 --- 改变<br/>
<br/>
#### 传递一个小技巧
在写代码的三个点后面加上golang,代码可以变得高亮
#1
上面预览的格式有点错乱,重新发布一下总结
```
明确指定大小即固定长度的为array
动态改变大小即不固定长度的为slice
在函数传递中,array是值传递,slice是地址传递
明确这个就应该很容易理解啦
arr5 是 array --- 值传递 --- 不改变
arr7 是 slice --- 地址传递 --- 改变
```
#### 传递一个小技巧
在写代码的三个点后面加上golang,代码可以变得高亮
#2