Go的官网文档How to Write Go Code中,已经介绍了Go的项目目录一般包含以下几个:

  • src 包含项目的源代码文件;
  • pkg 包含编译后生成的包/库文件;
  • bin 包含编译后生成的可执行文件。

可以通过下面的例子来说明工程目录的组织管理。(Windows 7 64位,go version go1.3.3 windows/amd64)

1. 创建一个库文件

创建一个库文件a.go并保存在scr目录的一个子目录下面。

package myfunc

import "fmt"

func Afunc(str string) {
fmt.Println("a.go is package mufunc.")
fmt.Println(str)
}

这时候目录结构如下:

<dirtest>
|--<src>
|--<mufunc>
|--a.go

2. 创建main

关于main包的位置,可以参照参考资料2,个人建议放在scr/main下面,毕竟官方推荐包名和文件存放的文件夹名称最好相同(虽然包名和文件夹名可以不相同,也就是说一个文件夹下可以包含多个包的.go文件)。

package main

import "myfunc"

func main() {
myfunc.Afunc("b.go is package main.")
}

这时候目录结构如下:

<dirtest>
|--<src>
|--<mufunc>
|--a.go
|--<main>
|--b.go

3. 使用go build

如果这时候使用go build,你会发现下面的输出:

E:\dirtest>go build src\main\b.go

src\main\b.go:3:8: cannot find package "myfunc" in any of:
C:\Program Files\go\src\pkg\myfunc (from $GOROOT)
D:\GoLang\src\myfunc (from $GOPATH)

从输出中我们可以看到,Go先是从$GOROOT中查找包myfunc,如果没找到就从$GOPATH中查找,结果都没有找到,我们可以使用go env输出Go的环境变量设置:

E:\dirtest>go env

set GOARCH=amd64
set GOBIN=
set GOCHAR=6
set GOEXE=.exe
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOOS=windows
set GOPATH=D:\GoLang
set GORACE=
set GOROOT=C:\Program Files\go
set GOTOOLDIR=C:\Program Files\go\pkg\tool\windows_amd64
set CC=gcc
set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0
set CXX=g++
set CGO_ENABLED=1

显然E:\dirtest这个目录没有加到$GOPATH中,在环境变量中添加该目录:

保存后,重新执行(可能需要重新打开控制台,让环境变量生效)go build,就在当前目录生成了一个可执行文件b.exe

E:\dirtest\src\main>go env
set GOARCH=amd64
set GOBIN=
set GOCHAR=6
set GOEXE=.exe
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOOS=windows
set GOPATH=D:\GoLang;E:\dirtest
set GORACE=
set GOROOT=C:\Program Files\go
set GOTOOLDIR=C:\Program Files\go\pkg\tool\windows_amd64
set CC=gcc
set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0
set CXX=g++
set CGO_ENABLED=1 E:\dirtest>go build src\main\b.go
E:\dirtest>dir E:\dirtest 的目录 2015/01/13 23:11 <DIR> .
2015/01/13 23:11 <DIR> ..
2015/01/13 23:11 1,958,912 b.exe
2015/01/13 22:52 <DIR> src E:\dirtest>b.exe
a.go is package mufunc.
b.go is package main.

虽然成功运行,但是没有按照期待的那样生成在bin目录下面。为了达到这样的效果,你需要go install。注意go install是针对package,而不是针对单个.go文件。

但是如果是当前状态执行go install,虽然可以成功,但你会发现,并没有在项目根目录E:\dirtest中创建bin\main.exe,反而是在D:\GoLang中创建了。

如果对main包执行go install呢?

E:\dirtest\src\main>go install
go install: no install location for E:\dirtest\src\main: hidden by D:\GoLang\src
\main

可以看到,输出提示当前目录被隐藏。显然这个顺序是对应$GOPATH的设置的,把$GOPATH中的路径顺序改一下:

然后在执行go install myfunc,发现成功地在pkg目录下面生成了myfunc.a。同样执行go install main,也成功的在bin目录下生成了main.exe。此时的目录结构如下:

<dirtest>
|--<src>
|--<mufunc>
|--a.go
|--<main>
|--b.go
|--<pkg>
|--<windows_amd64>
|--myfunc.a
|--<bin>
|--main.exe

现在就算是成功完成了一个示例“项目”吧...

4. 常见错误

除了上面的步骤中出现的错误,其实工程目录管理稍有不慎,就会出现其他问题,例如:

1. 一个文件夹下面包含多个不同包的源文件。也就是把a.gob.go都放到myfunc目录下面会是什么情况呢?

这时候的目录结构如下:

