簡體   English   中英

go 如何檢查函數是否存在

[英]go how to check if a function exists

有什么方法可以檢查 Go 中是否存在 func 嗎?

在 PHP 中,我可能會做類似的事情

if(function_exists('someFunction')) {
    //...
}

但我一直無法弄清楚如何在 Go 中做到這一點

對此的任何幫助都將受到極大的歡迎。

關於您正在嘗試做的事情的更多背景信息會有所幫助。 正如您在自己的評論中所指出的,如果您嘗試調用函數,Go 在編譯時檢查該函數是否存在,大多數情況下。

我想到的一個例外是當你使用interface{}並且你想在調用它之前檢查一個方法是否存在。 為此,您可以使用類型檢查。

例子:

package main

import "fmt"

// a simple Greeter struct
// with a Hello() method defined
type Greeter struct {
    Name string 
}
func (m *Greeter) Hello() string {
    return "hello " + m.Name
}

var x interface{}

func main() {
    x = Greeter {Name:"Paolo"} // x is a interface{}
    g,ok := x.(Greeter) // we have to check that x is a Greeter...
    if ok {
        fmt.Println(g.Hello()) // ...before being able to call Hello()
    }
} 

我能想到的另一種情況是,您正在為 Go 創建自己的工具,該工具需要在編譯 go 文件之前對其進行解析。 如果是這樣,Go 在解析器包的 for 中提供幫助

沒有辦法做到這一點(而且永遠是好的!)。 原因是 Go 是一種編譯語言,不支持可加載模塊(至少),所以函數不能在運行時來來去去,因此是否存在頂級函數,你可以通過定義知道:如果給定的源文件import sa 包含感興趣的函數1的包,該函數在此源文件中可見。 或者這個函數是在這個源文件所屬的同一個包中聲明的,因此它也是可用的。 在所有其他情況下,該功能不可用。 請注意,一個函數可能會在程序中編譯,但在編譯時在給定的源文件中仍然不可見,因此您所說的可見性的整個定義在 Go 中不存在。

另一方面,您可能需要一些通用性。 Go 中的通用性是通過接口實現的。 您可能會定義一個接口,然后需要一個類型來實現它。 檢查一個類型是否實現了一個接口是通過一個巧妙的技巧來完成的。


2021 年 12 月 29 日的更新。
Go 1.8中以plugin包的形式添加了對可加載模塊的支持,並且從那時起已經成熟以支持除 Windows 之外的大多數主流平台。
盡管如此,這個解決方案也不是沒有問題——例如,參見#20481


1沒有將該模塊重命名為空,但我們暫時不要觸及它。

假設你的東西是一個接口值,類型斷言,像這樣:

if Aer, ok := thing.(interface{MethodA()}); ok { 
  Aer.MethodA() 
} 

如果 thing 是一個結構,首先將它分配給一個接口變量,因為類型斷言只對接口值起作用。

定義一個命名接口而不是使用 nonce 不會有什么壞處,但是對於像這樣的簡單情況,這是不值得的。

最近我需要弄清楚一個結構是否具有特定的功能。 這是使用反射的另一種方法:

package main
     
import (
    "fmt"
    "reflect"
)

type FuncRegistry struct {}
  
func (fr FuncRegistry) Hi() {
    fmt.Println("function Hi")
}

func (fr FuncRegistry) Hello() {
    fmt.Println("function Hello")
}

func functionExists(obj interface{},funcName string) bool { 
     mthd := reflect.ValueOf(obj).MethodByName(funcName)
     if mthd.IsValid() { 
         fmt.Printf("Function '%s' exists \n",funcName)
         return true 
     } 
     
     fmt.Printf("Function '%s' does not exist\n",funcName)
     return false 
} 

// Main function
func main() {
    var fr FuncRegistry
    functionExists(fr,"Hi")
    functionExists(fr,"Hello")
    functionExists(fr,"Fail")
}

這聽起來很像XY 問題 請告訴您您要做什么。 據我所知,這是你不能像在 PHP 中那樣做的事情。

但是,您可以創建一個以函數名作為鍵的映射。 在那里手動添加函數或通過在編譯前或運行時解析源文件來生成內容。 不過,解析源代碼似乎是一種骯臟的黑客行為。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM