[英]General slice type in golang?
我在尝试将切片类型扩展为Go中的常规类型时遇到了一些困难。 我已经创建了一个示例代码来解释我的问题。 玩地面版
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类型的变量不能被切片:
不能切片c(类型序列器)
有没有一种方法可以定义一般类型的切片(int,float64,string,...)而不隐藏切片的很酷的索引功能?
你有
type Sequencer interface {
Mean() float64
}
c := Sequencer(b)
因此,变量c
包含满足Sequencer
接口的某种类型的值; 该类型具有Mean
方法。 这就是我们所能说的,不多也不少。 这并不意味着可以切片变量c
值。 因此,切片表达式c[:2]
无效。 例如,我们可以定义一个类型Map
,它满足Sequencer
接口但不能被切片。 如果你想切片c
然后断言它是一个可以切片的类型,例如, c.(Sequence)[:2]
。
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())
}
输出:
2.5
1.5
2.5
1.5
2.929795
提供接口定义中声明的方法的任何类型都可以存储在该类型的接口变量中。 虽然您存储的实际值是一个切片,但任何类型都可以实现该接口。 并且由于在许多情况下不可能静态地确定接口变量的动态类型,因此如果没有显式的类型断言,语言不会让您在封面下面查看。
如果切片是您期望实现Sequencer
类型的类型实现的,那么简单的解决方案是扩展接口以包含这样的方法:
type Sequencer interface {
Mean() float64
Slice(start, end int) Sequencer
}
这可以通过显而易见的方式为您的Sequence
类型实现:
func (s Sequence) Slice(start, end int) Sequencer {
return s[start:end]
}
然后,您可以使用以下方法获取切片的平均值:
fmt.Println(c.Slice(0, 2).Mean())
您可以在此处试验此解决方案: http : //play.golang.org/p/UMuqOarLUu
当然。 这与具有接口概念的任何其他语言没有什么不同。
你试图在一个不支持它的类型上调用“operator” []
- Sequencer
(一个接口)。 然而, Sequence
确实 - 因为它具有切片的属性,因此对b.Mean
和b[:]
的调用起作用。
如果这是C#,例如,你实际上是在尝试这个:
interface Sequencer {
float Mean();
}
Sequencer c = ...;
c[any_index] ... // error - interface doesn't have this operator defined
这里的限制是你不能在Go中实现运算符重载。 如果可以 - 那么你就可以将它添加到界面中,并且所有内容都会按预期方式进行。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.