文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Go如何安全地从数组中创建独立切片,也就是 "切片隔离"

2024-11-29 18:32

关注

这可能会导致一些不安全的场景,尤其当我们从数组中创建切片并修改切片的内容时,原数组也会受到影响。

如果需要确保切片是“独立的”,即切片的修改不会影响原数组或其他切片,应该采用某些方法来实现“切片隔离”。

问题背景

切片和数组共享内存,这是 Go 中常见的设计。以下代码说明了这一点:

package main

import "fmt"

func main() {
    arr := [5]int{1, 2, 3, 4, 5}
    slice := arr[1:4]  // 创建切片
    slice[0] = 100     // 修改切片的第一个元素
    fmt.Println("Array:", arr)  // 原数组也发生了变化
    fmt.Println("Slice:", slice)
}

输出:

Array: [1 100 3 4 5]
Slice: [100 3 4]

可以看到,修改切片后,原数组中的数据也被修改了。这是因为切片和数组共享底层存储。

如何安全地创建独立切片?

要安全地创建独立切片,使其修改不会影响原数组,我们可以采用以下几种方式:

1. 使用 copy 函数复制数据

copy 函数可以用于将一个数组或切片的数据复制到一个新的切片中,从而避免共享同一个底层数组。通过这种方式,两个切片不会共享内存,修改其中一个切片不会影响另一个切片。

示例代码:

package main

import "fmt"

func main() {
    arr := [5]int{1, 2, 3, 4, 5}
    slice := arr[1:4]       // 从数组创建切片
    
    // 使用 copy 函数创建新的切片并复制数据
    isolatedSlice := make([]int, len(slice))
    copy(isolatedSlice, slice)

    isolatedSlice[0] = 100  // 修改新的切片,不影响原数组

    fmt.Println("Array:", arr)               // 原数组未改变
    fmt.Println("Original Slice:", slice)    // 原切片未改变
    fmt.Println("Isolated Slice:", isolatedSlice) // 新切片已经改变
}

输出:

Array: [1 2 3 4 5]
Original Slice: [2 3 4]
Isolated Slice: [100 3 4]

通过 copy,我们创建了一个新的独立切片 isolatedSlice,修改该切片不会影响原数组或原切片。

解释:

2. 使用 append 函数扩展容量

在某些场景下,使用 append 创建新的切片时,由于超过了原始切片的容量,Go 语言会分配新的内存来存储扩展后的切片,这也可以用来实现切片隔离。

示例代码:

package main

import "fmt"

func main() {
    arr := [5]int{1, 2, 3, 4, 5}
    slice := arr[1:4]       // 从数组创建切片

    // 使用 append 扩展切片以创建新的内存分配
    isolatedSlice := append([]int(nil), slice...)

    isolatedSlice[0] = 100  // 修改新的切片,不影响原数组

    fmt.Println("Array:", arr)               // 原数组未改变
    fmt.Println("Original Slice:", slice)    // 原切片未改变
    fmt.Println("Isolated Slice:", isolatedSlice) // 新切片已经改变
}

输出:

Array: [1 2 3 4 5]
Original Slice: [2 3 4]
Isolated Slice: [100 3 4]

解释:

3. 手动复制数据

如果不想使用 copy 或 append,也可以手动创建一个新的切片,并逐个复制数据。

示例代码:

package main

import "fmt"

func main() {
    arr := [5]int{1, 2, 3, 4, 5}
    slice := arr[1:4]       // 从数组创建切片

    // 手动创建新切片并复制数据
    isolatedSlice := make([]int, len(slice))
    for i := range slice {
        isolatedSlice[i] = slice[i]
    }

    isolatedSlice[0] = 100  // 修改新的切片,不影响原数组

    fmt.Println("Array:", arr)               // 原数组未改变
    fmt.Println("Original Slice:", slice)    // 原切片未改变
    fmt.Println("Isolated Slice:", isolatedSlice) // 新切片已经改变
}

解释:

总结

切片隔离的方式:

  1. 使用 copy 函数:最常用的方式,将原切片的数据复制到一个新切片中。
  2. 使用 append 函数:通过 append 创建一个新的切片实例,可以实现内存隔离。
  3. 手动复制:手动将原切片的数据复制到新切片中。

何时需要切片隔离?

切片隔离主要用于以下场景:

通过上述方法,Go 程序员可以在需要的场景下创建独立的切片,避免切片和数组共享底层存储导致的潜在问题。

来源:Go语言圈内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