<p>So in C and C++ you can implement application plugins loading .dll or .so at runtime via dlopen, meaning your plugins and application is sort of decoupled.</p>
<p>Is something like that possible at runtime in go? Preferably plugins being written in go and being able to load them to the same process rather then some multiprocess rpc thing?</p>
<hr/>**评论:**<br/><br/>maruwan: <pre><p>Check out "Go execution modes" in <a href="https://github.com/golang/go/wiki/DesignDocuments">https://github.com/golang/go/wiki/DesignDocuments</a> to see a proposal for them. I'm not aware that they're implemented atm.</p></pre>sjustinas: <pre><p>Build modes have been implemented in 1.5. See the <a href="https://golang.org/cmd/go/#hdr-Description_of_build_modes" rel="nofollow">go tool documentation</a> for more.</p></pre>natefinch: <pre><p>Some build modes have been implemented, notably not buildmode=plugin, unfortunately.</p></pre>jammerlt: <pre><p>Thanks, this is quite useful, though sad that it's not on the roadmap.</p></pre>jbuberel: <pre><p>Take a look at this small set of examples:</p>
<p><a href="https://github.com/jbuberel/buildmodeshared" rel="nofollow">https://github.com/jbuberel/buildmodeshared</a></p>
<p>Go (1.5 or 1.6) does not support dynamically loaded shared libraries. But with -buildmode=shared you can approximate some behaviors.</p></pre>sandokan1572: <pre><p>I thought it was part of 1.5 release, wasn't it?</p></pre>postman_: <pre><p>The parts about runtime plugins are not yet implemented and that's a shame.</p></pre>natefinch: <pre><p>So, the answer is not right now (maybe in the future). However, multiprocess RPC doesn't have to be hard or ugly (and it's not even all that slow):</p>
<p>Plugins in Go are as easy as Pie: <a href="https://npf.io/2015/05/pie/">https://npf.io/2015/05/pie/</a></p></pre>szabba: <pre><p>Notably, Neovim (a Vim fork that aims to modernize the codebase and improve code quality) also does this (not exclusively though; Lua and VimScript support is embedded into the main binary).</p></pre>jammerlt: <pre><p>Well this has the whole separate process rpc problem where I can't guarantee the plugin will exit if the main app crashes, as well as having to write a bunch of boiler plate code doing func Hi(a int) { client.Call("Hi", a) }</p></pre>natefinch: <pre><p>My pie package avoids the non-exiting plugin problem by making the plugin run as a subprocess, with communication over stdin and stdout. Yes, you need to write the wrapper around the API, but that's really minor, and likely something like that would be required in most architectures in a statically typed language.</p></pre>indienick: <pre><p>There is also a Git-like style of plugins. This is how projects like <a href="http://terraform.io" rel="nofollow">Terraform</a> and <a href="http://getgb.io" rel="nofollow">gb</a> work.</p>
<p>Somewhere in your <code>$PATH</code> you have your main binary, let's call it <code>myapp</code>, and then you have more "plugins" as executables, with an agreed-upon nomenclature. For example, when you run</p>
<p><code>go get github.com/constabulary/gb/...</code></p>
<p>you not only get <code>$GOPATH/bin/gb</code>, but there is also <code>$GOPATH/bin/gb-vendor</code>.</p>
<p>A fairly common approach I've seen to how this is implemented (even in languages other than Go), is you check to see if <code>myapp foo</code> is a valid subcommand, and if it isn't, see if <code>myapp-foo</code> exists in your <code>$PATH</code>, and try to execute it with the given arguments.</p>
<p>This also pretty much allows you to write your plugins in any language, all it requires is that the "plugin" is somewhere in your <code>$PATH</code>, and that it's executable.</p>
<p>EDIT: If I completely missed your point, I apologize.</p></pre>natefinch: <pre><p>FWIW, I find this method of "plugin" to be completely useless. you gain exactly zero benefit over the plugin being just a standalone script. It's more discoverable, but that's about it. There's no actual interop with the main logic of the application. If all you need is commands that <em>look like</em> they're part of the main application, then I guess that's ok. But it wouldn't be something I would spend time implementing in one of my projects.</p></pre>kron4eg: <pre><p>Not at runtime, but considering fast build times, one could build "compile time" plugins, and in fact many do so. And not only in Go, most known is nginx.</p></pre>jammerlt: <pre><p>The problem with this is that it doesn't help the ecosystem, where by anyone can just start using anyone's plugin. You'd have to know how to build the project just to be able to use a plugin, which is a high entry bar for a novice.</p></pre>shazow: <pre><p>I briefly worked on a project that builds in the Go runtime into the binary to allow automagic recompiling without being concerned about the build environment:</p>
<p><a href="https://github.com/shazow/go-selfcompile">https://github.com/shazow/go-selfcompile</a></p>
<p>The funding was just to get it to the prototype phase, so it still needs to be developed further to be used in production. :)</p></pre>kron4eg: <pre><p>Yeah, definitely there is a problem, as well as a workarounds like compile/rpc.</p></pre>justinisrael: <pre><p>What if there were some kind of middle ground option between compiling external source into your main app, and running each plugin as a process via pie? What if there were something like a plugin manager which is the only external process that starts and communicates with your main app over RPC. This plugin manager could compile discovered plugins at startup (or be triggered to restart/recompile during runtime). It could then host all the plugins in one external process, and delegate for the main app. And you only have one extra process at this point, which can "dynamically" load plugins.
Any value in this alternative? </p></pre>kron4eg: <pre><p>Although it sounds like fascinating way to spend time on hacking thing like that, I don't think it has real value to its users. I assume I could be wrong.</p>
<p>I think each project should decide on how to proceed. Like nginx decided someday.</p>
<p>It will be nice if Go could obtain dlopen-ish feature in future releases, on the other hand I don't miss dynamic loading very much in my own projects.</p></pre>petulant_snowflake: <pre><p>All compile stuff should be taken care of by Go, if you write your package using 'Go idioms', including those for interfacing with native libs. </p>
<p>Even when using native libraries, or when writing assembly. To interface with native code (ie, C/C++) you need to write swig bindings. To do ASM, you need to write the .S files. These files have the same file naming scheme as the others, so they are included for the right platform. (ie, _unix.S _darwin.S etc.). I'm doing this from memory, so this may not be the right names. Swig is kind of painful for C++ code, but slightly easier for C code.</p>
<p>The point here is that any library can be written to be 'go get'-able and not require separate Makefiles or other parts. Internally, we have a couple of C++ libs that we use in Go code. Those libs are 1) available via internal debian repositories 2) correctly have the entries for pkg-config and 3) are made to be cross platform. We have no problem using 'go get' for the packages that bind to these libs on both OSX + Linux. I'm fairly certain with minimal modification it would be able to compile on Windows as well, but no one on our dev team uses Windows.</p>
<p>I will not lie, the learning curve to get the libs/packages able to be 'go get'-able out of the box is very very high. But, like most things challenging/worthwhile in IT, it's a fun learning curve.</p>
<p>(btw no one on the dev team is on *bsd or any other *nix besides OSX/Linux either, but I'm pretty damn certain it would just 'work' if we tried there)</p></pre>ja_6_u__ar: <pre><p>This is for me the biggest limitation of Go. If I write a commercial software I may want to sell optional plugins without having my client to recompile the entire program obviously. This is pretty much why I'm sticking to C++ and Java right now, until Go actually allows Go lib loading at runtime.</p></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传