zoukankan      html  css  js  c++  java
  • 如何编写Go代码

    介绍

    本文档演示了在模块内开发一个简单的 Go 包,并介绍了  go tool:这是获取、构建和安装 Go 模块、包和命令的标准方法。

    注意: 本文假定你使用的是Go 1.13或更高版本的Go,并且GO111MODULE环境变量没有设置。如果你要找这个文档的旧版本、前模块的版本,here.。

    代码组织形式
    Go程序被组织成。一个包是同一目录下的源文件的集合,这些源文件被编译在一起。在一个源文件中定义的函数、类型、变量和常量对同一包内的所有其他源文件都是可见的。

    一个存储库包含一个或多个模块。一个模块是由一起发布的相关的Go包组成的集合。一个 Go 仓库通常只包含一个模块,位于仓库的根目录下。

    一个名为go.mod的文件在那里声明了模块路径:模块内所有包的导入路径前缀。该模块包含了包含go.mod文件的目录中的包,以及该目录的子目录,直到下一个包含go.mod文件的子目录(如果有的话)。

    注意,你不需要先把代码发布到远程仓库中,然后才构建它。一个模块可以在本地定义,而不属于一个版本库。然而,像这样组织你的代码是一个好习惯,就像你有一天会发布代码一样。

    每个模块的路径不仅可以作为它的包的导入路径前缀,还可以指示go命令应该在哪里下载它。例如,为了下载golang.org/x/tools模块,go命令将查询https://golang.org/x/tools(这里有更多描述here)。

    导入路径是一个用于导入包的字符串。一个包的导入路径是指它的模块路径和模块内的子目录。例如,模块github.com/google/go-cmp目录中包含了一个包,在cmp/目录下。这个包的导入路径是github.com/google/go-cmp/cmp。标准库中的包没有模块路径前缀。

    你的第一个程序
    要编译和运行一个简单的程序,首先选择一个模块路径(我们将使用 example.com/user/hello),然后创建一个 go.mod 文件并声明它。命令如下

    $ mkdir hello # Alternatively, clone it if it already exists in version control.
    $ cd hello
    $ go mod init example.com/user/hello
    go: creating new go.mod: module example.com/user/hello
    $ cat go.mod
    module example.com/user/hello
    
    go 1.14
    $

    Go源文件中的第一个语句必须是package name。可执行的命令必须始终使用package main

    接下来,在该目录下创建一个名为hello.go的文件,包含以下Go代码。

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

    现在你可以用go工具建立并安装该程序。

    $ go install example.com/user/hello
    $

    这个命令建立hello命令,生成一个可执行的二进制文件。然后,它将这个二进制文件安装到 $HOME/go/bin/hello (或者在 Windows 下,%USERPROFILE%goinhello.exe)。

    安装目录由GOPATH和GOBIN环境变量控制。如果设置了GOBIN,二进制文件就会被安装到这个目录下。如果设置了GOPATH,二进制文件将被安装到GOPATH列表中第一个目录的bin子目录。否则,二进制文件会被安装到默认的GOPATH目录下的bin子目录($HOME/go或%USERPROFILE/go)。

    你可以使用 go env 命令来为未来的 go 命令设置环境变量的默认值。

    $ go env -w GOBIN=/somewhere/else/bin
    $
    要取消之前通过go env -w设置的变量,请使用go env -u。

    $ go env -u GOBIN
    $
    像go install这样的命令适用于包含当前工作目录的模块的上下文。如果工作目录不在 example.com/user/hello 模块中,go 安装可能会失败。

    为了方便起见,go命令接受相对于工作目录的路径,如果没有给出其他路径,则默认为当前工作目录下的包。所以在我们的工作目录下,以下命令都是等价的。

    $ go install example.com/user/hello
    $ go install .
    $ go install

    接下来,让我们来运行程序,确保它能正常运行。为方便起见,我们将把安装目录添加到PATH中,以便于运行二进制文件。

    # Windows users should consult https://github.com/golang/go/wiki/SettingGOPATH
    # for setting %PATH%.
    $ export PATH=$PATH:$(dirname $(go list -f '{{.Target}}' .))
    $ hello
    Hello, world.
    $

    如果你使用的是源码控制系统,现在是初始化仓库,添加文件,并提交第一次修改的好时机。同样,这一步是可选的:如果你不使用源码控制来编写Go代码。

    $ git init
    Initialized empty Git repository in /home/user/hello/.git/
    $ git add go.mod hello.go
    $ git commit -m "initial commit"
    [master (root-commit) 0b4507d] initial commit
     1 file changed, 7 insertion(+)
     create mode 100644 go.mod hello.go
    $

    go命令通过请求相应的HTTPS URL和读取HTML响应中的元数据来定位包含给定模块路径的存储库(参见go help importpath)。许多托管服务已经为包含Go代码的资源库提供了元数据,因此,要让你的模块供他人使用,最简单的方法就是让它的模块路径与资源库的URL匹配。

    从你的模块中导入包
    让我们写一个morestrings包,从hello程序中使用它。首先,为包创建一个目录,命名为$HOME/hello/morestrings,然后在该目录下创建一个名为reverse.go的文件,内容如下。

    // Package morestrings implements additional functions to manipulate UTF-8
    // encoded strings, beyond what is provided in the standard "strings" package.
    package morestrings
    
    // ReverseRunes returns its argument string reversed rune-wise left to right.
    func ReverseRunes(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)
    }

    因为我们的ReverseRunes函数是以大写字母开头的,所以它是exported的,可以在其他import我们morestrings包的包中使用。

    让我们用go build来测试一下这个包的编译。

    $ cd $HOME/hello/morestrings
    $ go build
    $

    这不会产生一个输出文件。相反,它将编译后的包保存在本地构建缓存中。

    在确认了morestrings包的构建后,让我们在hello程序中使用它。为此,修改你原来的 $HOME/hello/hello/hello.go 来使用 morestrings 包。

    package main
    
    import (
        "fmt"
    
        "example.com/user/hello/morestrings"
    )
    
    func main() {
        fmt.Println(morestrings.ReverseRunes("!oG ,olleH"))
    }

    安装hello程序。

    $ go install example.com/user/hello

    运行新版本的程序,你应该会看到一条新的、相反的消息。

    $ hello
    Hello, Go!

    从远程模块导入包

    一个导入路径可以描述如何使用版本控制系统(如Git或Mercurial)获取包的源代码。go工具使用这个属性来自动从远程版本库中获取包。例如,在你的程序中使用github.com/google/go-cmp/cmp。

    package main
    
    import (
        "fmt"
    
        "example.com/user/hello/morestrings"
        "github.com/google/go-cmp/cmp"
    )
    
    func main() {
        fmt.Println(morestrings.ReverseRunes("!oG ,olleH"))
        fmt.Println(cmp.Diff("Hello World", "Hello Go"))
    }

    当你运行go install、go build或go run等命令时,go命令会自动下载远程模块并将其版本记录在你的go.mod文件中。

    $ go install example.com/user/hello
    go: finding module for package github.com/google/go-cmp/cmp
    go: downloading github.com/google/go-cmp v0.4.0
    go: found github.com/google/go-cmp/cmp in github.com/google/go-cmp v0.4.0
    $ hello
    Hello, Go!
      string(
    -     "Hello World",
    +     "Hello Go",
      )
    $ cat go.mod
    module example.com/user/hello
    
    go 1.14
    
    require github.com/google/go-cmp v0.4.0
    $

    模块的依赖关系会自动下载到GOPATH环境变量指示的目录下的pkg/mod子目录。给定版本的模块的下载内容会在所有需要该版本的模块中共享,所以go命令将这些文件和目录标记为只读。要删除所有下载的模块,你可以通过 -modcache 标志来清除。

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

    你通过创建一个以_test.go命名的文件来编写一个测试,该文件包含一个名为TestXXX的函数,签名为func(t *testing.T)。测试框架会运行每个这样的函数;如果函数调用了失败函数,如t.Error或t.Fail,则认为测试失败。

    通过创建文件$HOME/hello/morestrings/reverse_test.go,在morestrings包中添加一个测试,其中包含以下Go代码。

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

    然后用go test运行测试。

    $ go test
    Passed
    OK example.com/user/morestrings 0.165s
    $
    运行 go help test ,查看测试包文档了解更多细节 testing package documentation.
    接下来

    订阅  golang-announce 邮件列表,当 Go 的新稳定版本发布时,你会收到通知。

    请参阅  Effective Go ,了解如何写出清晰、流畅的 Go 代码。

    也可以从入门教程开始:https://tour.golang.org/ 还有中文版 https://tour.go-zh.org/

    访问documentation page,了解有关go语言及其库和工具的深度文章。



  • 相关阅读:
    python限定方法参数类型、返回值类型、变量类型等
    双拼自然码
    关于将汉语拼音字母“ü”改成“v”的设想和建议
    数据库转模型图
    python中的捕获异常、异常跟踪
    内部教师爆料:某些民办学校真正的内幕
    炸薯条
    IntelliJ IDEA添加JavaDOC注释 方法 快捷键
    java获取当前路径的方法
    java获取全部子类或接口的全部实现
  • 原文地址:https://www.cnblogs.com/mignet/p/How_to_Write_Go_Code.html
Copyright © 2011-2022 走看看