General slice type in golang?
我在尝试将切片类型扩展为Go中的一般类型时遇到了一些困难。我创建了一个示例代码来解释我的问题。Play Ground版本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | package main import"fmt" type Sequencer interface { Mean() float64 } type Sequence []int func (s Sequence) Mean() float64 { sum := 0.0 for _, el := range s { sum += float64(el) } return sum / float64(len(s)) } func main() { a := []int{1, 2, 3, 4} b := Sequence(a) fmt.Println(b.Mean()) fmt.Println(b[:2].Mean()) c := Sequencer(b) fmt.Println(c.Mean()) fmt.Println(c[:2].Mean()) } |
main()函数的最后一行返回一个错误,说明不能切片Sequencer类型的变量:
cannot slice c (type Sequencer)
号
有没有一种方法可以定义一般类型的切片(int、float64、string等),而不隐藏切片的酷索引功能?
你有
1 2 3 4 5 | type Sequencer interface { Mean() float64 } c := Sequencer(b) |
因此,变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | package main import"fmt" type Sequencer interface { Mean() float64 } type Sequence []int func (s Sequence) Mean() float64 { sum := 0.0 for _, el := range s { sum += float64(el) } return sum / float64(len(s)) } type Map map[string]float64 func (m Map) Mean() float64 { sum := 0.0 for _, v := range m { sum += float64(v) } return sum / float64(len(m)) } func main() { a := []int{1, 2, 3, 4} b := Sequence(a) fmt.Println(b.Mean()) fmt.Println(b[:2].Mean()) c := Sequencer(b) fmt.Println(c.Mean()) fmt.Println(c.(Sequence)[:2].Mean()) m := Map{"one": 3.14159,"two": 2.718} fmt.Println(m.Mean()) } |
。
输出:
1 2 3 4 5 | 2.5 1.5 2.5 1.5 2.929795 |
。
提供接口定义中声明的方法的任何类型都可以存储在该类型的接口变量中。当您存储的实际值是一个切片时,任何类型都可以实现该接口。而且,由于在许多情况下,静态地确定接口变量的动态类型是不可能的,因此在没有显式类型断言的情况下,该语言不允许您浏览封面下面的内容。
如果您希望实现
1 2 3 4 | type Sequencer interface { Mean() float64 Slice(start, end int) Sequencer } |
号
这可以以明显的方式为您的
1 2 3 | func (s Sequence) Slice(start, end int) Sequencer { return s[start:end] } |
然后可以使用以下方法获得切片的平均值:
1 | fmt.Println(c.Slice(0, 2).Mean()) |
。
你可以在这里试验这个解决方案:http://play.golang.org/p/umuqoarluu
当然。这与任何其他具有接口概念的语言都没有区别。
您试图在不支持它的类型上调用"operator"
例如,如果这是C,您实际上是在尝试:
1 2 3 4 5 6 7 | interface Sequencer { float Mean(); } Sequencer c = ...; c[any_index] ... // error - interface doesn't have this operator defined |
这里的限制是不能在go中实现运算符重载。如果可以的话,那么您就可以将它添加到接口中,并且所有的操作都会按预期进行。