2019-09-12

执行go程序和创建包

Go-Learning

Golang的配置和Git的连接

配置过程和遇到的问题写在博客里

编写Go程序

工作空间

工作空间是一个存放管理Go代码的目录,其中包含三个子目录:
src目录包含Go的源文件,每个目录都代表了一个源码包
pkg目录包含包对象,存放编译后的包和依赖包
bin目录包含可执行文件,存放可执行对象
go工具用于构建源码包,并将其生成的二进制文件安装到pkg和bin目录中
src子目录常会包含多种版本控制的代码仓库,如Git或Mercurial,以此来跟踪一个或多个源码包的开发

如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
bin/
streak # 可执行命令
todo # 可执行命令
pkg/
linux_amd64/
code.google.com/p/goauth2/
oauth.a # 包对象
github.com/nf/todo/
task.a # 包对象
src/
code.google.com/p/goauth2/
.hg/ # mercurial 代码库元数据
oauth/
oauth.go # 包源码
oauth_test.go # 测试源码
github.com/nf/
streak/
.git/ # git 代码库元数据
oauth.go # 命令源码
streak.go # 命令源码
todo/
.git/ # git 代码库元数据
task/
task.go # 包源码
todo.go # 命令源码

编写并运行hello.go

  • 要编译并运行简单的程序,首先要选择包路径(我们在这里使用 github.com/user/hello),并在你的工作空间内创建相应的包目录:
1
$ mkdir $GOPATH/src/github.com/user/hello
  • 在该目录中创建名为hello.go的文件,其内容为以下代码:

    1
    2
    3
    4
    5
    6
    7
    package main

    import "fmt"

    func main() {
    fmt.Printf("Hello, world.\n")
    }
  • 用go工具构建并安装此程序

    1
    $ go install github.com/user/hello

注意,你可以在系统的任何地方运行此命令。go 工具会根据 GOPATH 指定的工作空间,在 github.com/user/hello 包内查找源码.
若在从包目录中运行 go install,也可以省略包路径:

1
2
$ cd $GOPATH/src/github.com/user/hello
$ go install
  • 输入完整路径运行
    1
    2
    $ $GOPATH/bin/hello
    Hello, world.

将代码推送到远程仓库

git的配置以及两种连接方式和遇到的问题已经写在博客里了

1
2
3
4
5
6
7
$ cd $GOPATH/src/github.com/user/hello
$ git init
$ git add hello.go
$ git commit -m "initial commit"
$ git remote add origin https://github.com/user-name/repo-name.git
$ git remote -v
$ git push -u origin master

实验结果


这里我第一次push的时候报错了,好像是因为库里本来就有了一个hello.go,但是我去看了并没有,,很迷惑
更改指令为

1
git push -f origin master

强推,即利用强覆盖方式用你本地的代码替代git仓库内的内容
参见【GIT】常用GIT知识点

你的第一个库

编写一个库,并让hello程序来使用它

  • 创建包目录

    1
    mkdir $GOPATH/src/github.com/user/stringutil
  • 在该目录下创建名为reverse.go的文件
    代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // stringutil 包含有用于处理字符串的工具函数。
    package stringutil

    // Reverse 将其实参字符串以符文为单位左右反转。
    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命令来测试该包的编译

    1
    $ go build github.com/user/stringutil

这不会产生输出文件,想要输出的话,必须使用go install命令,它会将包的对象放到工作空间pkg目录中

  • 确认stringutil包构建完毕后,修改原来的hello.go文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    package main

    import (
    "fmt"

    "github.com/user/stringutil"
    )

    func main() {
    fmt.Printf(stringutil.Reverse("!oG ,olleH"))
    }
  • 无论是安装包还是二进制文件,go工具都会安装它所依赖的任何东西,因此当我们通过

    1
    go install github.com/user/hello

来安装hello程序时,stringutil包也会被自动安装

  • 运行结果
  • 做完这些之后,工作空间变为
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    bin/
    hello # 可执行命令
    pkg/
    linux_amd64/ # 这里会反映出你的操作系统和架构
    github.com/user/
    stringutil.a # 包对象
    src/
    github.com/user/
    hello/
    hello.go # 命令源码
    stringutil/
    reverse.go # 包源码

测试

通过创建文件reverse_test.go来为stringutil添加测试,文件同样应该在stringutil目录下
代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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工具可从远程代码库自动获取包
若你在包的导入路径中包含了代码仓库的URL,go get就会自动获取,构建,并安装它

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

若指定的包不在工作空间中,go get就会将它放到GOPATH指定的第一个工作空间内。(若该包已存在,go get就会跳过远程获取,其行为与go install相同)
执行结果:

工作目录:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
bin/
hello # 可执行命令
pkg/
linux_amd64/
code.google.com/p/go.example/
stringutil.a # 包对象
github.com/user/
stringutil.a # 包对象
src/
code.google.com/p/go.example/
hello/
hello.go # 命令源码
stringutil/
reverse.go # 包源码
reverse_test.go # 测试源码
github.com/user/
hello/
hello.go # 命令源码
stringutil/
reverse.go # 包源码
reverse_test.go # 测试源码