MST

星途 面试题库

面试题:Go语言切片截取操作与底层数组共享风险 - 复杂场景

假设有一个切片s1,通过截取得到s2和s3。在后续对s2进行操作时,s3也发生了意外的变化。请分析可能的原因,并给出代码示例以及避免这种情况的方法。
44.5万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

可能原因

在Go语言中,切片(slice)是基于数组的动态数据结构,切片截取操作(例如 s1[a:b])返回的新切片与原切片共享底层数组。所以当对 s2 操作时,如果修改了共享底层数组的元素,s3 也会因为共享底层数组而受到影响。

代码示例

package main

import (
    "fmt"
)

func main() {
    s1 := []int{1, 2, 3, 4, 5}
    s2 := s1[1:3]
    s3 := s1[3:5]

    fmt.Println("初始s2:", s2)
    fmt.Println("初始s3:", s3)

    s2[1] = 100

    fmt.Println("修改s2后s2:", s2)
    fmt.Println("修改s2后s3:", s3)
}

在上述代码中,s2s3 都基于 s1 截取得到,共享底层数组。当修改 s2 中的元素时,s3 中对应的共享底层数组元素也会改变。

避免方法

为了避免这种情况,可以使用 append 函数创建一个新的独立切片,这样新切片就有自己独立的底层数组。

package main

import (
    "fmt"
)

func main() {
    s1 := []int{1, 2, 3, 4, 5}
    s2 := make([]int, len(s1[1:3]))
    copy(s2, s1[1:3])
    s3 := make([]int, len(s1[3:5]))
    copy(s3, s1[3:5])

    fmt.Println("初始s2:", s2)
    fmt.Println("初始s3:", s3)

    s2[1] = 100

    fmt.Println("修改s2后s2:", s2)
    fmt.Println("修改s2后s3:", s3)
}

上述代码通过 make 函数创建新的切片,并使用 copy 函数将原切片的数据复制过去,使得 s2s3 拥有独立的底层数组,对 s2 的修改不会影响 s3