【问题标题】:How to get a pointer of an interface如何获取接口的指针
【发布时间】:2019-12-15 01:03:04
【问题描述】:

这很难解释,但是我怎样才能得到一个实现了某个接口的 something 的指针呢?


考虑下面的代码:

package main

import (
    "fmt"
    "unsafe"
)

type Interface interface {
    Example()
}

type StructThatImplementsInterface struct {
}

func (i *StructThatImplementsInterface) Example() {
}

type StructThatHasInterface struct {
    i Interface
}


func main() {
    sameInterface := &StructThatImplementsInterface{}

    struct1 := StructThatHasInterface{i: sameInterface}
    struct2 := StructThatHasInterface{i: sameInterface}

    TheProblemIsHere(&struct1)
    TheProblemIsHere(&struct2)

}

func TheProblemIsHere(s *StructThatHasInterface) {
    fmt.Printf("Pointer by Printf: %p \n", s.i)
    fmt.Printf("Pointer by Usafe: %v \n", unsafe.Pointer(&s.i))
}

https://play.golang.org/p/HoC5_BBeswA


结果将是:

Pointer by Printf: 0x40c138 
Pointer by Usafe: 0x40c140 
Pointer by Printf: 0x40c138 
Pointer by Usafe: 0x40c148 

注意Printf 获得相同的值(因为两个StructThatHasInterface 使用相同的sameInterface)。但是,unsafe.Pointer() 返回不同的值。

如果可能,我如何在不使用fmtreflect 的情况下获得Printf 的相同结果?

【问题讨论】:

  • 两个struct值中i字段的地址是不同的值,因此unsafe.Pointer(&s.i)是不同的值。 .如果您不想假设接口在内存中的表示方式 (reflect.ValueOf(s.i).Pointer()),则可以使用 reflect 包。为什么不想使用反射包?
  • @CeriseLimón 我认为存在一种 更简单 的方式,而不是反映和理解 reflect 如何获得该值。我看reflect,他们使用(*emptyInterface)(unsafe.Pointer(&i)).word,但我不能让它在reflect之外工作,似乎reflect内部有一些magic
  • 表达式(*[2]uintptr)(unsafe.Pointer(&s.i))[1] 有效,但不能保证它将来会有效。 Value.Pointer 方法是解决此问题的受支持方法。其他解决方案要求您对内存布局做出假设。这对我来说似乎并不容易。
  • @CeriseLimón 你能解释一下它为什么有效吗?请将其发布为答案,然后我可以标记为“正确答案”。 :)

标签: go unsafe-pointers


【解决方案1】:

在当前版本的 Go 中,一个接口值是两个字长。具体值或指向具体值的指针存储在第二个字中。使用以下代码获取第二个单词为uintptr

  u := (*[2]uintptr)(unsafe.Pointer(&s.i))[1]

此代码不安全,不保证将来可以正常工作。

支持的获取指针的方式是:

  u := reflect.ValueOf(s.i).Pointer()

【讨论】:

    猜你喜欢
    • 2019-07-07
    • 1970-01-01
    • 1970-01-01
    • 2012-10-05
    • 2017-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-26
    相关资源
    最近更新 更多