gpt4 book ai didi

go - 如何确保 slice 使用的是另一个 slice 的副本而不是对它的引用?

转载 作者:IT王子 更新时间:2023-10-29 02:23:44 26 4
gpt4 key购买 nike

我正在学习 GO,但我有一个理论问题。

如何使用 slice 的副本而不是对它的引用?

package main

import "fmt"

func main() {
// slice containing 3 items
slice1 := []int{1, 2, 3}
// make an empty slice
slice2 := make([]int, 2, 5)
// create slice3 by appending int 4 to slice2
slice3 := append(slice2, 4)
// print [0 0 4]
fmt.Println(slice3)
// copy elements of slice1 onto slice2
copy(slice2, slice1)
// print [1 2 3] [1 2] [1 2 4]; how to make sure slice3 is using a copy [0 0 4]?
fmt.Println(slice1, slice2, slice3)
}

problem playground link

我想出了一个潜在的解决方案,但它毫无意义,因为它依赖于将 slice3 创建为空并通过 copy() 将 slice2 复制到 slice3。有没有捷径?

package main

import "fmt"

func main() {
// slice containing 3 items
slice1 := []int{1, 2, 3}
// make an empty slice
slice2 := make([]int, 2, 5)
// create slice3, copy slice2 and append int 4 to slice3
slice3 := make([]int, 2)
copy(slice3, slice2)
slice3 = append(slice3, 4)
// print [0 0 4]
fmt.Println(slice3)
// copy elements of slice1 onto slice2
copy(slice2, slice1)
// print [1 2 3] [1 2] [0 0 4];
fmt.Println(slice1, slice2, slice3)
}

solution playground link

编辑:

我已经 read在这个天真的例子中有一种特殊的行为可以作为解决方案(见下文)。但是,在任何其他情况下它都行不通。基本上,如果在没有指定底层数组大小的情况下创建空 slice ,GO 的 append 函数会提供该数组的副本,否则,如果有增长空间,append 将返回引用原始数组的 slice 。

注意:唯一的变化是 slice2 := make([]int, 2, 5) 变成 slice2 := make([]int, 2)

package main

import "fmt"

func main() {
// slice containing 3 items
slice1 := []int{1, 2, 3}
// make an empty slice
slice2 := make([]int, 2)
// create slice3 by appending int 4 to slice2
slice3 := append(slice2, 4)
// print [0 0 4]
fmt.Println(slice3)
// copy elements of slice1 onto slice2
copy(slice2, slice1)
// print [1 2 3] [1 2] [1 2 4]; how to make sure slice3 is using a copy [0 0 4]?
fmt.Println(slice1, slice2, slice3)
}

playground with a wanted behaviour

所以问题变成了:当我们附加到的 slice 指向具有指定大小和增长空间的数组时,是否可以复制上述行为?

编辑 2:我认为我想要实现的目标有些困惑。如何在以第一次调用中使用的格式传递 slice 时获取第二次调用的结果?

package main

import "fmt"

func main() {
fmt.Println("s3 references an array of s1")
worker(make([]int, 2, 5))
fmt.Println("\ns3 copies an array of s1")
worker(make([]int, 2))
}

func worker(s1 []int) {
s2 := []int{1, 2, 3}
fmt.Println(s1)
s3 := append(s1, 4)
fmt.Println(s3)
copy(s1, s2)
fmt.Println(s3)
}

playground

最佳答案

昨晚有几个人评论我说的不够清楚。所以我想澄清并提供我在@CoreyOgburn 和@JimB 的帮助下得出的答案

我在学习 GO 中的 slice 时发现了一个不一致的地方,这让我相信我做错了什么。虽然这不是现实生活中的例子,但我发现以下是复制和附加功能的一个很好的例子。

package main

import "fmt"

func main() {
fmt.Println("s3 references an array of s1")
// we pass a slice of length 2 and capacity 5
worker(make([]int, 2, 5))
fmt.Println("\ns3 copies an array of s1")
// we pass a slice of lenght 2 and capacity 2
worker(make([]int, 2))
}

func worker(s1 []int) {
// create new slice for future use
s2 := []int{1, 2, 3}
fmt.Println(s1)
// create a new slice by appending a value to a slice passed into this function
s3 := append(s1, 4)
// s3 holds whatever was passed into this function + int 4, that we just appended
fmt.Println(s3)
// copy contents of s2 onto s1
copy(s1, s2)
// if s1 had spare capacity when it was passed i.e. make([]int, 2, 5) s3 will be referencing the same array as s1, hence s3 will now hold the same values as s1
// if s1 capacity was the same as its length i.e. make([]int, 2) s3 will be referencing a new array after append(), hence copy has no effect on the values of s3
fmt.Println(s3)
}

@JimB 发布了一条评论,其中包含指向 blog post explaining how slices work 的链接,如果您正在学习这门语言,这是一本很棒的读物。A possible "gotcha" 部分中最重要的是对现实生活场景的“修复”的解释,可以推断为修复我的示例中的不一致。 (创建传递的 slice 的副本并改用它)
Playground

关于go - 如何确保 slice 使用的是另一个 slice 的副本而不是对它的引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32960461/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com