Skip to main content
  1. 经验技巧分享/
  2. 后端编程/

使用go build来编译go程序

··301 字
go howto

这篇文件准备揭开 go build 命令的面纱,帮助你了解如何通过 go build 来得到一个可执行程序。

同时,在上一篇文章中介绍使用 go modules 来管理 go 工程并编写第一个 helloworld 示例程序时,留下了一个悬念,为什么使用 hellohello 来作为程序文件的名称?

还是那个 helloworld #

下面仍然使用上文中的例子 helloworld

~/Projects/go/hello
➜  ls
go.mod        hellohello.go

其中 go.mod 内容如下:

// go.mod
module world

go 1.16

hellohello.go 代码如下:

// hellohello.go
package main

import "fmt"

func main() {
    fmt.Println("hello world 😀😀😀")
}

我们知道,使用 go run hellohello.go 可以编译并运行 hellohello.go 中所定义的逻辑。但是生成的可执行程序在操作系统的临时文件目录下, 如 临时文件目录/go-build2507969658/b001/exe/hellohello,这个可执行程序是用来测试的。

为了在当前目录下生成可执行程序,要使用开发工具链的 go build 工具。

  • go build hellohello.go

在这个 helloworld 示例程序目录下,执行 go build hellohello.go,会生成一个叫 hellohello 的可执行程序。如果你的文件名叫 helloworld,那么生成的可执行程序名称就为 helloworld

  • go build

helloworld 示例程序目录下,执行 go build,会生成一个叫 world 的可执行程序,这个名称是 go.mod 中定义的模块名称。 如果把模块名称定义为 world/youwu.today,那么生成的可执行程序叫 youwu.today

  • 其它的

以上只不过是为了方便的默认规则。当然,你还可以额外指定生成的可执行程序的名称,如使用go build -o 路径来指定路径:

~/Projects/go/hello
➜  go build -o .

~/Projects/go/hello
➜  ls

~/Projects/go/hello
➜  ls
go.mod        hellohello    hellohello.go world

使用 go build -o 名称 来指定生成的程序名:


~/Projects/go/hello
➜  go build -o h

~/Projects/go/hello
➜  ls
go.mod        h             hellohello    hellohello.go world

假设你的工程里面有多个 main 函数,需要生成多个可执行程序,那么使用 go build -o 输出名称 go文件的路径或位置。比如你可能会看到别人开源的 cli 工具,在 cmd 目录下有好多个子程序,使用了非常复杂的构建脚本来生成多个可执行程序,下次就知道了,通过一个 go build 无法完成的,使用 shell 或者 bat 脚本自己写一个执行脚本。

补充知识 #

若你是 go 编程新手,看了本文以及 go modules ,其中的 go rungo build 都没有向你指明要求。没错,就是 main package main function

这个隐含的规则非常关键,因为它会决定是否可以正常编译。

golang 的规定是这样的: 一个 go 程序中,如果定义了 main package main function,那么它会作为整个程序的入口,所有的用户过程都是从这里开始。

执行 go build 或者 go run 命令时,会查找指向目录是不是一个 main package,再查找这个 main package 是否有一个 main 函数。

举两个反例来辅助理解。

  • 修改为非 main package
// hellohello.go
package youwutoday

import "fmt"

func main() {
    fmt.Println("hello world 😀😀😀")
}

使用 go build 或者 go run 得到的结果表示,go build不会生成可执行程序(因为此时不是 main package),而 go run 则提示不是 main package 不能执行。

~/Projects/go/hello
➜  go build

~/Projects/go/hello
➜  ls
go.mod        hellohello.go

~/Projects/go/hello
➜  go run hellohello.go
go run: cannot run non-main package
  • 修改为无 main 函数
// hellohello.go
package main

import "fmt"

func youwutoday() {
    fmt.Println("hello world 😀😀😀")
}

go build 或者 go run 得到的结果来看,没有 main 函数根本无法继续。

➜  go run hellohello.go
# command-line-arguments
runtime.main_main·f: function main is undeclared in the main package

~/Projects/go/hello
➜  go build
# world
runtime.main_main·f: function main is undeclared in the main package