天天看点

go slice小释

golang中常用的slice,在使用的过程中很容易用错,总结下来根本原因是没有了解其底层数据结构。

1. 数据结构样式

// 这里只是举例
type slice struct {
    pointer    *interface{} // 指向值数组的指针
    length     int64        // 当前有效值长度
    capacity   int64        // 当前数组总长度
}

// PS: 
1. capacity >= length
2. 扩容规则 capacity *= 2
3. append操作时,如slice = append(slice, 1)
    if length <= append {
        // slice的地址没有改变,只是在底层的数据有效值位置后插入对应的值,并更改结构体中length的值
        length++
        pointer[length] = 1
    }
    else {
        capacity *= 2
        tempPoint = malloc(capacity * sizeof(值类型)) // 扩容
        copy(temPoint, pointer)
        pointer = temPoint
        pointer = append(temPoint, 1)
    }
           

2. 案例

func sliceTest1(value []int) {
	value[0] = 100
}

func sliceTest2(value []int) []int {
	value = append(value, 1)
	return value
}

func main() {
	sliceValue := make([]int, 1)
	fmt.Println(sliceValue) // 1
	sliceTest1(sliceValue)
	fmt.Println(sliceValue) // 100
	sliceValue2 := sliceTest2(sliceValue)
	fmt.Println(sliceValue) // 100
	fmt.Println(sliceValue2) // 100 1
}
           

3. 案例分析

  1. slice在函数传参时是值传递
  2. 因为结构中的指针地址的值也相同,所以在更改原有的值时,也会起到作用,如sliceTest1方法
  3. 但当长度(slice中的length和capacity)发生变化时,并不会影响到原始的slice,所以在调用sliceTest2方法后,sliceValue的值仍没有变化

4. 小结

1. slice在函数参数传递时时值传递,在没有length变化的情况下,会启动引用传递的效果,否则就不会影响到原有变量的值。

2. 想要放心大胆的使用slice,建议在函数传参时,传入*slice,使用是如(*sliceValue)即可,这样就可以真正的引用传递。

PS:

如有错漏,还望指出,教学相长,共同进步。