Go递归用于结构字段 – 函数 vs. 指针方法

huangapple go评论105阅读模式
英文:

Go recursion for struct fields - function vs. pointer method

问题

给定一个示例代码:

  1. type container struct {
  2. arr []int
  3. }

我想要递归地操作它的arr数组字段值。

我有两个选项,从功能上来说:

  • container上使用(指针接收者) 方法,直接访问它的arr数组
  • 使用一个函数,接收arr切片作为参数

无论哪种情况,每个递归调用都必须传递交替的起始和结束索引作为参数。

问题:
使用其中一种实现方式是否会有已知的理论上的好处或不利影响,主要考虑性能和内存占用,假设arr将包含10^610^9个元素之间的数量?


注:通过运行(非专业的基准测试)的实现,性能似乎没有显著差异。

英文:

Given an exemplary

  1. type container struct {
  2. arr int[]
  3. }

I want to recursively manipulate its arr array field values.

I have two options, functionally:

  • a (pointer receiver) method on container, directly accessing its arr array
  • a function, receiving the arr slice as parameter

In any case, alternating start and end indices have to be passed as parameters to each recursive call.

Question:<br>
Are there any known, theoretically beneficial or detrimental impacts, mainly with regards to performance¹ and memory footprint, by using one implementation over the other and considering that arr will hold between 10^6 and 10^9 elements?


¹ running (unprofessionally bench-marked) test implementations, performance does not seem to be significantly different

答案1

得分: 2

我认为你可以使用两种选项,但我建议使用指向数组的指针,因为它可以防止意外追加切片,从而导致整个切片内存的复制。

另外请注意,你不能以这种方式使用数组:

  1. func foo(sl []int) {
  2. sl[1] = 15
  3. }
  4. func main() {
  5. arr := [5]int{1, 2, 3, 4, 5}
  6. foo(arr)
  7. }

输出:

  1. cannot use arr (variable of type [5]int) as []int value in argument to foo

但你可以将数组转换为切片而不进行复制:

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func foo(sl []int) {
  6. sl[1] = 55
  7. }
  8. func main() {
  9. arr := [5]int{1, 2, 3, 4, 5}
  10. sl := arr[:]
  11. fmt.Printf("arr=%v, sl=%v\n", arr, sl)
  12. arr[1] = 5
  13. fmt.Printf("arr=%v, sl=%v\n", arr, sl)
  14. sl[1] = 15
  15. fmt.Printf("arr=%v, sl=%v\n", arr, sl)
  16. foo(sl)
  17. fmt.Printf("arr=%v, sl=%v\n", arr, sl)
  18. }

输出:

  1. arr=[1 2 3 4 5], sl=[1 2 3 4 5]
  2. arr=[1 5 3 4 5], sl=[1 5 3 4 5]
  3. arr=[1 15 3 4 5], sl=[1 15 3 4 5]
  4. arr=[1 55 3 4 5], sl=[1 55 3 4 5]
英文:

I think that you can use both options, but I recommend to use pointer to array because it will protect you from accidental append to the slice which can lead to copying of the entire slice memory.

Also keep in mind that you cannot use array in such way:

  1. func foo(sl []int) {
  2. sl[1] = 15
  3. }
  4. func main() {
  5. arr := [5]int{1, 2, 3, 4, 5}
  6. foo(arr)
  7. }

Output:

  1. cannot use arr (variable of type [5]int) as []int value in argument to foo

But you can convert array into slice without copying it:

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. )
  5. func foo(sl []int) {
  6. sl[1] = 55
  7. }
  8. func main() {
  9. arr := [5]int{1, 2, 3, 4, 5}
  10. sl := arr[:]
  11. fmt.Printf(&quot;arr=%v, sl=%v\n&quot;, arr, sl)
  12. arr[1] = 5
  13. fmt.Printf(&quot;arr=%v, sl=%v\n&quot;, arr, sl)
  14. sl[1] = 15
  15. fmt.Printf(&quot;arr=%v, sl=%v\n&quot;, arr, sl)
  16. foo(sl)
  17. fmt.Printf(&quot;arr=%v, sl=%v\n&quot;, arr, sl)
  18. }

Output:

  1. arr=[1 2 3 4 5], sl=[1 2 3 4 5]
  2. arr=[1 5 3 4 5], sl=[1 5 3 4 5]
  3. arr=[1 15 3 4 5], sl=[1 15 3 4 5]
  4. arr=[1 55 3 4 5], sl=[1 55 3 4 5]

huangapple
  • 本文由 发表于 2023年5月4日 19:56:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/76172904.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定