<p>Hey guys, I've been using (and loving) Go for a week or two, and one thing is perplexing me:</p>
<p>What's the deal with Gopath? Are you meant to maintain one monolithic Gopath for your entire system, or have a Gopath for each individual project? Because I thought it was the former: I figured the $GOPATH constant aliased to where you wanted to drop your global libraries, and then you would use relative imports for your project-specific files. In other words, $GOPATH would be like using C's</p>
<pre><code>#import <global library>
</code></pre>
<p>While relative imports with java-like directory structure (directory must match package name) would be like C's</p>
<pre><code>#import "local file"
</code></pre>
<p>It all makes a lot of sense and while the forced directory-naming is irritating, it makes sense and is good for organization so I went with it.</p>
<p>But everything and I mean EVERYTHING out there rants and raves about how awful relative imports are! Some even made noise that they're deprecated and only still supported because there are old libraries that haven't been updated yet. They make it sound like $GOROOT is for global and $GOPATH is for projects... but $GOPATH is an environment variable. Switching it every time you want to work on a different project would be so cumbersome that, if that was the only way to import local files, I would personally drive to California and slap Ken Thompson. You would have to switch: putting every package you ever write into the same namespace is insane.</p>
<p>So what's going on here? What's the "proper" way to manage local vs global imports?</p>
<hr/>**评论:**<br/><br/>010a: <pre><p>Go does not have a concept of "local imports" and you'd be going against recommended usage by trying to implement something like that. </p>
<p>I don't set $GOROOT. If you need to set it, it has everything to do with pointing to the <code>go</code> binary, <em>not</em> the binaries or source code of your projects.</p>
<p>The typical way of setting up your $GOPATH is to have a single directory (we'll say <code>$GOPATH=~/go</code>) which stores all of your go related code. </p>
<p>Every import in Go is global. If I start a new project which will have the package <code>github.com/user/project</code>, the source code for this goes in <code>~/go/src/github.com/user/project</code>. I would write <code>package main</code> in all of my .go files inside this directory (unless it is a pure library project, in which case it would have <code>package project</code>).</p>
<p>If my project relies on, say, <a href="https://github.com/labstack/echo" rel="nofollow">Echo</a>, I would write <code>import "github.com/labstack/echo</code> in my go files. <code>go get github.com/labstack/echo</code> would download the source code for Echo to <code>~/go/src/github.com/labstack/echo</code> compile it, and store the <code>.a</code> library for it in <code>~/go/pkg/{arch}/github.com/labstack/echo</code>. This would resemble a typical "global import" from C.</p>
<p>If I want to write my own library package which my project depends on, this might resemble a local import in C, but in Go its just another global import. I can write a new package <code>github.com/user/project/mylib</code>. This would go in folder <code>~/go/src/github.com/user/project/mylib</code>. In C, you would <code>#import "mylib/file.c"</code>. In Go, you just <code>import github.com/user/project/mylib</code>, <em>just like every other package</em>. You can even do that outside of your project. Go has no local imports. </p>
<p>In fact, the logical extension of this is that <strong>Go has no concept of files</strong>. You can organize your source code however you wish inside of a package. You could give each function its own .go file. Go doesn't care. This is very different from C because you import entire packages, not individual files. Quite nice. </p>
<p>And as another point: You don't <em>have</em> to create package names and organize your go code in your $GOPATH. If I have a <code>~/src/main.go</code> and <code>~/src/other.go</code>, I can certainly just run <code>go build main.go other.go</code> and it will compile, even if it imports other global libraries installed on $GOPATH. The only thing the $GOPATH is used for is imports, so you only have to keep your projects on the $GOPATH if you're going to be importing them in other packages. </p></pre>om0tho: <pre><p>Don't mess with $GOROOT, unless you're installing to some non-standard location. In fact, forget about that $GOROOT exists. The vast majority of people probably don't need to mess with that.</p>
<p>The suggested way of doing things is having only 1 $GOPATH. It's what Google does. Otherwise, you'll be going against the grain (have fun with that).</p>
<p>You can install third-party code globally. OR you can vendor it in your project, which basically means you copy the package you want to install in your own project. You can even fork it, if you wish. That'll allow you to use different versions of the package in different projects and also gives you control over updating it.</p>
<p>This will be the "official" way of doing things in August, when 1.5 comes out.</p>
<p><a href="https://groups.google.com/forum/#!topic/golang-dev/nMWoEAG55v8%5B1-25%5D" rel="nofollow">https://groups.google.com/forum/#!topic/golang-dev/nMWoEAG55v8%5B1-25%5D</a></p></pre>dchapes: <pre><blockquote>
<p>putting every package you ever write into the same namespace is insane</p>
</blockquote>
<p>No. <strong>Not</strong> making sure <em>every</em> package you write has a <strong>globally unique import path</strong> is insane because it's the right thing to do and it's also so trivial to do so.</p></pre>GoldDog: <pre><p>You know, GOPATH doesn't have to be a single path... </p></pre>LordButtersI: <pre><p>I know, but unless there's a way to restrict which paths are available for a given project, every project in the list is available to every other: you could never use a generic package name; you'd have to use some kind of hungarian </p>
<pre><code>package projectname_packagename
</code></pre>
<p>abomination. I don't want to do that, and I doubt anyone else does either.</p></pre>natefinch: <pre><p>You need a hierarchy. So for example, on disk:</p>
<pre><code>$GOPATH/src/project1/pkg1
$GOPATH/src/project1/pkg2
$GOPATH/src/project2/pkg1
$GOPATH/src/project2/pkg2
</code></pre>
<p>you would then import those as </p>
<pre><code>import "project1/pkg1"
</code></pre>
<p>or </p>
<pre><code>import "project2/pkg1"
</code></pre>
<p>The import statement directly translates to a path on disk rooted at your $GOPATH/src</p>
<p>If you use an online source control system like github, with a url like <a href="https://github.com/yourname/project1/pkg1" rel="nofollow">https://github.com/yourname/project1/pkg1</a></p>
<p>this would be put on disk by <code>go get</code> at</p>
<pre><code>$GOPATH/src/github.com/yourname/project1/pkg1
</code></pre>
<p>which you would import as</p>
<pre><code>import "github.com/yourname/project1/pkg1
</code></pre></pre>SupersonicSpitfire: <pre><p>One way is to first start developing a project in, say, $GOPATH/src/github.com/username/myproject, where GOPATH might be ~/go. Then first start developing in one relatively large source file. Then refactor it into several source files, based on which types and functions fit where. Then create new packages for where functionality seems to be separate, for instance $GOPATH/src/github.com/username/myfileformat, with "package myfileformat" at the top of every source file. Then import that package in "myproject". It can be useful to have a script for testing and building code if source code in either package you are developing are changing, perhaps using inotifywait. There are also tools that help with building and developing, but the above worked for me. YMMV. </p></pre>bertold: <pre><blockquote>
<p>Are you meant to maintain one monolithic Gopath for your entire system</p>
</blockquote>
<p>Yes.</p>
<blockquote>
<p>or have a Gopath for each individual project?</p>
</blockquote>
<p>Barring some very esoteric exceptions, no.</p>
<blockquote>
<p>What's the "proper" way to manage local vs global imports?</p>
</blockquote>
<p>There is no distinction between "local" or "global" imports.</p></pre>ddoreto: <pre><p>Currently I have one $GOPATH for each project and the entire $GOPATH is commited on git repo. That way I don't depend on a 3rd party lib be always available and if some repo have an update that breaks my app, I can plan the upgrade when I have time. So I know that what's on my repo is tested and working.</p>
<p>Changing the $GOPATH per project is not a pain when you make it automatic. I have a script that changes it for me, open a terminal and my editor on the correct directory.</p></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传