duanchun1909 2019-08-28 16:54
浏览 1134
已采纳

如何在Go中获取指向Interface {}的基础值的指针

I'm interfacing with C code in Go using cgo, and I need to call a C function with a pointer to the underlying value in an Interface{} object. The value will be any of the atomic primitive types (not including complex64/complex128}, or string.

I was hoping I'd be able to do something like this to get the address of ptr as an unsafe.Pointer:

unsafe.Pointer(reflect.ValueOf(ptr).UnsafeAddr())

But this results in a panic due to the value being unaddressable.

A similar question to this is Take address of value inside an interface, but this question is different, as in this case it is known that the value will always be one of the types specified above (which will be at most 64 bits), and I only need to give this value to a C function. Note that there are multiple C functions, and the one that will be called varies based off of a different unrelated parameter.

I also tried to solve this using a type switch statement, however I found myself unable to get the address of the values even after the type assertion was done. I was able to assign the values to temporary copies, then get the address of those copies, but I'd rather avoid making these copies if possible.

  • 写回答

1条回答 默认 最新

  • doulu7258 2019-08-28 18:31
    关注

    interface{} has own struct:

    type eface struct {
        typ *rtype
        val unsafe.Pointer
    }
    

    You have no access to rtype directly or by linking, on the other hand, even though you'll copy whole rtype, it may be changed (deprecated) at future.

    But thing is that you can replace pointer types with unsafe.Pointer (it may be anything else with same size, but pointer is much idiomatic, because each type has own pointer):

    type eface struct {
        typ, val unsafe.Pointer
    } 
    

    So, now we can get value contained in eface:

    func some_func(arg interface{}) {
       passed_value := (*eface)(unsafe.Pointer(&arg)).val
       *(*byte)(passed_value) = 'b'
    }
    
    some_var := byte('a')
    
    fmt.Println(string(some_var)) // 'a'
    
    some_func(some_var)
    fmt.Println(string(some_var)) // 'a', it didn't changed, just because it was copied
    
    some_func(&some_var)
    fmt.Println(string(some_var)) // 'b'
    

    You also might see some more usages at my repo: https://github.com/LaevusDexter/fast-cast

    Sorry for my poor English.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥60 求一个简单的网页(标签-安全|关键词-上传)
  • ¥35 lstm时间序列共享单车预测,loss值优化,参数优化算法
  • ¥15 基于卷积神经网络的声纹识别
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP