我的要求是要有一个有效地返回数组的函数。
据我所知,数组是值类型,因此将数组传入/传出到函数时,它会执行copy
。因此,我正在考虑数组的返回指针。人们会建议使用slice,但是通过使用slice,我仍然需要copy
才能转移到数组。
the linked strtod
documentation是包含两个解决方案的游乐场,请提出返回数组指针的正确方法,谢谢。
package main
import (
"fmt"
)
type geo [2]float32
func genArray () geo {
ret := geo{1.2, 2.3}
return ret
}
func genPointerOfArray () *geo {
ret := geo{1.2, 2.3}
return &ret
}
func main() {
ret1 := genArray()
ret2 := *genPointerOfArray()
fmt.Println(ret1, ret2)
}
答案 0 :(得分:3)
大多数开始学习Go的人都了解切片的概念。它是围绕数组的轻量级包装,它可以但不一定代表该基础数组的子集(或切片)。尽管有这种理解,开发人员在将这些知识付诸实践时仍会继续感到困惑。为什么?
当您要将数组传递给函数时,就会出现问题。 Go的文档清楚地表明,数组是通过副本传递的。如果您希望数组不可变,则可能有用。但是,在大多数情况下,这只是效率低下。最初,您可能会想做类似的事情:
names := []string{"leto", "paul", "teg"}
process(&names)
func process(names *[]string) {
...
}
这可能会引起您的间谍感。因此,您转到golang-nuts用户组,阅读相关文章,或者问一个问题,您不可避免地会得到以下答案:不要传递数组,传递切片。
这有点符合您所知道的,因为切片是数组周围的薄包装。但是,这仍然感觉好一点:
names := []string{"leto", "paul", "teg"}
process(names[0:])
func process(names []string) {
...
}
您自己想,这些只处理数组片段的人是谁? 95%的时间,我需要数组中的所有数据,而不仅仅是其中的一部分!
在这里,我们了解了人们在考虑数组和切片时存在的两个基本误解。
首先,将代表部分底层数组的切片功能视为次要优势。首先,切片是对数组的引用。代表整个数组的切片非常普遍。第二点使这一点更加绝对。
第二,您几乎肯定已经在处理切片了。上面的名称已经是一个切片(涵盖了整个基础数组)。处理数组的唯一时间是创建具有以下大小的数组:
names := [3]string{"leto", "paul", "teg"}
//or
names := [3]string{}
其他所有东西都是切片:
names := []string{"leto", "paul", "teg"}
//or
names := make([]string, 3)
//or
var names []string
因此,上述代码的解决方案最终是最直观的:
names := []string{"leto", "paul", "teg"}
process(names)
func process(names []string) {
...
}
让我们更进一步,并使用此知识来阐明另一个常见问题。您是否应该创建一个指针数组。例如,哪个更好?
sayans := []*Sayan{
&Sayan{Name: "Goku", Power: 9001,}
}
//or
sayans := []Sayan{
Sayan{Name: "Goku", Power: 9001,}
}
在两种情况下,sayans都是片。因此,将其传递给函数(或返回它)时,它们是相同的。第一个示例提供的额外间接寻址是否有用取决于情况,但是如果您不确定,可能不是,并且应该使用第二个版本。
两个要点是:
切片是对数组的引用,这些数组恰好具有 代表一个子集,几乎所有内容都已经成为一个切片