<p>Recently i ran into trouble where i was importing a library of mine (we'll call it
LibA), and i couldn't create a new instance of LibA.Service inside LibB.</p>
<p>The reason was the LibA.Service was using a logging interface from a 3rd party
library, and that logging interface returned itself. This is fine in it's own, but
it apparently breaks when LibA is not <em>just</em> a lib, but also has a <code>LibA/cmd/bin</code>
package. When i imported LibA.Service, it used the vendored Logger (vendored
because of LibA/cmd/bin), and my other library (LibB) was not using the
same type. LibB was using <code>github.com/foo/log.Logger</code> where as LibA required
<code>LibA/vendor/github.com/foo/log.Logger</code>.</p>
<p>So, because of vendoring and the lovely state of golang imports, it appears that
if you want a project to have both a library and a binary, the binary should be
moved outside of the core project or you risk running into importing issues caused
by vendoring.</p>
<p>Am i wrong? Is there another way around this? Type aliasing <em>might</em> help,
but in this case i have no idea. Golang package management is really frustrating.</p>
<hr/>**评论:**<br/><br/>disq: <pre><p>You could make a tiny/local Logger interface (one without any custom types in it) and use that in signatures.</p></pre>tscs37: <pre><p>I think it might be better if libraries would not expose interfaces to anything
they have vendor'ed.</p>
<p>If this is needed, the library should expose it using an interface that is either in the Stdlib or is defined in the library.</p>
<p>(Or alternatively type aliasing)</p>
<p>I think instead of removing the /cmd/ folder, I'd rather establish best practise that a library should not expose foreign interfaces outside the stdlib.</p></pre>throwlikepollock: <pre><p>Not sure this is always possible though, is it? Eg, log15.Logger has a New method that returns the logger. This is a common pattern for loggers, but it is impossible with what you outline, no?</p></pre>tscs37: <pre><p>You can simply define an interface for all relevant methods the logger exposes and expose the internal logger only through that.</p>
<p>If you use that throughout the package it has the advantage of the user being able to switch out the logger if necessary.</p>
<p>I'd also avoid exposing a logger to the outside from a library. Logging should normally be self-contained or generalized through interfaces.</p></pre>pinpinbo: <pre><p>In this situation, LibA import be: <code>github.com/foo/log.Logger</code> as well, no?</p>
<p>I think something is missing here, if this were true, then a lot of packages that imported logging library such as <code>Logrus</code> wouldn't work when imported.</p></pre>LnM7eG5bhl65: <pre><p>I think you are right. Libraries probably shouldn't vendor their dependencies, and it seems to follow that repos that combine a library + application probably shouldn't either.</p>
<p><a href="https://groups.google.com/forum/#!msg/golang-dev/WebP4dLV1b0/Lhk4hpwJEgAJ" rel="nofollow">https://groups.google.com/forum/#!msg/golang-dev/WebP4dLV1b0/Lhk4hpwJEgAJ</a></p>
<p><a href="https://groups.google.com/forum/#!topic/golang-nuts/liKQ6gtU4hk" rel="nofollow">https://groups.google.com/forum/#!topic/golang-nuts/liKQ6gtU4hk</a></p>
<p><a href="https://groups.google.com/d/msg/golang-nuts/AnMr9NL6dtc/UnyUUKcMCAAJ" rel="nofollow">https://groups.google.com/d/msg/golang-nuts/AnMr9NL6dtc/UnyUUKcMCAAJ</a></p>
<p><a href="https://groups.google.com/forum/#!topic/golang-dev/4FfTBfN2YaI" rel="nofollow">https://groups.google.com/forum/#!topic/golang-dev/4FfTBfN2YaI</a></p>
<p><a href="https://peter.bourgon.org/go-best-practices-2016/#dependency-management" rel="nofollow">https://peter.bourgon.org/go-best-practices-2016/#dependency-management</a></p></pre>giftideasplease9241: <pre><p>Yea it sucks, i don't actually <em>want</em> to vendor for my library, but my library also provides a binary. So i have a vendor in the package too, and thus, i introduce this problem.</p></pre>LnM7eG5bhl65: <pre><p>This may not work for your situation, but what about:</p>
<ol>
<li>Don't vendor github.com/foo/log in LibA or LibB</li>
<li>Instead, vendor the logger at LibA/cmd/bin/vendor/github.com/foo/log</li>
</ol>
<p>Users of LibA and LibB will need to deal with vendoring the logger on their own. Also, it's a little gross if LibA and LibB provide multiple binaries.</p></pre>giftideasplease9241: <pre><p>Oh interesting, i didn't know you could vendor in a subpath of a binary. This may be the proper solution!!</p>
<p>Is this idiomatic? I only ask because i've never heard of this. I'll definitely give it a go!</p></pre>LnM7eG5bhl65: <pre><p><a href="https://blog.gopheracademy.com/advent-2016/saga-go-dependency-management/" rel="nofollow">https://blog.gopheracademy.com/advent-2016/saga-go-dependency-management/</a></p>
<p>If the package management committee is successful, there will be a tool that will help ease the pains of vendoring. For example, the tool should be able to strip/hoist the vendored dependencies of LibA.</p>
<p>In the mean time, do what you have to.</p></pre>peterbourgon: <pre><p>No, you shouldn't put a vendor folder anywhere other than the root of a repo.</p></pre>thesilentwitness: <pre><p>One of the shitty things about the current state of Go :(</p></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传