Goのpluginパッケージを試してみる

例えば強いこだわりにより、switchを使いたくない時

eg)

func main() {
    if len(os.Args) < 2 {
        fmt.Println(help())
        os.Exit(1)
    }

    switch os.Args[1] {
    case "a":
        a.F()
    case "b":
        b.F()
    }
}

Go1.8で導入されているpluginのパッケージを使えば以下のように書ける。

func main() {
    if len(os.Args) < 2 {
        fmt.Println(help())
        os.Exit(1)
    }

    p, err := plugin.Open(os.Args[1] + ".so")
    if err != nil {
        fmt.Fprintf(os.Stderr, "Unexpected command: %s", err)
        os.Exit(1)
    }

    f, err := p.Lookup("F")
    if err != nil {
        fmt.Fprintf(os.Stderr, "Function F not found: %s", err)
        os.Exit(1)
    }

    f.(func())()
}

トリックはそれぞれのファイルを-buildmode=pluginでビルドすることでライブラリにしておき、さらにpluginパッケージにより動的に読み込んでしまう。

具体的には

1.ソースファイルを-buildmode=pluginオプションでビルド

$ go build -buildmode=plugin a.go
$ go build -buildmode=plugin b.go

2.main.goをビルドしたのち引数付きで実行

$ go build main.go
$ ./main a
This is a function in "a.go"
$ ./main b
This is a function in "b.go"

サンプルコード全体はgistに。

GoでもちょっとしたLL言語っぽいことができるみたい。

Refs