<dirtest>
|--<src>
|--<mufunc>
|--a.go
|--b.go

那么执行go installgo build,甚至go run都会是相同的错误:

E:\dirtest\src\myfunc>go install
can't load package: package myfunc: found packages myfunc (a.go) and main (b.go)
in E:\dirtest\src\myfunc E:\dirtest\src\myfunc>go build
can't load package: package myfunc: found packages myfunc (a.go) and main (b.go)
in E:\dirtest\src\myfunc E:\dirtest\src\myfunc>go run b.go
b.go:3:8: found packages myfunc (a.go) and main (b.go) in E:\dirtest\src\myfunc

从参考资料3中可以看到,每个子目录中只能存在一个package,否则编译时会报错,所以一个子目录下面不能包含多个不同包的源文件。

2. 一个项目能包含多个main()吗?

简单测试下,创建一个c.go,并使用myfunc包(没有导入其他包的情况类似):

package main
import "fmt"
import "myfunc" func main() {
fmt.Println("This is single c.go")
myfunc.Afunc("c.go is also package main.")
}

执行相应的命令,结果如下:

E:\dirtest\src\main>go build
# main
.\c.go:4: main redeclared in this block
previous declaration at .\b.go:5 E:\dirtest\src\main>go build c.go
# 成功,当前目录下生成了c.exe E:\dirtest\src\main>go install
# main
.\c.go:4: main redeclared in this block
previous declaration at .\b.go:5 E:\dirtest\src\main>go install c.go
go install: no install location for .go files listed on command line (GOBIN not
set) E:\dirtest\src\main>go run c.go
This is single c.go
a.go is package mufunc.
c.go is also package main.

显然只能是go rungo build c.go可行。如果把c.go移到单独的目录下面呢:

E:\dirtest\src\cmain>dir

 E:\dirtest\src\cmain 的目录

2015/01/14  11:27    <DIR>          .
2015/01/14 11:27 <DIR> ..
2015/01/14 11:24 147 c.go E:\dirtest\src\cmain>go build E:\dirtest\src\cmain>go install

均可以执行成功。go installbin目录下面生成了对应的exe文件。看来还是目录管理的问题。

3. go install: no install location for .go files listed on command line (GOBIN not set)

从上面的示例输出中就能看到,使用go install针对单个文件时,就会出现这个错误。默认情况下如果设置了$GOROOT$GOPATH,就会依次寻找$GOROOT/bin$GOPATH/bin。那么我们如果自定义设置了$GOBIN=E:\dirtest\bin之后会怎样?

E:\dirtest\src\cmain>go env
set GOARCH=amd64
set GOBIN=E:\dirtest\bin
set GOCHAR=6
set GOEXE=.exe
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOOS=windows
set GOPATH=E:\dirtest;D:\GoLang
set GORACE=
set GOROOT=C:\Program Files\go
set GOTOOLDIR=C:\Program Files\go\pkg\tool\windows_amd64
set CC=gcc
set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0
set CXX=g++
set CGO_ENABLED=1 E:\dirtest\src\cmain>go install c.go
# 成功在 E:\dirtest\bin 下面生成 c.exe

虽然成功了,但是go install应该是作用于包级别,而非单个文件。

4. go build、go install 和 go run 的区别

详细的可以查看参考资料4,这里简单说一下:

  • go build 编译包,如果是main包则在当前目录生成可执行文件,其他包不会生成.a文件;
  • go install 编译包,同时复制结果到$GOPATH/bin$GOPATH/pkg等对应目录下;
  • go run gofiles... 编译列出的文件,并生成可执行文件然后执行。注意只能用于main包,否则会出现go run: cannot run non-main package的错误。

此外,go run是不需要设置$GOPATH的,但go buildgo install必须设置。go run常用来测试一些功能,这些代码一般不包含在最终的项目中。

5. 总结

  1. 一定要管理好目录
  2. 多个项目最好都在一个$GOPATH下面,即src/proj1src/proj2,etc
  3. 尽量使用go install,这样能够规范项目整体结构

6. 参考资料

  1. Golang项目目录结构组织
  2. 关于main包放在哪的问题
  3. 关于golang中包(package)的二三事儿
  4. Running multi-file main package

