如果我需要在参数中传递(小)切片,那么写入pure function的最佳方法是什么? 切片不像数组那样传递值。因此,不可能保证在执行函数期间不会修改它。 一旦解决方案是每次调用函数时复制切片。它会在实践中起作用,但我更倾向于使用更安全的解决方案,因为无法确保在函数调用之前创建副本。
答案 0 :(得分:2)
你是对的,因为切片是参考值,所以不可能使用切片参数的真正纯函数。
根据您的需要,您可以使用数组。数组具有固定数量的元素,声明如下:
var myArray [10]int
按值传递时会复制数组。
另一种可能性是将切片封装在只允许从切片读取的接口中,而不是写入切片。
package main
import "fmt"
// The interface
type ReadOnlyStringSlice interface {
Get(int) string
}
// An implementation of ReadOnlyStringSlice
type MyReadOnlySlice struct {
slice []string
}
func (m MyReadOnlySlice) Get(i int) string {
e := m.slice[i]
return e
}
// Your "pure" function
func MyPureFunction(r ReadOnlyStringSlice) {
fmt.Println(r.Get(0))
}
func main() {
m := MyReadOnlySlice{[]string{"foo", "bar"}}
MyPureFunction(m)
}
答案 1 :(得分:2)
不是一个真正的答案,但我想仍然值得讨论。
我认为整个想法是一厢情愿的想法:努力在一种语言中使用纯函数是没有意义的,这种语言不会以任何方式使用你的函数纯粹的事实。如果你可以将一个函数“标记”为纯函数,那么Go理论上可以以某种方式使用这个提示来获得它的优势(例如,在一系列调用中重新排序某些函数的执行)。由于没有明确的支持这种东西,功能的纯度只存在于你的脑海中。例如,假设您能够以某种方式强制函数不修改传递给它的切片;即使这样,也没有什么能阻止你在该函数中执行另一个副作用(比如,执行I / O或修改全局变量)。
如果你正在编写一个库并希望它的调用者提供一个回调,并且回调一定不能改变,只需在文档中清楚地说明这一事实。
答案 2 :(得分:0)
如果您正在编写程序包,则可以导出一个获取切片但复制的方法 它并将其传递给真正的函数:
func MyExportedFunc(someSlice []int) {
sliceCopy := make([]int, len(someSlice))
copy(sliceCopy, someSlice)
myUnexportedFunc(sliceCopy)
}
当然,这不是解决问题的方法,因为MyExportedFunc
不是
纯。最好的方法可能是封装切片,正如@Tom建议的那样。