在 Go 中使用反射获取结构的名称

新手上路,请多包涵

我发现这个问题有很好的答案:

如何在 Golang 中查找对象的类型?

我尝试了答案并尝试以相同的方式获取结构的名称:

 package main

import (
        "fmt"
        "reflect"
)

type Ab struct {

}

func getType(myvar interface{}) string {
        return reflect.TypeOf(myvar).Name()
}

func main() {
        fmt.Println("Hello, playground")

        tst := "string"
        tst2 := 10
        tst3 := 1.2
        tst4 := new(Ab)

        fmt.Println(getType(tst))
        fmt.Println(getType(tst2))
        fmt.Println(getType(tst3))
        fmt.Println(getType(tst4))

}

去游乐场: http ://play.golang.org/p/tD8mygvETH

但输出是:

 Hello, playground
string
int
float64

Program exited.

预期输出将是:

 Hello, playground
string
int
float64
Ab

Program exited.

我试图通过阅读文档来弄清楚,但没有找到相关问题。所以,很抱歉这个非常笼统的问题,但是:

原因是什么, reflect.TypeOf().Name() 不适用于(这个)结构?

原文由 Daniele D 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.2k
2 个回答

在您的示例中,您传递了一个指针类型的值( *Ab ),而不是结构类型。

坚持 Type.Name()

如果它不是指针, Type.Name() 将正确返回 Ab 。在指针的情况下,如果您仍然想要结构的名称,则可以使用 Type.Elem() 来获取元素的类型:

 func getType(myvar interface{}) string {
    if t := reflect.TypeOf(myvar); t.Kind() == reflect.Ptr {
        return "*" + t.Elem().Name()
    } else {
        return t.Name()
    }
}

测试它:

 tst4 := Ab{}
tst5 := new(Ab)
fmt.Println(getType(tst4))
fmt.Println(getType(tst5))

输出(在 Go Playground 上尝试修改后的示例):

 Ab
*Ab

笔记:

请注意,因为 Type.Name() 不解析指针,如果传递的值是指向指针的指针,它将不起作用,例如 **Ab ,而 Type.String() 自动解析指针, 在这种情况下也适用。

我们可以轻松地使我们的 getType() 函数与 **Ab 一起工作(或使用任何深度的指针):

 func getType(myvar interface{}) (res string) {
    t := reflect.TypeOf(myvar)
    for t.Kind() == reflect.Ptr {
        t = t.Elem()
        res += "*"
    }
    return res + t.Name()
}

用值调用它:

 tst4 := Ab{}
tst5 := new(Ab)
tst6 := &tst5 // type of **Ab
tst7 := &tst6 // type of ***Ab

输出(在 Go Playground 上尝试):

 Ab
*Ab
**Ab
***Ab

使用 Type.String()

一个更简单和更好的方法是使用 Type.String() 而不是 Type.Name() 自动处理指针并且还包括包名称。例如:

 func getType(myvar interface{}) string {
    return reflect.TypeOf(myvar).String()
}

对于修改后的示例,它输出:

 string
int
float64
main.Ab
*main.Ab

Go Playground 上试试这个变体。

原文由 icza 发布,翻译遵循 CC BY-SA 3.0 许可协议

fmt 也有一个很酷的 %T 标签

package main

import (
    "fmt"
    "net/http"
)

type Potato struct {
}

func main() {
    fmt.Printf("I have a %T, an %T and a %T\n", Potato{}, http.StatusMultipleChoices, &http.Response{})
}

输出 I have a main.Potato, an int and a *http.Response https://play.golang.org/p/6z7_0BSitm

原文由 Azr 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题