开始编写GO

竹天亮 · · 653 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

预览
  • Go程序员通常让所有的Go代码在一个单独的工作空间(workspace).
  • 一个工作空间包含很多版本控制仓库(比如,通过git管理)
  • 每个仓库包含一个或者多个包(packages).
  • 每个包由单独的目录下的Go源文件组成.
  • 包的目录路径决定他的导入路径

注意这是和其他编程环境不同的地方:每个项目都有单独的工作空间,并且工作空间与版本控制仓库紧密绑定

工作空间

工作根目录有两个目录:

  • src包含够源文件
  • bin包含可执行命令

go tool构建并安装binaries到bin目录

src子目录一般包含多个版本控制仓库(比如Git或者Mercurial)追踪一个或多个源包的开发。

下面展示工作空间的结构:

bin/
    hello                          # command executable
    outyet                         # command executable
src/
    github.com/golang/example/
        .git/                      # Git repository metadata
        hello/
            hello.go               # command source
        outyet/
            main.go                # command source
            main_test.go           # test source
        stringutil/
            reverse.go             # package source
            reverse_test.go        # test source
    golang.org/x/image/
        .git/                      # Git repository metadata
        bmp/
            reader.go              # package source
            writer.go              # package source
    ... (many more repositories and packages omitted) ...</pre>

上面的树显示工作空间包含两个仓库(exampleimage)。example仓库包含两个命令(hellooutyet)和一把库(stringutil). image仓库包含bmp包和其他的一些内容

经典的工作空间包含多个源仓库,源仓库包含多个包和命令。大多数的Go程序员将所有的Go源代码和依赖放在一个单独的工作空间。

注意,不应该使用symbolic links关联文件或者目录到工作空间。

GOPATH环境变量

GOPATH环境变量指定工作空间的位置。默认是在home目录里的go目录,比如Unix的$HOME/go,Windows的%USERPROFILE%\go(通常是C:\Users\YourName\go)。

如果想在不同的地方,可以使用set GOPATH指定目录的路径。(另一种通用的设置是GOPATH=$HOME).注意GOPATH一定不能是Go的安装目录。

go env命令打印当前有效的GOPATH,如果没有设置则打印默认的位置。

为了方便,添加工作空间的bin目录到你的路径:

$ export  PATH=$PATH:$(go env GOPATH)/bin

为了简短,接下来的文档使用GOPATH代替``(go env GOPATH)。

导入路径(Import paths)

import path是唯一的字符串表示包。包的导入路径对应工作空间里它的位置或者远程仓库位置。

标准库里的包具有简短的导入路径,比如fmtnet/http。对于你自己的包,指定的路径不能与标准库里的包或者其他内部包冲突。

如果你将代码保存在源文件仓库,那么应该使用源仓库的根目录作为你的基础路径。比如,如果你有Github账号,那么github.com/{user}就是你的基本路径。

注意不要再你能构建之前推送代码到远程仓库。

我们将使用github.com/{user}作为你的基础路径。在工作空间下创建一个目录保存源代码:

$ mkdir -p $GOPATH/src/github.com/user
第一个程序

要编译和运行一个简单的程序,先选择一个包路径(我们先用github.com/user/hello)并且在工作空间创建相应的包目录:

$ mkdir $GOPATH/src/github.com/user/hello

接下来,在这个目录下创建一个名为hello.go的文件,包含如下代码:

package main

import "fmt"

func main() {
    fmt.Println("Hello, world.")
}

现在就可以构建并安装程序了:

$ go install github.com/user/hello

现在你就可以在你的系统里运行这个命令了。go tool通过GOPATH指定的工作空间查找github.com/user/hello包的源代码

如果已经在包目录里,就可以省略掉包路径

$ cd $GOPATH/src/github.com/user/hello
$ go install

这个命令构建hello命令,产生一个可执行的binary。然后安装这个binary到工作空间下的bin目录,也就是$HOME/go/bin/hello

go tool只会在有错误的时候打印输出,所以如果没有内容产生,表示执行成功。

现在可以通过全路径运行程序

$ $GOPATH/bin/hello
Hello, world.
第一个库

现在我们编写一个library并且在hello程序里使用。

同样,第一步先选择一个包路径(我们使用github.com/user/stringutil)先,创建包路径

$ mkdir $GOPATH/src/github.com/user/stringutil

然后创建一个命为reverse.go的文件:

// Package stringutil contains utility functions for working with strings.
package stringutil

// Reverse returns its argument string reversed rune-wise left to right.
func Reverse(s string) string {
    r := []rune(s)
    for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
        r[i], r[j] = r[j], r[i]
    }
    return string(r)
}

现在,使用go build测试包编译:

$ go build github.com/user/stringutil

如果已经在包源目录下,只需要:

go build

这不会产生输出文件。而是将编译完的包保存到本地构建缓存里。

现在修改hello.go来使用它:

package main

import (
      "fmt"
      "github.com/user/stringutil"
)

func main() {
        fmt.Println(stringutil.Reverse("!oG, olleH"))
}

install hello程序

$ go install github.com/user/hello

这一顿操作后,工作空间应该变成了:

bin/
    hello                 # command executable
src/
    github.com/user/
        hello/
            hello.go      # command source
        stringutil/
            reverse.go    # package source
Package names

Go源文件里的第一行一定是:

package name

其中name是包的默认名称。
(包中的所有文件必须使用相同的名称。)
Go的约定是报名是导入路径最后一个节点:crypto/rot13的包名是rot13

可执行命令的包名必须是package main

不要求包名称在链接到单个二进制文件的所有包中都是唯一的,只要导入路径(它们的完整文件名)是唯一的。

测试

Go有一个由go test命令和测试包组成的轻量级测试框架。

创建一个用_test.go结尾的文件,里面的方法命名为TestXXX。测试框架会运行每个方法;如果方法调用失败方法比如t.Error或者t.Fail,测试就被认为失败了。

创建一个$GOPATH/src/github.com/user/stringutil/reverse_test.go文件测试stringutil

package stringutil

import "testing"

func TestReverse(t *testing.T) {
    cases := []struct {
        in, want string
    }{
        {"Hello, world", "dlrow ,olleH"},
        {"Hello, 世界", "界世 ,olleH"},
        {"", ""},
    }
    for _, c := range cases {
        got := Reverse(c.in)
        if got != c.want {
            t.Errorf("Reverse(%q) == %q, want %q", c.in, got, c.want)
        }
    }
}

然后执行go test

$ go test github.com/user/stringutil
ok      github.com/user/stringutil  0.165s
远程包

导入路径可以描述如何使用诸如Git或Mercurial之类的修订控制系统来获取包源代码。go tool使用该属性自动从远程仓库拉去包。比如,本文档里的实例就保存在github.com/golang/example。如果你在包的导入路径引入远程URL, go get将会自动获取,构建并且安装它:

$ go get github.com/golang/example/hello
$ $GOPATH/bin/hello
Hello, Go examples!

如果工作空间不存在指定的包,go get会将它放在GOPATH指定的第一个工作空间内。(如果包存在,go get会跳过远程获取,就和go install的行为一样了)

经过上面的操作后,工作目录结构将会变为:

bin/
    hello                           # command executable
src/
    github.com/golang/example
      .git/                       # Git repository metadata
        hello/
            hello.go                # command source
        stringutil/
            reverse.go              # package source
            reverse_test.go         # test source
    github.com/user/
        hello/
            hello.go                # command source
        stringutil/
            reverse.go              # package source
            reverse_test.go         # test source

Gihub上托管的hello命令依赖同一仓库下的stringutil包。hello.go文件里的imports使用相同的导入路径规范,所以go get命令可以定位并且安装起来的包:

import "github.com/golang/exmaple/stringutil"

规范是最简单的方式让你的Go包可以对其他的可用


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:竹天亮

查看原文:开始编写GO

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

653 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传