dongwo5110
dongwo5110
2017-04-19 14:26

何时真正需要将Go源代码放在$ GOPATH / src中?

已采纳

Take a look at this shell session, where I build a simple hello world program in Go.

$ cd ~/lab/hello/
$ ls
hello.go
$ cat hello.go 
package main

import "fmt"

func main() {
    fmt.Printf("hello, world
")
}
$ go build
$ ./hello 
hello, world
$ go env
GOARCH="amd64"
GOBIN=""
GOCHAR="6"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH=""
GORACE=""
GOROOT="/usr/lib/go"
GOTOOLDIR="/usr/lib/go/pkg/tool/linux_amd64"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0"
CXX="g++"
CGO_ENABLED="1"
$ lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description:    Debian GNU/Linux 8.7 (jessie)
Release:    8.7
Codename:   jessie

Here is what I don't understand. The tutorial at https://golang.org/doc/install#testing says that I should place my hello.go file at ~/go/src/hello. But I am not following this. How is my program compiling then? If my program is compiling fine in this manner, why does the documentation say that I should keep my source code at ~/go/src or $GOPATH/src when it does not seem to matter?

Is there a scenario where it is really necessary to place the source code at $GOPATH/src?

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

3条回答

  • dongpo5264 dongpo5264 4年前

    The standard Go tools look in the $GOPATH subdirectories src, pkg, and bin. For example,

    currency.go:

    package main
    
    import (
        "fmt"
        "time"
    
        "golang.org/x/text/currency"
    )
    
    func main() {
        t1799, _ := time.Parse("2006-01-02", "1799-01-01")
        for it := currency.Query(currency.Date(t1799)); it.Next(); {
            from := ""
            if t, ok := it.From(); ok {
                from = t.Format("2006-01-01")
            }
            fmt.Printf("%v is used in %v since: %v
    ", it.Unit(), it.Region(), from)
        }
    }
    

    Output:

    $ go build currency.go
    currency.go:7:2: cannot find package "golang.org/x/text/currency" in any of:
        /home/peter/go/src/golang.org/x/text/currency (from $GOROOT)
        /home/peter/gopath/src/golang.org/x/text/currency (from $GOPATH)
    $ 
    

    If we put the missing package in $GOPATH/src, the standard Go tools will find it.

    $ go get golang.org/x/text/currency
    $ go build currency.go
    $ ./currency
    GBP is used in GB since: 1694-07-07
    GIP is used in GI since: 1713-01-01
    USD is used in US since: 1792-01-01
    $ 
    
    点赞 评论 复制链接分享
  • dphdh395195 dphdh395195 4年前

    You really need to put your code in a GOPATH once you write more than a package main. When you import "github.com/me/myapp/mylib", Go will look under your GOPATH for that. Tools like go test also work in terms of packages under GOPATH, not .go files.

    It also becomes the more practical thing to do as soon as your code is in more than one file. It's like the difference between compiling your C program by directly invoking cc/gcc/etc. and using a tool like make.

    If you're starting out and wondering why people want to break up projects into multiple packages in the first place, reasons include:

    • Projects grow, and by 10K or 100K lines you really need to organize.
    • Projects often turn out to contain reusable tools, and packages let other projects import them separately.
    • Packages let you track and control what code has access to what other code and variables. For instance, private names in one package aren't accessible for other packages, so you know you can mess around with that private stuff without breaking code outside the package, and you know that no code outside is futzing with private fields/variables or calling private code behind your back.
    • Packages minimize namespace collisions, i.e., you can have gzip.Reader and io.Reader. If you choose your names right, packagename.ThingName can make code read naturally.
    • Packages can be recompiled, tested, etc. individually, which keeps your edit/build/test cycle faster.
    • In Go specifically, packages enforce some other things about your code organization, like no cyclic dependencies (if A imports B, B doesn't directly or indirectly import A) and that packages under /foo/internal/ only get used by packages under /foo/. Constraints like these can help keep a big project from ending up like tangled spaghetti.

    There are other benefits but those should help show why it's worth getting in the habit. It's fine to just charge forward writing things in a big package for a little bit and start breaking up files moving some types, functions, etc. out into other packages as needed; the 'natural' boundaries will start to make more sense over time.

    点赞 评论 复制链接分享
  • dongshu7162 dongshu7162 4年前

    As JimB says in his comment, the Go documentation makes this clear; basically, the GOPATH is workspace which allows you to keep all your project files and imports and artifacts in one location.

    For a simple project it's not strictly necessary, but when you begin importing dependencies and want to manage libraries it becomes more helpful.

    点赞 评论 复制链接分享