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 已知许多点位,想通过高斯分布来随机选择固定数量的点位怎么改
  • ¥15 怎么生成确定数目的泊松点过程
  • ¥15 layui数据表格多次重载的数据覆盖问题
  • ¥15 python点云生成mesh精度不够怎么办
  • ¥15 QT C++ 鼠标键盘通信
  • ¥15 改进Yolov8时添加的注意力模块在task.py里检测不到
  • ¥50 高维数据处理方法求指导
  • ¥100 数字取证课程 关于FAT文件系统的操作
  • ¥15 如何使用js实现打印时每页设置统一的标题
  • ¥15 安装TIA PortalV15.1报错