2012-09-01 32 views
1

如何在加載時向註冊表註冊某個對象(例如函數)以便向程序添加新程序包時會自動爲程序添加新功能,而無需修改其他程序包中的代碼?Go的下載包?

下面是一個代碼示例,它應該說明我正在嘗試做什麼。

的src /說/ say.go:

package main 

import (
    "os" 
    "reg" 
) 

func main() { 
    if len(os.Args) != 2 { 
     os.Stderr.WriteString("usage:\n say <what_to_say>\n") 
     os.Exit(1) 
    } 

    cmd, ok := reg.GetFunc(os.Args[1]) 
    if ok { 
     os.Stdout.WriteString(cmd()) 
     os.Stdout.Write([]byte{'\n'}) 
    } else { 
     os.Stderr.WriteString("I can't say that!\n") 
     os.Exit(1) 
    } 
} 

的src/REG/reg.go:

package reg 

var registry = make(map[string]func() string) 

func Register(name string, f func() string) { 
    registry[name] = f 
} 

func GetFunc(name string) (func() string, bool) { 
    f, ok := registry[name] 
    return f, ok 
} 

的src /高/ hi.go:

package hi 

import (
    "reg" 
} 

func init() { 
    reg.Register("hi", func() string { 
     return "Hello there!" 
    }) 
} 

當編碼這個,我天真地認爲,可能編譯到二進制文件中的程序包「hi」會被編譯器找到。然後,在加載時,init()函數將運行。如果是這樣的事情是如何工作的,我已經能夠在東西砸像下面添加一個新的「說不」的命令:

的src /沒有/ no.go:

package no 

import (
    "reg" 
) 

func init() { 
    reg.Register("no", func() string { 
     return "Not a chance, bub." 
    }) 
} 

但,它似乎並沒有這樣工作。

我可能只是通過一個Pythonic鏡頭來思考這個問題太多了,但是有什麼辦法可以完成某些事情嗎?如果沒有,我會改變我的方針,並且我會學到一些關於Go方式的新東西。

在此先感謝!

回答

3

因爲你必須按順序使用import編譯器增加一個包,我的建議是要做到以下幾點:

無需使用多種投遞,你只能有一個單一的包多重下載檔案。每個命令文件都放在同一個包文件夾(cmds)中。這是可能的,因爲您可以在一個包中包含多個init,無論您添加了多少新的插入文件,您都不必對say.go進行任何編輯。

package main 

import (
    "os" 
    "reg" 
    _ "cmds" 
) 
.... 

和以前不包

// Command no 
package cmds 

import (
    "reg" 
) 

func init() { 
    reg.Register("no", func() string { 
     return "Not a chance, bub." 
    }) 
} 
+0

太棒了。這正是我所期待的。事後看來,我應該自己想到這個。但請注意一點。我認爲你仍然需要在「cmds」導入之前加下劃線,否則你會得到一個導入的和未使用的錯誤。即進口(_「cmds」)。 – AntiMS

+0

很高興我能幫到你。你說得對。我編輯了答案並添加了下劃線。 – ANisus

2

根據我讀到的有關init function的內容,如果您只是在say.go中將「hi」和「no」添加到要導入的包列表中,我認爲您的示例可行。如果你這樣做,它會起作用嗎?

我知道你不想更改say.go中的代碼,所以我想這不是一個真正的解決方案。

+0

沒想好。如果沒有辦法讓它在沒有修改say.go的情況下工作,那將是一個合理的妥協......如果它工作的話。不幸的是它不起作用。如果我只是在say.go的輸入中添加「hi」和「no」,它會給我一個「導入但未使用」的錯誤,因爲我從來沒有在任何其他代碼中引用「hi」或「no」 。走。 – AntiMS

+3

@ user1483512:因爲你必須「導入_」任何「'來獲得使用它導入''無論什麼」'w/o的副作用。 – zzzz

+0

哇哇!我錯過了文檔中的某處。到目前爲止,這個答案正式成爲我個人案例的最佳建議。感謝你們倆。 :) – AntiMS