doumianfeng5065 2016-05-27 23:49 采纳率: 0%
浏览 53

golang-如何访问struct的内部(反射?)

I need to add attributes to a log15 logger, but if I inadvertently add one twice it will appear twice. So, I want to add logic to see if the attribute is already populated and skip the action if it is.

Here's what I get when I output the log object:

log="&{ctx:[field1 val1 field2 val2 field3 val3 field2 val2] h:0xc82052c1e0}"

How can I access that 'ctx' field and validate when my value is already there? I've tried some reflection tricks and can get the data type, but I can't figure out how to get the value.

  • 写回答

1条回答 默认 最新

  • douzhuo6931 2016-05-28 01:23
    关注

    I will first go through what you asked for exactly, that is access the attributes stored in the logger's context.

    Reflection in Go is based on Type and Value. You do not have access to any data using Type, you just have information about the type (surprise !). So, here you have to use the Value side of reflection.

    However, the problem is that the ctx field of the logger is not exported, so it's not possible to access it directly. However, using a bit of unsafe operations make it doable.

    Here is the code:

    package main
    
    import (
        "fmt"
        "reflect"
        "unsafe"
    )
    
    type logger struct {
        ctx []interface{}
    }
    
    type Logger interface {
        Populate(ctx ...interface{})
    }
    
    func NewLogger() Logger {
         return &logger{}
    }
    
    func (l *logger) Populate(ctx ...interface{}) {
        l.ctx = ctx
    }
    
    func main() {
        log := NewLogger()
        log.Populate(42, "42", 84, "84")
        fmt.Println(log)
        // &{[42 42 84 84]}
        v := reflect.ValueOf(log).Elem()
        field := v.FieldByName("ctx")
        ar := *(*[]interface{})(unsafe.Pointer(field.UnsafeAddr()))
    
        for _, i := range ar {
            fmt.Println(i)
        }
        // 42 42 84 84
    }
    

    Go playground

    Do NEVER do that

    The code works, and produces what you expect. However, what you are doing is using reflection and unsafe operations to get values from an unexported struct of a third-party library. My english is not good enough to express properly how bad this is.

    If you don't want to have twice the same attribute in the logger, do not put it twice in the first place, it's far better and easier than maintaining the code that's above.

    If you still do not trust yourself enough for this, then wrap the logger in a struct where you store the attributes contained in the logger. At least it will be something you have your hands on, and do the same job.

    So, you're free to use this code. But if you want to do yourself a favor, you won't use it in that case.

    评论

报告相同问题?

悬赏问题

  • ¥15 R语言Rstudio突然无法启动
  • ¥15 关于#matlab#的问题:提取2个图像的变量作为另外一个图像像元的移动量,计算新的位置创建新的图像并提取第二个图像的变量到新的图像
  • ¥15 改算法,照着压缩包里边,参考其他代码封装的格式 写到main函数里
  • ¥15 用windows做服务的同志有吗
  • ¥60 求一个简单的网页(标签-安全|关键词-上传)
  • ¥35 lstm时间序列共享单车预测,loss值优化,参数优化算法
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值