golang学习手册之build子命令(中)
build单个导入路径
单个文件
golang要求源代码文件必须以“.go”作为名字后缀,这样才可以被build等命令行工具识别。
文件名后缀不是“.go”
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18➜ example0 cat ./example0.go
package example0
➜ example0 cat ./example0.txt
package example0
➜ example0 go build -n ./example0.go
# command-line-arguments
mkdir -p $WORK/b001/
cat >$WORK/b001/importcfg << 'EOF' # internal
import config
EOF
cd /home/Admin/projects/examples/example0
/home/Admin/.g/go/pkg/tool/linux_arm64/compile -o $WORK/b001/_pkg_.a -trimpath "$WORK/b001=>" -p command-line-arguments -complete -buildid Vw6mBaJb5SUht4kgt4T9/Vw6mBaJb5SUht4kgt4T9 -goversion go1.18 -c=4 -D _/home/Admin/projects/examples/example0 -importcfg $WORK/b001/importcfg -pack ./example0.go
/home/Admin/.g/go/pkg/tool/linux_arm64/buildid -w $WORK/b001/_pkg_.a # internal
➜ example0 go build -n ./example0.txt
cannot find package "." in:
/home/Admin/projects/examples/example0/example0.txt两份文件内容是一样的,都只有一句package声明;编译go文件是正常的;但是编译txt文件会报错,说明golang的源代码文件名要以“.go”结尾。
文件名后缀是“_test.go”
1
2
3
4➜ example1 cat example1_test.go
package example1
➜ example1 go build -n ./example1_test.go
➜ example1加了-n参数,但是没有任何输出,说明example1_test.go文件被build忽略了;实际上,这类go文件需要go test命令处理。
源代码不属于main包
由前文可知,当源代码不属于main包时,编译后的结果是库文件,但是默认情况下这个库文件不会被保存下来,想要保存要使用-o参数指定保存路径。1
2
3
4
5
6
7
8
9
10
11
12
13➜ example2 cat example2.go
package example2
➜ example2 go build ./example2.go
➜ example2 ls -al
总用量 12
drwxr-xr-x. 2 Admin Admin 4096 6月 24 17:02 .
drwxr-xr-x. 8 Admin Admin 4096 6月 21 09:56 ..
-rw-r--r--. 1 Admin Admin 17 6月 24 17:02 example2.go
➜ example2 go build -o ./example.a ./example2.go
➜ example2 ls
example2.go example.a
➜ example2 file example.a
example.a: current ar archive可以看到,若不使用-o参数,编译后确实没有产生任何新的文件;使用了-o参数指定了保存路径后,出现了新的文件example.a,其类型为archive,是个二进制类型的文件。
需要注意的是,编译库文件的源代码时,-o的参数值只能是文件而不能是目录,否则就会报错:1
2➜ example2 go build -o ./ ./example2.go
go: no main packages to build当试图将编译结果保存到当前目录时,报错了,这个错误暗示只有编译可执行文件的源代码时,才可以为-o参数指定目录。
源代码属于main包
如果声明属于main包,源代码就必须存在一个main函数,否则编译报错。
1
2
3
4
5➜ example3 cat example3.go
package main
➜ example3 go build -o ./example3.go
_/home/Admin/projects/examples/example3
runtime.main_main·f: function main is undeclared in the main package若属于main包且包含main函数,即存在程序执行入口,那么build默认会在当前目录保存编译结果——可执行文件,文件与源代码文件同名(除去后缀),这与编译库文件的源代码有所不同。
1
2
3
4
5
6
7
8➜ example3 cat example3.go
package main
func main() {
}
➜ example3 go build ./example3.go
➜ example3 ls
example3 example3.go当然也可以对这类源代码文件使用-o参数,定制可执行文件的名字。
1
2
3➜ example3 go build -o main ./example3.go
➜ example3 ls
example3 example3.go main不同的是,此时-o参数的值还可以是目录,build会在指定目录下保存可执行文件,名字默认与源代码文件同名。
1
2
3
4➜ example3 mkdir tmp1
➜ example3 go build -o ./tmp1 ./example3.go
➜ example3 ls tmp1
example3
先创建目录tmp1,然后编译的时候将其指定为保存路径,编译完成后在tmp1目录中生成了可执行文件example3。
若目录不存在,还会先创建目录,需要注意指定不存在的目录时,需要在目录名末尾添加“/”,否则会被当做文件。
1
2
3
4
5➜ example3 go build -o ./tmp2/ ./example3.go
➜ example3 ls
example3 example3.go main tmp1 tmp2
➜ example3 ls tmp2
example3tmp2目录本来不存在,编译之后,先创建了tmp2目录,然后在其中生成了对应的可执行文件。
main函数只有在属于main包时才有意义,会被特殊对待;若不属于main包,就是一个普通函数。
1
2
3
4
5
6
7
8➜ example3 cat tmp.go
package example3
func main() {
}
➜ example3 go build ./tmp.go
➜ example3 ls
example3 example3.go main tmp1 tmp2 tmp.go
tmp.go文件声明所在包是example3,虽然含有main函数,但是编译之后并没有生成对应的可执行文件。
单个目录
若导入路径是一个目录,则目录中必须包含golang源代码文件才可以进行编译,否则会报错。
1
2
3
4➜ example4 ls
example4.txt
➜ example4 go build .
package .: no Go files in /home/Admin/projects/examples/example4当前目录仅有一个txt文件,编译当前目录就会报错,说找不到go文件;可想而知,如果目录是空的,也会是同样结果。
build不会递归的去编译目录,也就是仅仅编译导入路径指定的目录,但是不包括其子目录;也可以理解为,build同样会忽略指定目录下类型为目录的文件。
1
2
3
4
5
6
7
8
9
10➜ example4 cat tmp/tmp.go
package main
func main() {
}
➜ example4 go build -o main ./tmp
➜ example4 ls
example4.txt main tmp
➜ example4 go build .
package .: no Go files in /home/Admin/projects/examples/example4直接编译子目录tmp是成功的,在当前目录下生成了可执行文件;但是编译当前目录example4还是一样的报错,这说明指定目录的子目录不会影响该目录的编译结果,亦即目录不会递归编译。
导入路径指定目录下若存在多个go文件,则要求这些文件属于同一个包,否则会报错。
1
2
3
4
5
6
7
8
9
10
11
12➜ example5 cat ./example5.go
package main
func main() {
}
➜ example5 cat ./tmp.go
package tmp
func tmp() {
}
➜ example5 go build .
found packages main (example5.go) and tmp (tmp.go) in /home/Admin/projects/examples/example5两个go文件分别声明了自己的包是main和tmp,那么build它们共同所在的目录,就报错了。
导入路径指定目录下的go文件属于同一个非main包
与编译单个非main包的go文件的表现几乎一样,区别就是指定目录下可能会有多个go文件一起被编译。导入路径指定目录下的go文件都属于main包
与编译单个main包的go文件几乎一样,区别就是指定目录下会有多个go文件一起被编译,可执行文件的名字默认与源代码所在目录同名。1
2
3
4
5
6
7
8
9
10
11
12
13➜ example6 cat main.go
package main
func main() {
}
➜ example6 cat example6.go
package main
func test() {
}
➜ example6 go build .
➜ example6 ls
example6 example6.go main.go