duandao3265 2016-03-04 08:05
浏览 349
已采纳

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

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

  • 写回答

3条回答 默认 最新

  • doukuilian8365 2016-03-04 08:16
    关注

    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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 名为“Product”的列已属于此 DataTable
  • ¥15 安卓adb backup备份应用数据失败
  • ¥15 eclipse运行项目时遇到的问题
  • ¥15 关于#c##的问题:最近需要用CAT工具Trados进行一些开发
  • ¥15 南大pa1 小游戏没有界面,并且报了如下错误,尝试过换显卡驱动,但是好像不行
  • ¥15 没有证书,nginx怎么反向代理到只能接受https的公网网站
  • ¥50 成都蓉城足球俱乐部小程序抢票
  • ¥15 yolov7训练自己的数据集
  • ¥15 esp8266与51单片机连接问题(标签-单片机|关键词-串口)(相关搜索:51单片机|单片机|测试代码)
  • ¥15 电力市场出清matlab yalmip kkt 双层优化问题