英文:
Golang reflect package "is not a type"
问题
我正在尝试学习接口以及如何编写一个可以处理不同类型的单个函数。我想出了一个例子,其中我要找到一个int
切片或float32
切片中的最大值。代码如下所示。我一直收到错误信息“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}))
}
你的代码中出现了错误。在这里,你试图使用t
作为类型来访问切片s
的元素。然而,这是不允许的,因为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 := v.Index(0).Interface()
for i := 1; i < v.Len(); i++ {
elem := v.Index(i).Interface()
switch elem := elem.(type) {
case int:
if elem > maxval.(int) {
maxval = elem
}
case float32:
if elem > maxval.(float32) {
maxval = elem
}
}
}
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}))
}
修复后的代码使用了反射来获取切片的元素,并使用类型断言来比较不同类型的元素。这样,你就可以在一个函数中处理不同类型的切片了。希望对你有帮助!
英文:
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?
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}))
答案1
得分: 1
我认为在这种情况下,你最终需要手动处理不同的类型。据我所知,类型断言必须在编译时是真实的类型。这是我在playground上的最佳尝试:http://play.golang.org/p/J8RdHF2MVV
英文:
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
答案2
得分: 1
我正在尝试学习接口以及如何编写一个可以处理不同类型的单个函数。
如果你想简化问题,可以避免使用整个反射包,只需为你的特定目的定义一个接口,以及实现该接口的类型。类似这样:
package main
import "fmt"
import "math"
// 自定义类型
type IntArray []int
type Float32Array []float32
// IntArray 类型的 Max 方法
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)
}
// Float32Array 类型的 Max 方法
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)
}
// 定义一个接口,该接口适用于任何包含返回 float64 的 Max 方法的类型
type Maxing interface {
Max() float64
}
// 定义一个函数,该函数接受实现了 Maxing 接口的类型
func maxer(m Maxing) float64 {
return m.Max()
}
func main() {
// 声明一个新的 IntArray
i := IntArray([]int{1, 2, 3})
// 声明一个新的 Float32Array
f := Float32Array([]float32{1.0, 2.0, 3.0})
// 使用实现了 Max 接口的任何类型与 maxer 函数一起使用
fmt.Printf("maxer(IntArray) = %f\n", maxer(i))
fmt.Printf("maxer(Float32Array) = %f\n", maxer(f))
}
这段代码定义了两个自定义类型 IntArray
和 Float32Array
,它们分别实现了 Max
方法。然后定义了一个接口 Maxing
,该接口要求实现一个返回 float64
的 Max
方法。最后,定义了一个函数 maxer
,该函数接受实现了 Maxing
接口的类型,并调用其 Max
方法。
在 main
函数中,我们创建了一个 IntArray
和一个 Float32Array
,并将它们作为参数传递给 maxer
函数进行计算。
英文:
> 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
类似于bjarneh的回答。如果你想通过接口来实现这个功能,最好避免使用反射。反射对于比较值来说并不好,因为你无法知道值的类型。
我的建议是实现类似于Go语言的排序接口(sort.Interface),它允许你在任何类型上使用sort函数。
通过这种方式实现,你就可以获取结构体或字符串的最大值,只要你为它们实现了相应的函数。
在Go Playground上的代码示例:
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}))
}
希望对你有帮助!
英文:
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.
My suggestion is to implement something similar to go's sort interface which allows you to use the function sort on any type.
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.
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}))
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论