我刚开始学习Go语言,我想构建一个从切片中选择随机子序列的函数。但是,我不知道这个切片可以存储什么类型的值,这些值可以是整数,字符串或某些结构的元素。例如,让我们假设我必须结构:
type person struct {
name string
age int
}
type animal struct {
name string
age int
breed string
}
现在,我想构建函数getRandomSequence,如下所示:作为参数给出切片S和长度l,该函数返回一个切片,其中包含来自切片S的l个随机选择的元素。我遇到的问题是 - 如何使这个函数适用于任何可能的切片。我试着做以下事情:
func GetRandomSequence(S interface{}, l int) []interface{} {
switch S.(type) {
case person:
// Do random selection of l elements from S and return them
case animal:
// Do random selection of l elements from S and return them
case int:
// Do random selection of l elements from S and return them
}
return " Not Recognised"
}
有人可以建议我怎么写这样的功能吗?如果S是任何类型的单个元素,那么我设法使类似(即一般)函数起作用(因此[]interface{}
只是interface{}
而不是UniversalAuthorizer
}但我无法找到如何解决这个问题
答案 0 :(得分:1)
只需使用interface{}
而不是[]interface{}
。空接口可以存储任何类型,包括切片。
您的代码看起来像这样(虽然我没有测试):
func GetRandomSequence(S interface{}, l int) interface{} {
returnSlice := []interface{}
switch v := s.(type) {
// inside the switch v has the value of S converted to the type
case []person:
// v is a slice of persons here
case []animal:
// v is a slice of animals here
case []int:
// v is a slice of ints here
case default:
// v is of type interface{} because i didn't match any type on the switch
// I recommend you return nil on error instead of a string
// or always return 2 things, the value and an error like
// the standard library
return "Not Recognized"
}
rerurn returnSlice
}
我建议您完成Tour of go,但对于这个问题,答案是here。
根据您想要做的事情,看起来您可能不需要不同类型的切片,只需要一片interface{}
。如果在你的函数中从切片中提取随机元素,你就不关心元素的类型了:
func GetRandomSequence(S []interface{}, l int) []interface{} {
returnSlice := make([]interface{}, 0, l)
for i:=0; i<l; i++ {
// S[i] here is always of type interface{}
returnSlice = append(returnSlice, S[getRnd()]) // you need to implement getRnd() or just "math/rand" or something.
}
return returnSlice
}
答案 1 :(得分:1)
编写一个与切片索引一起使用的示例函数。
// Sample k random elements from set of n elements.
// The function set sets an element in the output given
// an index in the output and the index in the input.
func sample(k int, n int, assign func(out int, in int)) {
for i := 0; i < k; i++ {
set(i, i)
}
for i := k; i < n; i++ {
j := rand.Intn(i + 1)
if j < k {
set(j, i)
}
}
}
像这样使用:
in := []person{ {"John", 10}, {"Sally", 11}, {"James", 9}, {"Eve", 8} }
out := make([]person, 2)
sample(len(out), len(in), func(i, j int) { out[i] = in[j] })
因为sample
仅适用于长度和索引值,所以它可以在任何类型的切片上使用。
此方法类似于标准库中的sort.Search。