在这篇文章中,您会看到以下在 go 中连接切片的方法
一般练习两片串联
连接两个以上切片的简单解决方案
连接两个以上切片的有效解决方案
一般练习两片串联package main
import "fmt"
func main() {
slice1 := []string{"apple", "banana", "peach" }
slice2 := []string{"avacado", "kiwi", "pineapple"}
slice3 := append(slice1, slice2...)
fmt.Println(slice3)
}
Go 中的切片串联可以使用标准库中内置的append()函数来完成。
在上面的示例中,切片 (slice1) 作为其第一个参数,第二个切片 (slice2) 中的所有元素作为其第二个参数。 当我们将这些切片作为参数传递时,使用append()函数,它会返回一个包含所有元素的更新切片。
append() 中第二个参数后面的三点运算符 (...) 是因为它是一个可变参数函数并且接受无限数量的参数。
连接两个以上切片的简单解决方案您可以传递给追加函数的切片数量 (2) 是有限制的,假设您已经看到需要追加两个以上的切片,下面是合并方法的一种版本。
package main
import "fmt"
func main() {
slices := [][]string{{"apple", "banana", "peach"},
{"orange", "grape", "mango"},
{"strawberry", "blueberry", "raspberry"}}
fmt.Println(concatAppend(slices))
}
func concatAppend(slices [][]string) []string {
var tmp []string
for _, s := range slices {
tmp = append(tmp, s...)
}
return tmp
}
我们在这里所做的本质上是循环遍历切片并对 tmp 数组执行重复追加以保留每次迭代。
连接两个以上切片的有效解决方案(快 2 倍)有些人发现这种创建空切片然后追加的方法会导致许多不必要的分配,可以通过以下方法避免这些分配并将代码性能提高两倍
package main
import "fmt"
func main() {
slices := [][]string{{"apple", "banana", "peach"},
{"orange", "grape", "mango"},
{"strawberry", "blueberry", "raspberry"}}
fmt.Println(concatcopyPreAllocate(slices))
}
func concatCopyPreAllocate(slices [][]string) []string {
var totalLen int
for _, s := range slices {
totalLen = len(s)
}
tmp := make([]string, totalLen)
var i int
for _, s := range slices {
i = copy(tmp[i:], s)
}
return tmp
}
以下是 Cameron Sparr 在 StackOverflow 上的回答以及基准测试示例的链接。
使用append() 进行切片连接的副作用append() 函数并不总是为返回的切片创建新的底层数组。 如果切片 1 的容量足以容纳切片 2 中的元素,则生成的切片将与切片 1 共享相同的底层数组,这可能会产生意想不到的副作用。
例子:
package main
import "fmt"
func main() {
slice1 := make([]int, 3, 6) // s1 has capacity of 5
slice1[0], slice1[1], slice1[2] = 1, 2, 3 // s1 has length of 3
slice2 := []int{4, 5, 6}
slice3 := append(slice1, slice2...)
fmt.Println("Before adding element to slice 3")
fmt.Println("slice1:", slice1)
fmt.Println("slice2:", slice2)
fmt.Println("slice3:", slice3)
//fmt.Println(slice1, slice3)
slice3[0] = 7
fmt.Println("After adding element to slice 3")
fmt.Println("slice1:", slice1)
fmt.Println("slice2:", slice2)
fmt.Println("slice3:", slice3)
}
//output
Before adding element to slice 3
slice1: [1 2 3]
slice2: [4 5 6]
slice3: [1 2 3 4 5 6]
After adding element to slice 3
slice1: [7 2 3]
slice2: [4 5 6]
slice3: [7 2 3 4 5 6]
更改切片 3 中的元素值也会导致切片 1 发生更改。 发生这种情况是因为它们共享相同的底层数组,这可能会导致错误。 可以通过确保append()返回的切片由新的底层数组支持来防止此问题,而不管切片1的容量如何。
就是这样:
package main
import "fmt"
func main() {
slice1 := make([]int, 3, 6) // s1 has capacity of 5
slice1[0], slice1[1], slice1[2] = 1, 2, 3 // s1 has length of 3
slice2 := []int{4, 5, 6}
slice3 := append(slice1[:len(slice1):len(slice1)], slice2...)
fmt.Println("Before adding element to slice 3")
fmt.Println("slice1:", slice1)
fmt.Println("slice2:", slice2)
fmt.Println("slice3:", slice3)
//fmt.Println(slice1, slice3)
slice3[0] = 7
fmt.Println("After adding element to slice 3")
fmt.Println("slice1:", slice1)
fmt.Println("slice2:", slice2)
fmt.Println("slice3:", slice3)
}
//output
Before adding element to slice 3
slice1: [1 2 3]
slice2: [4 5 6]
slice3: [1 2 3 4 5 6]
After adding element to slice 3
slice1: [1 2 3]
slice2: [4 5 6]
slice3: [7 2 3 4 5 6]
将附加功能调整为
append(slice1[:len(slice1):len(slice1)], slice2...)
//output
Before adding element to slice 3
slice1: [1 2 3]
slice2: [4 5 6]
slice3: [1 2 3 4 5 6]
After adding element to slice 3
slice1: [1 2 3]
slice2: [4 5 6]
slice3: [7 2 3 4 5 6]
结论
我们看到了在 Go 中连接两个或多个切片的两种方法,以及如何避免使用 append() 函数的副作用。如果您对 Go 中的切片连接有任何进一步的见解,请随时发表评论。
快乐编码!
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved