如何编写Go代码

栏目: Go · 发布时间: 6年前

内容简介:本文演示了一个简单的Go语言包的开发,以及请注意,这与其他编程环境不同,在这些环境中,每个项目都有一个单独的工作区,工作区与版本控制仓库紧密相关。

简介

本文演示了一个简单的 Go 语言包的开发,以及 go tool 命令的使用,包含:获取、构建、安装Go包和命令的标准方法。

go tool 要求用特别的方式来组织你的Go代码。仔细阅读本文,它解释了启动和运行Go安装的最简单方法。

代码组织

概述

  • 程序员通常会将所有Go代码保存在一个工作区中
  • 工作空间包含许多版本控制的仓库(repo)(例如,由Git管理的)
  • 每个仓库包含一个或多个包
  • 每个包由一个目录中的一个或多个Go源文件组成
  • 包目录的路径确定其导入路径

请注意,这与其他编程环境不同,在这些环境中,每个项目都有一个单独的工作区,工作区与版本控制仓库紧密相关。

工作区

工作空间是一个目录层次结构,其根目录有两个目录:

src
bin

go工具构建二进制文件并将其安装到 bin 目录。

src 子目录通常包含多个版本控制的仓库(例如Git),用于跟踪一个或多个源包的开发。

在实践中,工作区应该是什么样子呢? 下面给出一个例子:

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) ...

上面的这个树型结构展示出一个工作区包含了2个仓库( exampleimage )。 example 仓库包含了2个命令( hellooutyet )和一个库( stringutil )。 image 仓库包含了 bmp 包和 一些其他的包。

通常工作区会包含很多的源仓库(包含需要多和命令)。大多数的Go开发者都会把他们的源代码和依赖存放在一个工作区。

命令和库是从不同类型的源包构建的。我们稍后会讨论这种区别。

GOPATH 环境变量

GOPATH 环境变量用来指定工作区的位置。默认是用户主目录的 go 目录,如在 Linux 和macOS上是 $HOME/go , 在Windows上是 C:\Users\YourName\go

go env GOPATH 命令会打印出当前有效的 GOPATH ; 如果环境变量没有被设置会打印出默认的位置。

为方便起见,将工作空间的 bin 子目录添加到 PATH

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

为简洁起见,本文档其余部分中的脚本使用 $GOPATH 而不是 $(go env GOPATH) 。即

$ export PATH=$PATH:$GOPATH/bin

而如果还没有设置 $GOPATH 就运行写好的脚本,你需要替换为 $HOME/go , 否则需要执行:

$ export GOPATH=$(go env GOPATH)

要学习更多关于gopath环境变量,可以使用查看帮助 go help gopath

要使用自定义的工作区,可以查看 https://golang.org/wiki/SettingGOPATH

导入路径

导入路径(import path)是唯一标识包的字符串。包的导入路径对应于其在工作空间内或远程仓库中的位置(如下所述)。

标准库中的包具有简短的导入路径,例如 fmtnet/http 。对于我们自己开发的包您必须选择一个基本路径,该路径不太可能与将来添加到标准库或其他外部库中发生冲突。

如果将代码保存在某个源仓库中,则应使用该源仓库的根作为基本路径。例如,如果你在 github.com/user 上有一个GitHub帐户,那么这应该是你的基本路径。

请注意,在构建代码之前,无需将代码发布到远程仓库。组织代码只是一个好习惯,好像有一天你会发布它一样。实际上,你可以选择任意路径名称,只要它对标准库和更大的Go生态系统是唯一的。

我们将使用 github.com/user 作为我们的基本路径。在工作区内创建一个目录,用于保存源代码:

$ mkdir -p $GOPATH/src/github.com/user

你的第一个Go程序

要编译和运行一个简单的程序,首先要选择一个包路径(我们会使用 github.com/user/hello ),然后在工作区里创建一个相应的包目录:

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

接下来,在hello目录里创建一个 hello.go 文件,写入以下内容:

package main

import "fmt"

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

现在就可以使用go工具来构建和安装该程序:

go install github.com/user/hello

注意,你可以在系统上的任何地方运行该命令。go工具通过在 GOPATH 指定的工作空间内查找 github.com/user/hello 包来查找源代码。

如果是在这个包目录内运行 go install 也可以忽略包路径:

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

