Go中目录结构GOPATH的做用

在学习go语言的过程中, 你也许问过本身一个问题, GOPATH究竟是作什么的? 或许在写过一些代码以后, 很快你就会在网上找到一些资料, 它告诉咱们GOPATH这个环境变量它指定了一个目录, 这个目录包含了咱们全部的源码, 好比这里的介绍, 可是我以为光是理解这一点是不够的, 由于你会发现让人为难的是, 看起来彷佛咱们每新建一个项目, 都要往GOPATH再补充一条路径, 这实在是反人类的作法啊.html

我本身曾经也有过那样的顾虑, 为了巩固本身的理解, 同时也为了让其余读者更清楚GOPATH的做用, 我但愿这篇小文但愿可以起到必定的做用.git

基本探索

让咱们先从目录结构开始提及, 在写registry-watch这个项目的时候, 编辑器常常提示我结构不正确, 因而在网上搜了搜, 找到了这个.github

按照文档的说法, 做为一个workspace, 它须要包含三个目录:golang

workspace
  |-- src
  |-- pkg
  |-- bin

src表示咱们的源码目录, 在不考虑另外两个目录的状况下, 假设我写了一个demo项目, 并新建了一个hello.go, 它是main模块, 同时它依赖于另一个函数, 该函数位于library/world.go:json

hello.goapi

package main

import "fmt"
import "demo/library"

func main() {
    fmt.Println("Hello, " + library.World())
}

world.go编辑器

package library

// World return "World"
func World() string {
    return "World"
}

因而目录结构变成了如今这个样子:函数

workspace
  |-- src
  |     |-- demo
  |     |     |-- hello.go
  |     |     |-- library
  |     |     |     |-- world.go
  |-- pkg
  |-- bin

如今我cd src目录并运行go install demo后, 咱们发现如下变化:工具

workspace
  |-- src
  |     |-- demo
  |     |     |-- hello.go
  |     |     |-- library
  |     |     |     |-- world.go
  |-- pkg
  |     |-- darwin_amd64
  |     |     |-- demo
  |     |     |     |-- library.a
  |-- bin
  |     |-- demo

这个例子基本说明了问题, 当咱们写的模块是main时, 它会对应到一个可执行文件, 而且编译后的文件会被复制到bin目录, 若是是其余模块, 它会被编译成一个库文件, 而且被复制到pkg目录. 这就是咱们必须提供三个目录的缘由, 一个放源代码, 一个放编译后的可执行文件, 另一个放编译后的库文件.学习

协做

一个项目老是会由多个成员进行协做开发, 在观察咱们的项目结构以后, 很天然的, 咱们会发现应该被提交的代码只有hello.golibrary/world.go, 也就是说咱们的.git目录应该位于src/demo之下.

workspace
  |-- src
  |     |-- demo
  |     |     |-- .git
  |     |     |-- hello.go
  |     |     |-- library
  |     |     |     |-- world.go
  |-- pkg
  |-- bin

再考虑另一个问题, 咱们常常会运行go get xxx去安装一些包, 这些包会被下载到$GOPATH/src目录下, 当另一个团队成员拉下咱们的代码时, 若是还须要逐个去运行go get xxx那就太不方便了, 因而咱们须要借助一个依赖管理的工具, 这就是godep. 当咱们运行过go get xxxx安装过依赖以后, 只要再到项目目录下, 运行godep save, 便会将全部的依赖记录在一个文件当中, 而且这个时候咱们的目录结构再次发生了一些小小的变化.

workspace
  |-- src
  |     |-- demo
  |     |     |-- .git
  |     |     |-- Godeps
  |     |     |     |-- _workspace
  |     |     |     |-- Godeps.json
  |     |     |-- hello.go
  |     |     |-- library
  |     |     |     |-- world.go
  |-- pkg
  |-- bin

如今来到须要拉代码的这一方, 对于像上面这样一个仓库. 咱们须要多考虑一些事情. 咱们不如以kubernetes为例来作示例:

cd workspace/src
git clone https://github.com/kubernetes/kubernetes.git k8s.io/kubernetes
godep restore

初看可能会奇怪, 为何须要指定目的目录呢, 尤为是k8s.io看起来好生奇怪, 其实只要大概找一个源码文件看看就知道了, 好比这个文件

pkg/api/context.go

package api

import (
    stderrs "errors"
    "time"

    "golang.org/x/net/context"
    "k8s.io/kubernetes/pkg/auth/user"
)

咱们知道import路径都是针对$GOPATH/src的, 因此很天然的咱们要有k8s.io这个目录.

总结

这个时候, 咱们回到一开始提到的顾虑, 咱们真的须要对每个项目都添加一条GOPATH路径吗? 否则, 咱们所说的项目不过是以一个文件夹的形式存在于$GOPATH/src中, 咱们只须要配置一个GOPATH, 并把项目都建在src目录下就能够了.

参考博客:https://github.com/zhouhaibing089/Blog/issues/5