Go项目目录管理的更多相关文章

  1. JavaWeb学习之tomcat安装与运行、tomcat的目录结构、配置tomcat的管理用户、web项目目录、虚拟目录、虚拟主机(1)

    1.tomcat安装与运行双击tomcat目录下的bin/startup.bat,启动之后,输入http://localhost:8080,出现安装成功的提示,表示安装tomcat成功 2.tomca ...

  2. VS20xx下项目开发目录管理方法

    在VS20XX之后项目管理使用解决方案(solution)管理一个大的开发工程中多个项目(Project). 以下目录配置与工程名称无关,适用于一般的工程组织过程. 对于一般的生成可执行程序的工程,使 ...

  3. 转:基于Maven管理的JavaWeb项目目录结构参考

    通常在创建JavaWeb项目时多多少少都会遵循一些既定的比较通用的目录结构,下面分享一张基于Maven管理的JavaWeb项目目录结构参考图: 上图仅是参考,不同项目不同团队都有自己的约定和规范. 个 ...

  4. Linux档案与目录管理

    Linux档案与目录管理1. 目录与路径1.1 相对路径与绝对路径1.2 目录的相关操作: cd, pwd, mkdir, rmdir cd [相对路径或绝对路径]cd ~ [用户]: 切换家目录cd ...

  5. 规范化的软件项目演进管理--从 Github 使用说起

    规范化的软件项目演进管理 从 Github 使用说起 1   前言 首先,本文的层次定位是:很基本很基础的 Github 工具的入门级应用,写给入门级的用户看的. 基本上工作过几年的人,下面描述的这些 ...

  6. MVVM 模式下iOS项目目录结构详细说明

    ➠更多技术干货请戳:听云博客 我们在做项目的时候,会经常用到各种设计模式,最常见的要数 MVC (模型,视图,控制器)了.但是,今天我们要说的是另一种设计模式——MVVM. 所以 MVVM 到底是什么 ...

  7. Linux 档案与目录管理

    『 cd /etc 』这个情况,这也就是所谓的『绝对路径』,他是从根目录连续写上来的一个情况,所以不论你在哪一个路径现执行这一个指令,都会将你移动到该路径下.那如果我是使用『 cd etc 』呢?那表 ...

  8. Coding 初级教程(一)——用GitHub的GUI客户端对Coding的项目进行管理

    一.概述 二.Git基本概念 1.有关存储的四个概念 2.分支(branch) 三.项目管理实战操作 1.安装 GHfW(GitHub for Windows) 2.在Coding上新建一个项目(新建 ...

  9. Jenkins配置基于角色的项目权限管理--转

    本文将介绍如何配置jenkins,使其可以支持基于角色的项目权限管理. 由于jenkins默认的权限管理体系不支持用户组或角色的配置,因此需要安装第三发插件来支持角色的配置,本文将使用Role Str ...

随机推荐

  1. logstash的index值可以为中文

    logstash中的 output中 有index属性,表示在elk中的主键标识. 在实际应用中,index的值不能为大写字母,可以是小写字母.数字.下划线.中文. 这里重点强调index为中文时,注 ...

  2. 转载 筛子算法之golang实现求素数解析

    package main import "fmt" // Send the sequence 2, 3, 4, ... to channel 'ch'. func generate ...

  3. LC 789. Escape The Ghosts

    You are playing a simplified Pacman game. You start at the point (0, 0), and your destination is(tar ...

  4. javascript之Location对象

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. JSTL核心标签库详解

    <c:out>标签 标签用于输出一段文本到浏览器中. 属性名 是否支持EL 属性类型 属 性 描 述 value true Object 指定要输出的内容 escapeXml true B ...

  6. JavaScript中的bind,call和apply函数的用法和区别

    一直没怎么使用过JavaScript中的bind,call和apply, 今天看到一篇比较好的文章,觉得讲的比较透彻,所以记录和总结如下 首先要理解的第一个概念,JavaScript中函数调用的方式, ...

  7. Oracle安装过程中Oracle Database Configuration Assistant失败问题解决

    今天在安装Oracle的过程中出现了oracle Database Configuration Assistant问题,我解决该问题的方法是将我的计算机用户名更改了一下,改成了pc1.之后再在orac ...

  8. 在web项目中获取ApplicationContext上下文的3种主要方式及适用情况

    最近在做web项目,需要写一些工具方法,涉及到通过Java代码来获取spring中配置的bean,并对该bean进行操作的情形.而最关键的一步就是获取ApplicationContext,过程中纠结和 ...

  9. Anaconda环境配置常用命令

    1. 新建一个环境: conda create -n ForPytorch python=3.6 该行命令新建了一个叫做ForPytorch的环境,该环境使用的python是3.6版本.新建一个环境的 ...

  10. 云计算共享组件--时间同步服务NTP(2)

    一.标准时间讲解 地球分为东西十二个区域,共计 24 个时区 格林威治作为全球标准时间即 (GMT 时间 ),东时区以格林威治时区进行加,而西时区则为减. 地球的轨道并非正圆,在加上自转速度逐年递减, ...