本节告诉你如何使用 go 来写一个计算类的库,这个库包含了 2 个函数,一个计算 2 数之和,另一个计算两数之差,并且掌握 go 的项目结构。
在 tutorial 文件夹下面创建一个文件夹 package,还有子文件夹 calc, testcalc,如图 1.
$ mkdir package
$ cd package
$ mkdir calc testcalc
这两个文件非常简单,add.go 里有一个名为 Add 的函数,sub.go 里有一个名为 Sub 的函数。
// add.go
package hello
func Add(a int32, b int32) int32 {
return a + b;
}
// sub.go
package hello
func Sub(a int32, b int32) int32 {
return a - b;
}
// main.go
package main
import (
"fmt"
"gopl/tutorial/package/calc"
)
func main() {
var a int32 = 1
var b int32 = 2
sum := hello.Add(a, b)
diff := hello.Sub(a, b)
fmt.Printf("%d + %d = %d\n", a, b, sum)
fmt.Printf("%d - %d = %d\n", a, b, diff)
}
$ go run main.go
不出意外,你会出现下面的结果(如果你是从第 1 篇跟着我做的话):
接下来,很重要,为了能让你的程序成功运行,你需要配置一个名为 GOPATH
的环境变量,它的值是 ~/gogo
$ export GOPATH=~/gogo
再执行一次:
好了进入正题,我知道你心里有一万头羊鸵在奔腾:你特么的想说啥啊?好吧我错了,保证没有下次了。
从第 1 篇开始我就让你吭哧吭哧建立了一堆文件夹,你也不知道是干啥的,为啥要这么搞。现在可以来说明一下。
首先 gogo
文件夹,取啥名字无所谓,因为我电脑上已经存在了一个叫 go
的文件夹了,我实在找不到更好的名字,所以就取了个 gogo
这样的名字。未来,我打算把所有 go 的程序都放在这里面。
为了让 go 编译工具能管辖 gogo
文件夹,所以才有了后面添加 export GOPATH=~/gogo
这样的动作。当然了,go 肯定可以管理很多文件夹的,你只要继续往 GOPATH
里追加文件夹路径即可。
所有被添加到 GOPATH
的路径,都可以称之为工作目录。
如果你的 gogo
没有被 go 认同,就会出现图 2 中的结果,找不到包。因为它并不是合法的 go 工作目录。
工作目录就应该有工作目录的样子,它下面必须有三个子目录,分别是 src
, pgk
, bin
,就算我不解释,你也能猜测它们是干啥的。
所有的源代码放在 src
下面。比如在我们这里,src
下面有一个文件夹 gopl
,这个系列的 go 文章产生的源代码都放在这下面(gopl 是那本神书的名字缩写)。如果你有什么想法,也想搞个学习笔记的文件夹,你应该在 src 下面创建一个你的文件夹,比如叫 lihailewodego
什么的(名字有点长,但是它真的可以啊)。
如果你觉得这个工作目录名字不够酷,你甚至可以再添加一个工作目录,比如叫 godafahao
,然后追加到 GOPATH
里,像这样 export GOPATH=~/gogo:~/godafahao
,不要忘记再添加三个子目录啊。
在 main.go 中,引入了 2 个包,一个是 go 自带的,另一个是我们自己编写的。
import (
"fmt"
"gopl/tutorial/package/calc"
)
记住了,gopl/tutorial/package/calc
不是包名,它是包导入路径。一般来说,包名是包导入路径的最后一个目录名。说人话,就是说上面第 2 个包的包名是 calc
.
然鹅,上面说的包名的定义并不是绝对的,所以我前面加了『一般来说』这 4 个字。如果哪个 go 的包名不符合上面的规则,你可以把他打死。(哈哈,你来打我啊)。
gopl/tutorial/package/calc
这个路径真正包名叫 hello
,实际上,它是在 add.go 和 sub.go 第一行定义的(称之为包声明):
package hello
这是个不推荐的做法,你应该写成 package calc
而不是上面那样,这样你在 main.go 中使用这个加减法包时可以使用 calc.Add(...)
而不是 hello.Add(...)
这种反人类的写法了。
除了我们自己编写的包外,还引入了一个 fmt
包,这个包的导入路径是 fmt
,包名也是 fmt
,在 main.go
中,我们使用了这个包的 Printf
函数输出结果到屏幕。
在 go 里,程序都是通过 package
来组织管理的,不同的包提供不同的功能,这有点像其它语言的库的概念。go 语言自身提供了各种各样的包供我们使用,另外,我们也可以使用第三方的包来扩展程序。
main
包是 go 语言里特殊的包,程序的入口就在这里。入口函数名和 C 语言一样,也叫 main.
掌握 go 语言的项目结构。
练习:
gopl/tutorial/package/calc
,但包名却不是 calc
,请你修正过来。