[best practices] Should cmd/* be separated from libraries?

blov · · 415 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>Recently i ran into trouble where i was importing a library of mine (we&#39;ll call it LibA), and i couldn&#39;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&#39;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&#39;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&#39;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&#39;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&#39;t work when imported.</p></pre>LnM7eG5bhl65: <pre><p>I think you are right. Libraries probably shouldn&#39;t vendor their dependencies, and it seems to follow that repos that combine a library + application probably shouldn&#39;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&#39;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&#39;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&#39;s a little gross if LibA and LibB provide multiple binaries.</p></pre>giftideasplease9241: <pre><p>Oh interesting, i didn&#39;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&#39;ve never heard of this. I&#39;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&#39;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

415 次点击  
加入收藏 微博
0 回复
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传