Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Types golang的通用切片类型?_Types_Go_Slice - Fatal编程技术网

Types golang的通用切片类型?

Types golang的通用切片类型?,types,go,slice,Types,Go,Slice,我在尝试将切片类型扩展为Go中的常规类型时遇到了一些困难。我创建了一个示例代码来解释我的问题 main()函数的最后一行返回一个错误,指出Sequencer类型的变量无法切片: 无法切片c(类型序列器) 有没有一种方法可以定义一般类型的切片(int、float64、string等),而不隐藏切片的索引功能?当然可以。这与任何其他具有接口概念的语言没有什么不同 您试图在不支持“运算符”[]的类型上调用它-Sequencer(接口)。然而,Sequence确实如此,因为它具有片的属性,因此调用b.M

我在尝试将切片类型扩展为Go中的常规类型时遇到了一些困难。我创建了一个示例代码来解释我的问题

main()函数的最后一行返回一个错误,指出Sequencer类型的变量无法切片:

无法切片c(类型序列器)


有没有一种方法可以定义一般类型的切片(int、float64、string等),而不隐藏切片的索引功能?

当然可以。这与任何其他具有接口概念的语言没有什么不同

您试图在不支持“运算符”
[]
的类型上调用它-
Sequencer
(接口)。然而,
Sequence
确实如此,因为它具有片的属性,因此调用
b.Mean
b[:]
有效

例如,如果这是C#,那么您实际上是在尝试:

interface Sequencer {
    float Mean();
}

Sequencer c = ...;

c[any_index] ... // error - interface doesn't have this operator defined

这里的限制是不能在Go中实现运算符重载。如果可以,那么您就可以将其添加到接口中,所有这些都将按照预期进行。

任何提供接口定义中声明的方法的类型都可以存储在该类型的接口变量中。虽然您存储的实际值是一个切片,但任何类型都可以实现该接口。由于在许多情况下,静态地确定接口变量的动态类型是不可能的,因此如果没有显式的类型断言,该语言不允许您深入了解

如果您希望类型实现您的
Sequencer
类型来实现切片,那么简单的解决方案是扩展接口以包括这样一种方法:

type Sequencer interface {
    Mean() float64
    Slice(start, end int) Sequencer
}
这可以通过明显的方式为您的
序列
类型实现:

func (s Sequence) Slice(start, end int) Sequencer {
    return s[start:end]
}
然后,可以使用以下方法获得切片的平均值:

fmt.Println(c.Slice(0, 2).Mean())
您可以在此处尝试此解决方案:

您有

type Sequencer interface {
    Mean() float64
}

c := Sequencer(b)
因此,变量
c
包含满足
Sequencer
接口的某种类型的值;该类型具有
Mean
方法。这就是我们所能说的,不多也不少。这并不意味着变量
c
值可以切片。因此,切片表达式
c[:2]
无效。例如,我们可以定义一个类型
Map
,它满足
Sequencer
接口,但不能切片。如果您想要切片
c
,则断言它属于可以切片的类型,例如,
c.(序列)[: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

那么您的答案是没有办法在切片中定义的“[]”上实现运算符重载吗?没有。。我的答案是你不能定义操作符。。因此,您的接口无法定义一个。当您试图通过接口的“眼睛”访问变量时。。它不会看到的。因此,您必须使用自定义的
typedef
来访问
typesequence[]int
并以这种方式访问它。但是如果我事先不知道切片的类型呢?那么我就不能索引一个通用的切片类型了?不,因为Go没有泛型。您可以查看类型断言,或者打开一个类型来实现这一点。。而且很快就会变得很难看。也许有一种方法可以用reflect软件包实现这一点……我最喜欢这个建议,因为它使切片变得通用而没有任何类型断言,但我仍然认为不能使用方便的索引样式[:]是一件遗憾的事,我们不需要知道切片维度……是的+1。我没有包含断言示例(我真的很懒:/)
2.5
1.5
2.5
1.5
2.929795