Golang反映包装“不是一种类型”

时间:2022-08-30 17:43:53

I'm trying to learn interfaces and how I can write a single function to work with different types. I came up with this example where I'm finding the maximum value in either a slice of int or a slice of float32. The code is as follows. I keep getting this error "t is not a type". Could someone please tell me what is wrong and how I might go about fixing it?

我正在尝试学习接口,以及如何编写一个函数来处理不同类型的函数。我找到了这个例子,我在这里找到了一个整数的最大值或者一个浮点数。代码如下。我一直得到这个错误"t不是一个类型"谁能告诉我哪里出了问题,我该怎么解决?

package main

import "fmt"
import "reflect"

var _ = fmt.Println
var _ = reflect.TypeOf

func maxer(s interface{}) interface{} {
    v := reflect.ValueOf(s)
    t := v.Type()

    maxval := s.(t)[0]
    for _, v := range s.(t)[1:] {
        if v > maxval {
            maxval = v
        }
    }
    return maxval
}

func main() {
    fmt.Println(maxer([]int{1, 2, 3, 4}))
    fmt.Println(maxer([]float32{1.1, 2.1, 3.14, 0.1, 2.4}))

3 个解决方案

#1


1  

I think you're going to end up needing to manually handle different types in this case. AFAIK, type assertions must be real types at compile time. Here's my best try in play: http://play.golang.org/p/J8RdHF2MVV

我认为在这种情况下,您将需要手动处理不同类型。AFAIK,类型断言在编译时必须是真正的类型。下面是我的最佳尝试:http://play.golang.org/p/J8RdHF2MVV。

#2


1  

I'm trying to learn interfaces and how I can write a single function to work with different types.

我正在尝试学习接口,以及如何编写一个函数来处理不同类型的函数。

then it's probably simpler to avoid the whole reflection package, and just define an interface for your specific purpose.. and types that implement your interface. something like this:

然后,避免整个反射包可能更简单,只需要为特定的目的定义一个接口。以及实现接口的类型。是这样的:

package main

import "fmt"
import "math"


// Homegrown types
type IntArray []int
type Float32Array []float32


// Max defined for type IntArray
func (a IntArray) Max() float64 {
    max := math.MinInt32;
    for i := 0; i < len(a); i++ {
        if a[i] > max {
            max = a[i]
        }
    }
    return float64(max)
}


// Max defined for type Float32Array
func (a Float32Array) Max() float64 {
    max := float32(-1 * math.MaxFloat32)
    for i := 0; i < len(a); i++ {
        if a[i] > max {
            max = a[i]
        }
    }
    return float64(max)
}


// Define an interface that works for any type
// containing a Max function returning a float64 
type Maxing interface {
    Max() float64
}


// Define a function that works with your interface type
func maxer(m Maxing) float64 {
    return m.Max();
}


func main(){

    // Declare a new IntArray
    i := IntArray([]int{1,2,3})

    // Declare a new Float32Array
    f := Float32Array([]float32{1.0,2.0,3.0})

    // Use any type implementing the Max interface with the 'maxer' func
    fmt.Printf("maxer(IntArray)     = %f\n", maxer(i));
    fmt.Printf("maxer(Float32Array) = %f\n", maxer(f));

}

#3


0  

Similar to bjarneh's response. If you want to do this via interfaces, best to avoid reflect. Reflect is not good for comparing values, because you cannot know what type the values are.

类似于bjarneh的反应。如果您想通过接口实现这一点,最好避免反射。反射不适合比较值,因为您不知道值是什么类型。

My suggestion is to implement something similar to go's sort interface which allows you to use the function sort on any type.

我的建议是实现类似go的sort接口,它允许您使用任何类型的函数排序。

Implementing it this way would then allow you to get max value for structs or strings, as long as you implemented the functions for them.

通过这种方式实现,可以让您获得结构或字符串的最大值,只要您实现了它们的函数。

On go playgorund

playgorund围棋

package main

import (
    "fmt"
)

type Comparable interface {
    Less(i, j int) bool
    Len() int
    Val(i int) interface{}
}

func maxer(s Comparable) (interface{}) {
    if s.Len() == 0 {
        return nil
    }
    maxI := 0
    for i := 1; i < s.Len(); i++ {
        if s.Less(maxI, i) {
            maxI = i
        }
    }
    return s.Val(maxI)
}

type MaxerInt []int
func (m MaxerInt) Len() int {return len(m)}
func (m MaxerInt) Val(i int) interface{} {return m[i]}
func (m MaxerInt) Less(i, j int) bool {return m[i] < m[j]}

type MaxerFloat []float64
func (m MaxerFloat) Len() int {return len(m)}
func (m MaxerFloat) Val(i int) interface{} {return m[i]}
func (m MaxerFloat) Less(i, j int) bool {return m[i] < m[j]}

func main() {
    fmt.Println(maxer(MaxerInt{1, 2, 3, 4}))
    fmt.Println(maxer(MaxerFloat{1.1, 2.1, 3.14, 0.1, 2.4}))
}

#1


1  

I think you're going to end up needing to manually handle different types in this case. AFAIK, type assertions must be real types at compile time. Here's my best try in play: http://play.golang.org/p/J8RdHF2MVV

我认为在这种情况下,您将需要手动处理不同类型。AFAIK,类型断言在编译时必须是真正的类型。下面是我的最佳尝试:http://play.golang.org/p/J8RdHF2MVV。

#2


1  

I'm trying to learn interfaces and how I can write a single function to work with different types.

我正在尝试学习接口,以及如何编写一个函数来处理不同类型的函数。

then it's probably simpler to avoid the whole reflection package, and just define an interface for your specific purpose.. and types that implement your interface. something like this:

然后,避免整个反射包可能更简单,只需要为特定的目的定义一个接口。以及实现接口的类型。是这样的:

package main

import "fmt"
import "math"


// Homegrown types
type IntArray []int
type Float32Array []float32


// Max defined for type IntArray
func (a IntArray) Max() float64 {
    max := math.MinInt32;
    for i := 0; i < len(a); i++ {
        if a[i] > max {
            max = a[i]
        }
    }
    return float64(max)
}


// Max defined for type Float32Array
func (a Float32Array) Max() float64 {
    max := float32(-1 * math.MaxFloat32)
    for i := 0; i < len(a); i++ {
        if a[i] > max {
            max = a[i]
        }
    }
    return float64(max)
}


// Define an interface that works for any type
// containing a Max function returning a float64 
type Maxing interface {
    Max() float64
}


// Define a function that works with your interface type
func maxer(m Maxing) float64 {
    return m.Max();
}


func main(){

    // Declare a new IntArray
    i := IntArray([]int{1,2,3})

    // Declare a new Float32Array
    f := Float32Array([]float32{1.0,2.0,3.0})

    // Use any type implementing the Max interface with the 'maxer' func
    fmt.Printf("maxer(IntArray)     = %f\n", maxer(i));
    fmt.Printf("maxer(Float32Array) = %f\n", maxer(f));

}

#3


0  

Similar to bjarneh's response. If you want to do this via interfaces, best to avoid reflect. Reflect is not good for comparing values, because you cannot know what type the values are.

类似于bjarneh的反应。如果您想通过接口实现这一点,最好避免反射。反射不适合比较值,因为您不知道值是什么类型。

My suggestion is to implement something similar to go's sort interface which allows you to use the function sort on any type.

我的建议是实现类似go的sort接口,它允许您使用任何类型的函数排序。

Implementing it this way would then allow you to get max value for structs or strings, as long as you implemented the functions for them.

通过这种方式实现,可以让您获得结构或字符串的最大值,只要您实现了它们的函数。

On go playgorund

playgorund围棋

package main

import (
    "fmt"
)

type Comparable interface {
    Less(i, j int) bool
    Len() int
    Val(i int) interface{}
}

func maxer(s Comparable) (interface{}) {
    if s.Len() == 0 {
        return nil
    }
    maxI := 0
    for i := 1; i < s.Len(); i++ {
        if s.Less(maxI, i) {
            maxI = i
        }
    }
    return s.Val(maxI)
}

type MaxerInt []int
func (m MaxerInt) Len() int {return len(m)}
func (m MaxerInt) Val(i int) interface{} {return m[i]}
func (m MaxerInt) Less(i, j int) bool {return m[i] < m[j]}

type MaxerFloat []float64
func (m MaxerFloat) Len() int {return len(m)}
func (m MaxerFloat) Val(i int) interface{} {return m[i]}
func (m MaxerFloat) Less(i, j int) bool {return m[i] < m[j]}

func main() {
    fmt.Println(maxer(MaxerInt{1, 2, 3, 4}))
    fmt.Println(maxer(MaxerFloat{1.1, 2.1, 3.14, 0.1, 2.4}))
}