在 Go 中使用反射来获取结构的名称 [英] using reflection in Go to get the name of a struct

查看:88
本文介绍了在 Go 中使用反射来获取结构的名称的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

如何在Golang?

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

包主进口 (fmt"反映")类型 Ab 结构 {}func getType(myvar interface{}) string {返回reflect.TypeOf(myvar).Name()}功能主(){fmt.Println("你好,游乐场")tst := "字符串"tst2 := 10tst3 := 1.2tst4 := 新的(Ab)fmt.Println(getType(tst))fmt.Println(getType(tst2))fmt.Println(getType(tst3))fmt.Println(getType(tst4))}

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

但输出是:

你好,游乐场细绳整数浮动64程序退出.

预期输出为:

你好,游乐场细绳整数浮动64抗体程序退出.

我试图通过阅读文档来弄清楚,但没有找到相关问题.所以,对于这个非常普遍的问题,抱歉,但是:

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

解决方案

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

坚持Type.Name()

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

func getType(myvar interface{}) string {如果 t :=reflect.TypeOf(myvar);t.Kind() == 反射.Ptr {返回 "*" + t.Elem().Name()} 别的 {返回 t.Name()}}

测试:

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

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

抗体*抗体

注意:

请注意,由于 Type.Name() 不解析指针,如果传递的值是指向指针的指针,则它不起作用,例如**Ab,虽然 Type.String() 自动解析指针,但在这种情况下也能工作.

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

func getType(myvar interface{}) (res string) {t :=reflect.TypeOf(myvar)对于 t.Kind() ==reflect.Ptr {t = t.Elem()资源 += "*"}返回 res + t.Name()}

用值调用它:

tst4 := Ab{}tst5 := 新的(Ab)tst6 := &tst5//**Ab 的类型tst7 := &tst6//***Ab 的类型

输出(在 Go Playground 上试试):

抗体*抗体**抗体***抗体

使用Type.String()

一种更简单更好的方法是使用 Type.String() 而不是 Type.Name(),后者会自动处理指针并包含包名称.例如:

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

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

字符串整数浮动64主要抗体*主抗体

Go Playground 上试试这个变体.

I found this question with this great answers:

How to find a type of a object in Golang?

I played around with the answer and tried to get the name of a struct in the same way:

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))

}

Go playground: http://play.golang.org/p/tD8mygvETH

But the output is:

Hello, playground
string
int
float64


Program exited.

Expected output would be:

Hello, playground
string
int
float64
Ab

Program exited.

I tried to figure out by reading the documentation but didn't find the issue about that. So, sorry for the very general question, but:

What's the reason, reflect.TypeOf().Name() does not work with (this) struct(s)?

解决方案

In your example you pass a value of pointer type (*Ab), not a struct type.

Sticking to Type.Name()

If it is not a pointer, Type.Name() will properly return Ab. In case of pointer if you still want the struct's name, you can use Type.Elem() to get the element's type:

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

Testing it:

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

Output (try your modified example on the Go Playground):

Ab
*Ab

Note:

Note that as Type.Name() does not resolve pointers, it would not work if the value passed is a pointer to pointer, e.g. **Ab, while as Type.String() automatically resolves pointers, would work in this case too.

We can easily make our getType() function to work with **Ab too (or with any depth of pointers):

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

Calling it with values:

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

Output (try it on the Go Playground):

Ab
*Ab
**Ab
***Ab

Using Type.String()

A simpler and better approach would be to use Type.String() instead of Type.Name() which automatically handles pointers and also includes package name. E.g.:

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

For the modified example it outputs:

string
int
float64
main.Ab
*main.Ab

Try this variant on the Go Playground.

这篇关于在 Go 中使用反射来获取结构的名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