该命令会生成一个 hello 命令,生成一个可执行的二进制文件。同时安装到工作区目录下的 bin 目录,生成的可执行文件是 hello (如果是windows则是 hello.exe)。

在本例子中是 $GOPATH/bin/hello , 也就是 $HOME/go/bin/hello

当有错误发生的时候,go工具仅会打印除错误,所以如果没有任何输出的时候说明已经执行成功。

可以通过全路径来运行:

$ $GOPATH/bin/hello
Hello, world.

如果已经把 $GOPATH/bin 加入到了 PATH , 可以直接输入二进制文件名:

$ hello
Hello, world.

如果你正在使用一个版本控制系统,比如Git,现在是时候来初始化来生成一个仓库(repository),然后添加文件,做第一次提交。

当然这一步是可选的,不一定非要使用版本控制系统来写Go代码

$ cd $GOPATH/src/github.com/user/hello
$ git init
Initialized empty Git repository in /home/user/work/src/github.com/user/hello/.git/
$ git add hello.go
$ git commit -m "initial commit"
[master (root-commit) 0b4507d] initial commit
 1 file changed, 1 insertion(+)
  create mode 100644 hello.go
$ git push origin master

你的第一个库

我们再来写一个库,并在 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

如果已经在 github.com/user/stringutil 目录里,则直接执行:

$ go build

当然该命令不会生成文件,而是把编译好的包放到了本地的构建(build)缓存里。

确实 stringutil 包被编译后, 修改 hello.go :

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

修改后的:

package main

import (
    "fmt"

    "github.com/user/stringutil"
)

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

再次安装

$ go install github.com/user/hello

执行:

$ hello
Hello, Go!

通过上面的一些步骤后,现在我们的结构是这样子的:

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

包名

在Go原文件中第一个使用的语句必须是

package name

其中 name 就是包的默认名称。一个包中的所有文件必须使用相同的包名。

Go的约定是包名称是导入路径的最后一个元素,例如导入的包 crypto/rot13 , 包名就是 rot13

如果是可执行的文件,包名必须使用 main

不强制要求所有的包名都是唯一的,但是要求导入的路径必须是唯一的(全路径文件名)。

更多关于go的命名规范可以查看 Effective Go

测试

Go提供了一个由 go testtesting 包组成的测试框架。

通过创建一个以 _test.go 结尾的文件,里面写有以 TestXXX 开头的函数。测试框架会运行每一个这样的函数,如果函数调用了一个失败的函数,如 t.Errort.Error , 那么测试就算不通过。

通过添加一个测试文件到 stringutil 包中,

$ vim $GOPATH/src/github.com/user/stringutil/reverse_test.go

添加如下代码:

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

如果当前是在 go test github.com/user/stringutil 目录中,则直接执行:

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

更多细节可以运行 go run test 和 查看 测试包文档

远程包

导入路径可以描述如何使用诸如Git之类的版本控制系统来获取包源代码。go工具使用此属性自动从远程仓库获取包。例如,本文档中描述的示例也保存在GitHub github.com/golang/example 上托管的Git仓库中。如果你在包的导入路径中包含仓库URL,那么go将自动获取,构建和安装它:

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

如果指定的包不在工作区, go get 将会通过 GOPATH 把它放到指定的工作区,如果包已经存在, go get 会跳过远程获取,其行为与 go install 相同。

上面 go get 之后的目录结构如下:

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

在GitHub上托管的 hello 命令取决于同一仓库中的 stringutil 包。 hello.go 文件中的导入使用相同的导入路径约定,因此 go get 命令也能够找到并安装依赖包。

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

此约定是使你的Go包可供其他人使用的最简单方法。

Go Wikigodoc.org 提供了外部Go项目的列表。

有关使用go工具使用远程仓库的更多信息, 可以查看 go help importpath

原文地址: https://golang.org/doc/code.html


以上所述就是小编给大家介绍的《如何编写Go代码》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Python Algorithms

Python Algorithms

Magnus Lie Hetland / Apress / 2010-11-24 / USD 49.99

Python Algorithms explains the Python approach to algorithm analysis and design. Written by Magnus Lie Hetland, author of Beginning Python, this book is sharply focused on classical algorithms, but it......一起来看看 《Python Algorithms》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

随机密码生成器
随机密码生成器

多种字符组合密码