如何将类型传递给函数参数

时间:2018-06-29 08:13:13

标签: go

错误:类型CustomStruct不是表达式。

type CustomStruct struct {
}

func getTypeName(t interface{}) string {
    rt := reflect.TypeOf(t).Elem()
    return rt.Name()
}

getTypeName(CustomStruct)

如何在没有类型实例的情况下将结构类型传递给函数?

这将起作用

getTypeName((*CustomStruct)(nil))

但是我想知道是否还有更简单的版本。

2 个答案:

答案 0 :(得分:7)

不能。您只能传递一个值,并且CustomStruct不是值,而是类型。使用类型标识符是编译时错误。

通常,当要传递“类型”时,您传递描述该类型的reflect.Type值。这是您在getTypeName()内“创建”的内容,但是getTypeName()几乎没什么可做的:

func getTypeName(t reflect.Type) string {
    return t.Name()
}

// Calling it:
getTypeName(reflect.TypeOf(CustomStruct{}))

(也不要忘记,对于诸如[]int之类的匿名类型,它返回一个空字符串。)

另一种方法是像您一样传递“类型化的” nil指针值,但是同样,您也可以使用类型化的nil值来创建reflect.Type,而不创建相关类型的值,例如:

t := reflect.TypeOf((*CustomStruct)(nil)).Elem()
fmt.Println(t.Name()) // Prints CustomStruct

答案 1 :(得分:1)

让我们复活这个!

Go 的泛型提案获得批准,并且最终会到来。当这个问题第一次被问到时,这可能更有意义,但是对于现在想要实现泛型模式的任何人来说,我想我已经有了一个不错的 API。

目前,您不能与抽象类型交互,但您可以与抽象类型上的方法交互,并且反射允许您检查函数签名。对于方法,第 0 个是接收者。

type Example struct {int}
type Generic struct{reflect.Type}

func (p Example) Type() {}

func Reflect(generic interface{}) Generic {
    real := reflect.TypeOf(generic)
    if real.Kind() != reflect.Func || real.NumIn() < 1 {
        panic("reflect.Type.In(n) panics if not a func and if n out of bounds")
    }
    return Generic{real.In(0)}
}

func (g Generic) Make() interface{} {
    return reflect.Zero(g.Type).Interface()
}

func main() {
    tOfp := Reflect(Example.Type)
    fmt.Printf("Name of the type: %v\n", tOfp.Name()) 
    fmt.Printf("Real (initial)value: %v\n", tOfp.Make())
}

一些快速笔记:

  1. “示例”的结构并不重要,重要的是它有一个带有非指针接收器的方法。
  2. 将称为“通用”的类型定义为结构体是为了实现我认为 OP 的实际意图。
  3. 上面对“Generic”的定义是一个结构体而不是一个接口,因此它可以有自己的方法集。将“通用”定义为接口,并使用特定于与其一起使用的每个操作数类型的方法集会很有意义。

如果您不知道,真正的泛型将在 Go 1.18 中出现。我上面的例子没有 linter 或编译保护,如果使用不当会在运行时发生恐慌。它确实有效,并且可以让您在等待本机实现时对抽象类型进行推理。

快乐编码!