如何在go中获取函数的地址?

az31mfrm  于 2023-05-27  发布在  Go
关注(0)|答案(4)|浏览(119)

在Go语言中可以获取函数引用的地址吗?
就像

func myFunction() {
}

// ...

unsafe.Pointer(&myFunction)

但事实并非如此。我猜这是不可能的,但我还没有找到任何证据。

编辑:背景

我的问题的背景来自于处理CGO和C函数指针。这个方法的作用是:

/*
void go_myFunction();

typedef void (*myFunction_f)();

myFunction_f pMyFunction;
*/
import "C"

//export go_myFunction
func go_myFunction() {
// ...
}

func SetupFp() {
  C.pMyFunction = (*[0]byte)(unsafe.Pointer(C.go_myFunction))
}

我也知道文档中指出传递一个指向go函数的指针是不起作用的。但是上面的代码似乎离它不远了。我只是想知道是否有人可以以某种方式跳过出口步骤。

bihw5rsg

bihw5rsg1#

Go语言中的function类型是不可寻址的,也是不可比较的,因为:
函数指针表示函数的代码。而且由function literal创建的匿名函数的代码在内存中只存储一次,不管返回匿名函数值的代码运行了多少次。
Original answer
如果你需要比较一个函数的地址,你可以用reflect.Pointer来做。但无论如何,这种操作比不可能更无意义,因为:
如果v的Kind是Func,则返回的指针是底层代码指针,但不一定足以唯一地标识单个函数。唯一的保证是当且仅当v是nil func Value时结果为零。

zfciruhq

zfciruhq2#

你可以像这样得到一个Go函数的地址:

package main

import (
    "fmt"
    "reflect"
)

func HelloWorld() {
    fmt.Println("Hello, world!")
}

func main() {
    var ptr uintptr = reflect.ValueOf(HelloWorld).Pointer()
    fmt.Printf("0x%x", ptr)
}
nwsw7zdq

nwsw7zdq3#

可以使用函数GetFuncAddr获取函数地址:

package main

     import (
         "fmt"
         "unsafe"
         "reflect"
      )

     func HelloWorld() {
        fmt.Println("Hello, world!")
     }

     func GetFuncAddr(i interface{}) uintptr {
     type IHeader struct {
        typ  uintptr
        word uintptr
      }
    
    return (*IHeader)(unsafe.Pointer(&i)).word
    }

  func main() {
   tmp := HelloWorld
   ptr1 := *(*uintptr)(unsafe.Pointer(&tmp)) //Way 1

   ptr2 := GetFuncAddr(HelloWorld)  //Way 2
   fmt.Printf("0x%x = 0x%x", ptr1, ptr2)

   //Thits is not are functon addrress!!!
   BadPTR1 := reflect.ValueOf(HelloWorld).Pointer()
   BadPTR2 := **(**uintptr)(unsafe.Pointer(&tmp)) //dereferenced pointer
   fmt.Printf("\nBAD: 0x%x = 0x%x", BadPTR1 , BadPTR2 )
  }
lsmepo6l

lsmepo6l4#

你可以这样做:

myFunction := func() {}
fmt.Println(&myFunction)

相关问题