Really wrestling with GOPATH

polaris · · 582 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>I&#39;m trying to figure out Go and while the language itself is very straight-forward, the whole project layout is driving me nuts. Maybe someone has a rational answer for why it is, but I&#39;ve searched in this subreddit and haven&#39;t found one that clicks yet.</p> <p>I just want to build and run a simple Go app, so why am I messing with the GOPATH which doesn&#39;t point to the installed version of Go, but instead a folder that I have code in? And why am I not even setting it to the folder containing my main.go, but instead one directory above it with a ./src folder in it? And why do I then have to run go build from ./src and not my the location of my GOPATH? I feel like I must be missing something? Given the issues wrestling this, I&#39;m scared to do some simple directory layout in my project to group things together in a sane way because of the various ways Go treats folders in your project. Is there a simple answer here that will let me move past fighting the build system so I can write some code?</p> <hr/>**评论:**<br/><br/>MisterMagnifico: <pre><p>No, use the GOPATH it&#39;s ingrained into Go. </p> <p>The point in Go is to have packages. GOPATH is where all Go source code lives. Let&#39;s assume you&#39;ve set the GOPATH env variable to c:\go.</p> <p>Let&#39;s assume you create a package called &#34;helloworld&#34; with main.go. The folder structure would look like:</p> <p>c:\go\src\helloworld\main.go The reason it&#39;s broken down this way is because as you compile different packages they&#39;ll live in: c:\go\pkg...</p> <p>This way Go doesn&#39;t have to recompile parts that are already compiled. So it&#39;s reasonable to say src\ is where .. source is. </p> <p>You&#39;ll start to see things like github.com\username\package... This is so that you can pull code in from remote locations and use it. At first it feels very weird to have a long directly, but in the long run it makes sense. That&#39;s exactly where this code is running from. That way any other person can come by and understand EXACTLY what package you were referring too. We can also setup our own private repositories (see GoGS for example).</p> <p>I hope this helps as little. </p> <p>C:\</p></pre>Vicus_114: <pre><p>But how do you manage multiple projects?</p> <p>Let&#39;s say I develop two completely different programs. Should these share a $GOPATH? I have them in different repositories. At the moment depending on what project I work I would always have to change the $GOPATH.</p></pre>theGeekPirate: <pre><p>Yes, the same $GOPATH is used.</p> <p>One project would be $GOPATH/src/first, and the other would end up being $GOPATH/src/second.</p></pre>fern4lvarez: <pre><p>Exactly, that&#39;s why it&#39;s called <code>GOPATH</code>, not <code>PROJECTPATH</code>, many projects and their dependencies can live there. You can set multiple <code>GOPATH</code>s for multiple projects and change the variable value as you go, but that&#39;s not really recommended.</p></pre>MisterMagnifico: <pre><p>The idea is pretty simple:</p> <p>C:\go\src\helloworld\main.go - this is your actual application C:\go\src\hello\what.go - let&#39;s say this does some task that computes the actual string &#34;hello world&#34; and that &#34;helloworld&#34; needs to reference it (import it). You&#39;d only have to ever import &#34;hello&#34; since everything is under the C:\go (aka GOPATH). </p> <p>Go&#39;s premise is that you make a lot of small packages that do ONE thing. That way the code is easily reusable by other packages.</p> <p>You can make as many packages as you want.</p></pre>confusedlambda: <pre><p>The answer is that it depends.</p> <p>You can have multiple projects in a single GOPATH. Each project will have a main.go in a different package. Often this is the right way to go. All the projects will share the same dependencies, when you upgrade a library each project will be updated. This works well when all the projects are updated and deployed together (like micro services).</p> <p>If you don&#39;t work on and/or deploy the projects at the same time, you might consider multiple GOPATHs. A common example would be a consultant that has multiple clients. You probably wouldn&#39;t mix code for multiple clients in the same GOPATH.</p></pre>Vicus_114: <pre><p>That&#39;s exactly the use-case I&#39;m concerned about. I don&#39;t want to mix up different projects and the dependencies of them.</p></pre>stephens2424: <pre><p>A lot of people I&#39;ve introduced to Go have similar problems getting started, so you&#39;re not alone.</p> <p><a href="https://golang.org/doc/code.html">This</a> is more or less the canonical place where the project layout is described. When you lay out your own code, the hardest requirement Go imposes that I can think of is that a directory and a package are roughly equivalent.</p> <p>GOPATH is a simple solution to the problem: how should the compiler find imported packages (outside of the standard library)? Obviously, if you&#39;re in a directory, and you execute <code>go build</code>, the tool knows you want to build that directory&#39;s package, but it&#39;s not obvious where the tool should find everything else. In C this is managed by the linker knowing some default locations (/usr/include), or by specifying flags. GOPATH reduces that complexity down to one environment variable.</p> <p>The key here: the GOPATH directory should be a &#34;go workspace&#34;. That just means you&#39;ll find three subdirectories: &#34;src&#34;, for source code, &#34;bin&#34;, for compiled binaries, and &#34;pkg&#34;, for intermediate objects cached by the go tool. Under &#34;pkg&#34; and &#34;src&#34;, everything is laid out in nested directories that match the import path, which also matches the repository URL ... which also matches what you pass to &#34;go get&#34; when you want to download a new open source package ... and what you append to <a href="http://godoc.org/">http://godoc.org/</a> when you want to see nice documentation ... etc.</p> <p>I&#39;m not sure how much this helped, but hopefully so! I know I fidgeted with it quite a bit when I first got started. If you just start with a simple setup like:</p> <pre><code>$ mkdir -p $HOME/go/src/github.com/username/repository $ export GOPATH=$HOME/go $ cd $HOME/go/src/github.com/username/repository </code></pre> <p>write code there, run <code>go get</code> for dependencies, and <code>go build</code>, I think you should be good to go.</p></pre>p7r: <pre><p>Everybody I know who fights $GOPATH ends up regretting it and finds their life simpler when they embrace it.</p> <p>I think the problem you might have is the way you have worked in the past in term of laying out projects on disk. I suspect you kind of want to have a layout like this perhaps:</p> <pre><code>|- project_one | |- code | | |- assets | | |- bin | | |- lib | | +- ... | |- documentation | |- proposals | +- budgets +- project_two |- code | |- assets | |- bin | |- lib | +- ... |- documentation |- proposals +- budgets </code></pre> <p>And so you end up going into your project, and everything is there, including a code directory, and you can send the whole lot in one go to a colleague. Even if you are only dealing with code and no supporting directories, you&#39;re thinking &#34;everything is separated by projects&#34;.</p> <p>And you think by putting all your code under one $GOPATH/src directory, somehow it all gets jumbled up. Except it doesn&#39;t.</p> <p>In Go, we say code lives over here and everything else lives over there:</p> <pre><code>|- go | |- bin | | |- project_one[.exe] | | +- project_two[.exe] | |- pkg | | +- ... (dragons be &#39;ere) | +- src | |- project_one | | |- package_one | | |- package_two | | +- package_three | +- project_two | |- package_one | |- package_two | +- package_three |- project_one | |- code -&gt; ~/go/src/project_one | |- documentation | |- proposals | +- budgets +- project_two |- code -&gt; ~/go/src/project_two |- documentation |- proposals +- budgets </code></pre> <p>So you can get the same layout, just use symbolic links. The advantage is you now know which packages are coming from where. Yes, you end up with a github.com folder right next to your projects. Hey, your own project might end up living at <code>$GOPATH/src/github.com/[your GH username]/project</code> and you think it&#39;s weird, but it means you can switch to another package of the same name from another user and you know which one you&#39;re actually bringing to the party.</p> <p>I&#39;ve only been doing Go for a couple of months, but I actually miss $GOPATH when I go to other languages already. It&#39;s worth sticking with.</p></pre>codenamegary: <pre><p>Great explanation, totally just triggered a lightbulb moment for me in understanding how to organize my stuff.</p> <p>Thank you!</p></pre>dewey4iv: <pre><p>Use the GOPATH -- trust me, it will make your life easier. In fact.. I switched everything I do (even if it isn&#39;t a go project) to using the structure. I&#39;m not saying you need to/should do that -- but it&#39;s much easier to embrace the convention than to fight it. </p></pre>Fwippy: <pre><p>It&#39;s good practice to put your package at: <code>$GOPATH/src/URL/TO/YOUR/PROJECT/</code> - for instance, <code>$GOPATH/src/github.com/golang/example/hello</code> (see <a href="https://github.com/golang/example/" rel="nofollow">https://github.com/golang/example/</a> ).</p> <p>When you import that package, whether in your own code or another user, you will refer to it as `import &#34;github.com/golang/example/hello&#34;</p> <p><code>$GOPATH</code> should be set once for your computer; and then you should forget about it, and don&#39;t change it. Some people like to set it to <code>$HOME</code>, I set mine to <code>$HOME/go</code> to keep it a bit more separate. So my projects live at <code>$HOME/go/src/github.com/fwip/PROJECT_NAME/</code>. I can <code>go run main.go</code> from the package directory, no issues.</p> <p>If you want to have multiple packages in the same repository, that&#39;s cool, just put each in their own sub-folder (like in the example above).</p></pre>fern4lvarez: <pre><p>Fwiw, there&#39;s one context where <code>GOPATH</code> it&#39;s not used, and it&#39;s on <code>gb</code>-based projects, where each project live with its dependencies on an isolated place in your file system.</p> <p><a href="http://getgb.io/" rel="nofollow">http://getgb.io/</a></p></pre>YEPHENAS: <pre><p><a href="http://tip.golang.org/doc/code.html#Overview" rel="nofollow">http://tip.golang.org/doc/code.html#Overview</a></p></pre>StonyPriapus: <pre><blockquote> <p>I just want to build and run a simple Go app, so why am I messing with the &gt;GOPATH which doesn&#39;t point to the installed version of Go, but instead a &gt;folder that I have code in?</p> </blockquote> <p>Because the go version you use is determined by the command you run, if you do go run main.go you&#39;re defining the go version in go by using the path.</p> <blockquote> <p>And why am I not even setting it to the folder containing my main.go, but &gt;instead one directory above it with a ./src folder in it? So that It knows where to look for dependencies, this way you can install dependencies without being root.</p> <p>And why do I then have to run go build from ./src and not my the location of &gt;my GOPATH? Because when you do go build or go run you specify a set of files, if you do go build main.go and main.go isn&#39;t there it won&#39;t work. If you do from GOPATH go build src/my/package/path/main.go then it should work</p> <p>I feel like I must be missing something? Given the issues wrestling this, I&#39;m &gt;scared to do some simple directory layout in my project to group things &gt;together in a sane way because of the various ways Go treats folders in &gt;your project. Is there a simple answer here that will let me move past &gt;fighting the build system so I can write some code? Check similar projects.</p> </blockquote></pre>fjantomen: <pre><p>Related question:</p> <p>How do you treat related projects that aren&#39;t golang? Do you put them in the same folder structure under GOPATH? </p> <p>I have this project where I&#39;ve split up the functionality in multiple different services using different languages, and all the code is put nicely together in subfolders under the project folder ...except the Go code that needs to live somewhere else. It&#39;s a bit annoying.</p></pre>slrz: <pre><p>Yes, just put it next to the Go sources. The go tool will simply ignore it.</p></pre>Lukeaf: <pre><p>What about using direnv to manage it on a per-project basis? It has a &#34;layout&#34; for go as well. <a href="https://github.com/direnv/direnv/wiki/golang" rel="nofollow">https://github.com/direnv/direnv/wiki/golang</a></p> <p>I find that between direnv and glide (<a href="https://github.com/Masterminds/glide" rel="nofollow">https://github.com/Masterminds/glide</a>) it is a good way of isolating out your project dependencies and nuances, while still adhering to the GOPATH requirements. That way I can still have multiple projects in my workspace but keep my workspaces isolated.</p> <p>FWIW - Often if you work with clients it is not totally a great idea to have all your projects interconnected as people can come back after some time and you need fixed constraints on the project. Go 1.5 vendoring helps a lot though.</p></pre>natefinch: <pre><p>GOPATH is how the Go tools translate <code>import &#34;foo.bar/myproj/somelib&#34;</code> into a directory on disk that contains code to be compiled. This is how you reference code not in the same directory as the file you&#39;re working on. </p> <p>One of the main motivators of GOPATH is that in the modern world, pretty much all code lives in a source control system somewhere online (either github or bitbucket, or your company&#39;s source control server on the intranet)... and since that&#39;s the way you get the code, why not organize your code around where it lives? It gives every package a globally unique identifier (the URL), and it makes it easy to find any specific piece of code. It&#39;s super handy for knowing where to go to look at the latest state of some third party library you&#39;re using.</p> <p>For very small projects that don&#39;t use anything other than the standard library, yes, it can be annoying. But if you use go for very long, you&#39;ll almost certainly start pulling in third party code, at which point, you need a GOPATH anyway.</p></pre>foxh8er: <pre><p>100% feel you there, but just bite the bullet and create the directory structure. fighting it is more trouble than it is worth. </p></pre>Aoteamerica: <pre><p>Dude bro. I made this thing. You may find it useful (you will need ruby).</p> <p><a href="https://gist.github.com/penguinpowernz/c231ad9c94c7d39e45eb" rel="nofollow">https://gist.github.com/penguinpowernz/c231ad9c94c7d39e45eb</a></p> <p>At least for me jumping around between project folders it is. I just run <code>goset</code> in the directory I want to be my new GOPATH and it sets all that up for me.</p> <p>Also, note that the path to go itself should be in GOROOT. Mine is currently <code>/usr/local/go</code>. Also make sure that You put <code>/usr/local/go/bin</code> into your PATH (set in your <code>$HOME/.bash_profile</code> or whatever).</p></pre>natefinch: <pre><p>no no, don&#39;t fight the gopath. It will just makes your life more difficult.</p></pre>sethammons: <pre><p>Ditto with @natefinch - don&#39;t fight it. I did what you did and had a little utility to set my GOPATH for each project when I cd&#39;d to it. I thought that it was nice and easy. Don&#39;t to that. Set $GOPATH once. I use $HOME/go. All my projects go in $HOME/go/src/github.com/$GITHUB_USER/$PROJECT. I cd to the project and I can just &#34;go run&#34; or &#34;go test&#34;. I can &#34;go get $PACKAGE&#34; from anywhere on my system. It just works. If you have a dependency issue where one project needs a different version of a supporting package, you can use <code>godep restore</code> or (more rightly) use vendoring to lock in the packages you need. One GOPATH also helps some editors like Sublime Text work better for Go code.</p></pre>Aoteamerica: <pre><p>Ahhh true. I do use sublime text. Might take your/natefinch&#39;s advice.</p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

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