Golang之旅2:工程结构

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, 2) failed. Got %d, expected 3.", 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, expected 4.", v)
  }
}

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

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


转载请注明: 转载自赵德栋的 个人主页 CSDN博客

作者:赵德栋,作者介绍

本博客的文章集合:http://zhaodedong.com/category/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值