0x00 前言
我一直对go中的一些概念比较模糊,比如它的GOPATH到底是个什么意思、项目目录是怎么布局的、怎样做的测试。因此这次就先上一个小工程,试试水。
0x01 工程概要
功能
目前有的功能是add和sqrt。
dante@dante-pc:~/workspace/go/calcproj/bin$ ./calc
USAGE: calc command [arguments] ...
The commands are:
add Addition of two values.
sqrt Square root of a non-negative value.
工程目录结构
我一直感觉这种目录结构能很直观地帮助理解。
我把这个calcproj添加到了GOPATH中。
export GOROOT=/opt/go
export GOPATH=/home/dante/workspace/go/calcproj
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin
假设这个工程被分割为两个部分:
- 可执行程序,名为 calc,内部只包含一个calc.go文件;
- 算法库,名为 simplemath,每个 command对应于一个同名的go文件,比如add.go。
下面是项目目录结构(这些目录是自己创建的)。
dante@dante-pc:~/workspace/go$ tree calcproj/
calcproj/
├── bin
│ └── calc
└── src
├── calc
│ └── calc.go
└── simplemath
├── add.go
├── add_test.go
├── sqrt.go
└── sqrt_test.go
0x02 代码
主程序calc.go
package main
import "os"// 用于获得命令行参数os.Args
import "fmt"
import "simplemath"
import "strconv"
var Usage = func() {
fmt.Println("USAGE: calc command [arguments] ...")
fmt.Println("\nThe commands are:\n\tadd\tAddition of two values.\n\tsqrt\tSquare root of a non-negative value.")
}
func main() {
args := os.Args
if args == nil || len(args) < 2 {
Usage()
return
}
fmt.Println(args[1])
switch args[1] {
case "add":
if len(args) != 4 {
fmt.Println("USAGE: calc add <integer1><integer2>")
return
}
v1,err1 := strconv.Atoi(args[2])
v2,err2 := strconv.Atoi(args[3])
if err1 != nil || err2 != nil {
fmt.Println("USAGE: calc add <integer1><integer2>")
return
}
ret := simplemath.Add(v1,v2)
fmt.Println("Result: ",ret)
case "sqrt":
if len(args) != 3 {
fmt.Println("USAGE: calc sqrt <integer>")
return
}
v,err := strconv.Atoi(args[2])
if err != nil {
fmt.Println("USAGE: calc sqrt <integer>")
return
}
ret := simplemath.Sqrt(v)
fmt.Println("Result: ",ret)
default:
Usage()
}
}
算法库程序
add.go
//add.go
package simplemath
import "testing"
func TestAdd1(t *testing.T) {
r := Add(1,2)
if r != 3 {
t.Errorf("Add(1,2) Failed. Got %d,expected 3.",r)
}
}
sqrt.go
//sqrt.go
package simplemath
import "testing"
func TestSqrt1(t *testing.T) {
v := Sqrt(16)
if v != 4 {
t.Errorf("Sqrt(16) Failed. Got %v,expected 4.",v)
}
}
测试
add_test.go
package simplemath
import "testing"
func TestAdd1(t *testing.T) { r := Add(1,2) if r != 3 { t.Errorf("Add(1,r) }
}
sqrt_test.go
package simplemath
import "testing"
func TestSqrt1(t *testing.T) { v := Sqrt(16) if v != 4 { t.Errorf("Sqrt(16) Failed. Got %v,v) }
}
@H_996_301@0x03 运行和测试
运行
进入bin目录,执行下面命令,就可以看到目录中多了一个calc文件。。
go build calc
然后执行这个程序。
dante@dante-pc:~/workspace/go/calcproj/bin$ ./calc add 100 10
add
Result: 110
dante@dante-pc:~/workspace/go/calcproj/bin$ ./calc sqrt 10
sqrt
Result: 3
测试
测试比较简单,在任意目录执行下面命令(我在测试程序中,专门改了一个错的结果,因此会报错)。
dante@dante-pc:~/workspace/go/calcproj/bin$ go test simplemath
--- FAIL: TestSqrt1 (0.00s)
sqrt_test.go:6: Sqrt(16) Failed. Got 4,expected 4.
FAIL
FAIL simplemath 0.001s
@H_837_403@0x04 注意
注意1
记得添加GOPATH,不然执行上面的build命令时会提示错误。如下:
dante@dante-pc:~/workspace/go$ go build calc
can't load package: package calc: cannot find package "calc" in any of: /opt/go/src/calc (from $GOROOT) /home/dante/workspace/go/src/calc (from $GOPATH)
不同版本间的差异
我用的是go1.6.2,参考书的可能比较老,因此代码不能用,问题就出在获取输入参数上。
举个简单例子:
/calc add 100 10
按照参考书上的程序,在判断此处的参数长度是,它用的是if len(args) != 3
,我就必须改成if len(args) != 4
.
这属于语言细节,慢慢体会即可。
0xFF 总结
目前用的还很少,工程也很小,以后慢慢提升把。
2016-4-24 12:38:00 hnds
作者:赵德栋,作者介绍