<p>So I have a bunch of small projects written in Go, most of which use more or less the same dependencies. Mainly a mysql driver, boltdb and a few packages which I wrote myself. The mysql driver and boltdb are both very stable projects. I don't think there was ever any case where I updated them and my code broke.</p>
<p>I've ended up realizing that in this case, vendoring seems to be giving me more trouble than it solves. I've decided to delete the vendor folder and go back to the simplicity of "go get" for now which seems to be getting the job done just fine.</p>
<p>Has anyone else tried this before? Have you regretted it? Should I go back to vendoring? Thanks.</p>
<hr/>**评论:**<br/><br/>sh41: <pre><blockquote>
<p>I've decided to delete the vendor folder and go back to the simplicity of "go get" for now which seems to be getting the job done just fine.</p>
</blockquote>
<p>I expect this not to be a popular preference, but I've been doing that and really enjoying it. I use latest versions of the vast majority of my dependencies (I update them regularly with <a href="https://github.com/shurcooL/Go-Package-Store#readme">Go Package Store</a>) without vendoring.</p>
<p>However, most of my dependencies are:</p>
<ul>
<li>my own packages or packages I help maintain (have push rights to)</li>
<li>are created by people I trust to maintain them well</li>
<li>are mature and don't change APIs often, and when they do, it's for the better and easy to update</li>
</ul>
<p>In the end, without vendoring, if you pick your dependencies with care, it's very easy to have 95%+ uptime. But if you want 100% uptime, then you have no choice but to vendor.</p>
<p>Vendoring feels like a very expensive solution that makes sense to use when it's unavoidable. In all other cases, it's so much simpler and more lightweight to skip it, since it really only buys you at most 5%~ uptime.</p></pre>bupku5: <pre><p>you have given a perfectly rational explanation of how you develop safely with vendoring. you didn't insult or misquote anyone. yet you are still downvoted in this sub because you are apparently violating some zeitgeist</p>
<p><a href="/r/golang">/r/golang</a> is really becoming terrible</p></pre>tv64738: <pre><p>Downvoted? It's the highest-rated comment..</p></pre>ChristophBerger: <pre><p>There is always someone who downvotes posts or comments for no good reason. As I am writing this, <a href="/u/sh41" rel="nofollow">/u/sh41</a>'s comment has 19 upvotes, and this clearly shows that knee-jerk downvotes are not a typical behavior in <a href="/r/golang" rel="nofollow">/r/golang</a>.</p></pre>ragefacesmirk: <pre><p>It's easier to get up votes for causing a riot... It's not just here</p></pre>bupku5: <pre><p>if you aren't careful, vendoring can be far more misguided than just using <code>go get</code></p>
<p>most people don't bother rationalizing the version they fixate on, for all they know they are fixating on a version the author regretted and changed ten minutes later</p>
<p>you need to have the discipline to regularly check your dependencies for version changes and bugfixes, no different than if you used <code>go get</code>, otherwise you may be just fixating on obsolete garbage</p></pre>adamtanner: <pre><p>Relying on the GOPATH and go get is basically how Go at Google works.</p>
<p>The GOPATH is modeled after the way Google does source control as a massive monorepo. In that world the GOPATH is the root of your repo so everything is checked in and essentially vendored already. </p>
<p>This works really well if you have a bunch of closed source projects that share the same dependencies and you don't mind checking out the entire world or doing fun git tricks to select subtrees.</p>
<p>I've found the most successful cases of this tend to be with multiple teams/projects with shared dependencies like auth, logging, API clients, etc. Version skew sucks, but so does having to "update the whole world", so it's a trade-off. :)</p>
<p>Vendoring on a per project basis tends to work really well for self-contained code bases, like most open source projects whose output are executables, that you intend for others to checkout and build. It is generally not recommended to vendor inside of packages that are intended to be used as libraries by others.</p></pre>kaeshiwaza: <pre><p>Which trouble do you have using dep (specially for small project) ?</p></pre>nesigma: <pre><p>There's no trouble. I just find "go get" more convenient for the case I've described above (small projects with few and stable dependencies).</p></pre>kaeshiwaza: <pre><p>The answer of your question is your first sentence. Why loose the ability to know which revision of your dependencies you used when it's so easy ? It's a kind of thing that it's too late when you find out you needed it...</p></pre>nesigma: <pre><p>As I said, I find it inconvenient for the case I described above. Sure without <code>dep</code> I am going to lose the ability to know which revision of my dependencies I used. But that's the thing. I never had to think about this before. By default with "go get" I have to always be on a working version. There's nothing extra to think about. It either works or it doesn't.</p>
<p>Also with <code>dep</code> or another tool, unless you vendor your dependencies, then people have to do an extra command to build the project. And if the dependencies are vendored then you end up with big vendor folders. For example just the 2 dependencies I described above (mysql + boltdb) make a vendor folder of around 5.5MB. </p>
<p>None of this is especially troublesome but for a small project with few and stable dependencies I find that the simplicity of "go get" goes away with those little problems and extra overhead.</p>
<p>Anyways, based on the current answers it seems that I am not the only one that does this. I hope to see more answers and opinions but the current answers have encouraged me to keep doing it.</p></pre>kemitche: <pre><p>There's a potential middle ground - using dep or glide or similar to write a vendor.json or similar file with the "last known good" dependency version, but not requiring the use of those tools to populate the vendor/ dir after fetching the repo.</p></pre>nesigma: <pre><blockquote>
<p>but not requiring the use of those tools to populate the vendor/ dir after fetching the repo</p>
</blockquote>
<p>How can this be done?</p></pre>kemitche: <pre><p>Basically, <code>go get</code> doesn't know about any of the vendoring helper tools. It only knows that, if a package is in <code>vendor/</code>, to use that instead of <code>$GOPATH/src</code> for that package.</p>
<p>The tools can usually work in one of two ways.</p>
<ol>
<li>You commit the <code>vendor/</code> directory to source control. In this case, the tools just assist with figuring out what packages to get, and getting the right version of them into <code>vendor/</code>. During build time, the tool itself is unnecessary; <code>go get</code> will "just work."</li>
<li>You DON'T commit the <code>vendor/</code> directory. Instead, you just commit the <code>package.json</code> or <code>gopkg.toml</code> or equivalent file; that file just says "we want to build this using the dependencies in this file at the versions listed in the file." In this case, you're instructed <em>NOT</em> to <code>go get</code> the package or command; instead, you fetch the source "normally" (or use <code>go get -d</code> to download, but not build). Then, you run <code>glide</code> or <code>dep</code> or <code>govendor</code> or whatever to locally create (but again, not commit) the <code>vendor/</code> directory, fetching all appropriate packages.</li>
</ol>
<p>My suggestion - and I haven't tried it myself - would be to go with option 2. Don't commit the <code>vendor/</code> directory. Then just tell people that <code>go get</code> <em>should</em> work. What should happen is that <code>go get</code> - ignorant of the <code>gopkg.toml</code> (or whatever file) goes through the normal process of fetching dependencies into <code>$GOPATH/src</code>. Anyone who encounters issues can use <code>glide</code> (or <code>dep</code> or <code>govendor</code>) to try rebuilding with the "last known good" dependencies.</p></pre>ChristophBerger: <pre><p>So basically, what you suggest is always using the latest dependencies via simple <code>go get</code> (i.e., no vendoring of any kind) but at the same time keep track of the last known good version of each dependency, to be able to revert to that version in case building or testing wit the latest version fails.</p>
<p>This is indeed an interesting idea. Do the current dependency tools support this kind of "version bookkeeping without vendoring" out of the box?</p></pre>kemitche: <pre><blockquote>
<p>This is indeed an interesting idea. Do the current dependency tools support this kind of "version bookkeeping without vendoring" out of the box?</p>
</blockquote>
<p>I wrote more about it as a reply to the other comment: <a href="https://www.reddit.com/r/golang/comments/6m7vic/anyone_else_find_vendoring_inconvenient_for_small/dk0kbov/?context=3" rel="nofollow">https://www.reddit.com/r/golang/comments/6m7vic/anyone_else_find_vendoring_inconvenient_for_small/dk0kbov/?context=3</a></p>
<p>I'm only speculating based on how I've seen the tools work. I <em>think</em> they'll all work this way out of the box. Since <code>go get</code> is completely oblivious to the tools, if you don't commit <code>vendor/</code>, just the package manifest, and never run the 3rd party tool, <code>go get</code> should use <code>$GOPATH/src</code> (including fetching any missing dependencies, at their latest commit).</p></pre>ChristophBerger: <pre><blockquote>
<p>and never run the 3rd party tool</p>
</blockquote>
<p>(...except for updating the last known good version after all tests succeed)</p>
<p>That's the step (or rather, non-step) that was missing in my mental model of your approach. Thanks. </p></pre>xchapter7x: <pre><p>I'd suggest taking a look at glide (<a href="https://github.com/Masterminds/glide" rel="nofollow">https://github.com/Masterminds/glide</a>)
You can pin versions, or pull latest. No need to keep a vendor dir committed, just a yaml defining your deps.</p>
<p>There is also the emerging standard (<a href="https://github.com/golang/dep" rel="nofollow">https://github.com/golang/dep</a>) which takes a similar approach</p></pre>nesigma: <pre><p>I am already using <code>dep</code> for some projects. I find "go get" more convenient for the case I've described above (small projects with few and stable dependencies).</p></pre>lobster_johnson: <pre><p>Keep in mind that Glide is horribly, <em>horribly</em> buggy. I've been using it for more than a year, and when it works, it's fine, but mostly it just craps out or does the wrong thing. In fact, the released version (0.12.3) doesn't even work on most of our repos; we have to use the development version, otherwise it randomly fails with inexplicable errors such as "could not detect VCS" or HTTP 404 (on packages that do exist).</p>
<p>These issues have persisted across a number of releases, and even the authors seem to agree about how awful it is. If you look through the Github issues, many of them seem to be waiting for some kind of new "versioning engine" that will clean everything up. But this seems to be a long-running project that isn't ready yet.</p>
<p>I'm really looking forward to replacing it with Dep.</p></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传