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

             go是一种静态编译型的语言,它的编译速度非常快。

             go的官方编译器称为gc,包括编译工具5g,6g和8g,连接工具5l,6l和8l。其中的数字表示处理器的架构。我们不必关心如何挑选这些工具,因为go提供了名为”go”的高级构建工具,会帮我们处理编译和链接的事情。”go”构建工具不仅可以构建本地程序和本地包,还可以抓取、构建和安装远端的第三方程序和包。

    1:代码组织

    go开发者通常将所有的go代码放在一个单独的workspace中。一个workspace可以包含多个版本控制库(比如git),每一个库包含若干package,每个package就是包含一个或多个go源码文件的目录;package目录的路径决定他的引用路径;

    workspace下通常有3个子目录:src包含go源码文件;pkg包含package对象;bin包含可执行程序。go编译时,构建src中的go源码,并将编译后的二进制文件安装到pkg和bin中;

     

    下面是一个workspace的例子:

    bin/
        hello                          # command executable
        outyet                         # command executable
    pkg/
        linux_amd64/
            github.com/golang/example/
                stringutil.a           # package object
    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) ...

    上面的workspace中包含两个版本库:example和image。example库包含2个可执行程序:hello和outyet,一个库文件stringutil。image库包含bmp和其他package等。

     

    2:GOPATH环境变量

    环境变量GOPATH指明了workspace的位置。默认情况下,该环境变量的值是home目录下的名为go的子目录,比如Unix下的$HOME/go,Windows下的C:UsersYourNamego。

    通过设置GOPATH来指明workspace的具体位置。注意GOPATH不能设置为和GO的安装目录一样。

    “go env GOPATH”命令可以打印出GOPATH的当前值。

     

    3:引用路径(import path)

    引用路径用于唯一标识一个package。package的引用路径对应该packge相对于workspace中的位置,或者是一个远程库的地址。

    标准库中的package引用路径都是像”fmt”和”net/http”这样的短路径。对于自己定义的package,必须选择一个不会与标准库发生冲突的基路径。

     

    比如,以github.com/user为基路径,需要在workspace中创建对应的目录:

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

     

    go程序或者包的import语句,会首先搜索GOPATH定义的路径,然后在搜索GOROOT所定义的路径(也就是go的安装路径)。

    4:第一个程序

    首先是确定package路径,这里使用的路径是github.com/user/hello,在workspace中创建对应的目录:

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

     

    然后在上面的目录中新建源码文件hello.go,其内容如下:

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

     

    接下来就可以编译、构建并安装该package了:

    go install github.com/user/hello

    上面的命令可以在系统内任意位置执行。go编译器可以通过GOPATH环境变量得到workspace的路径,进而在其中的github.com/user/hello这个package中找到源码。

     

    go install命令构建hello,产生一个可执行文件,并将该文件安装到workspace中的bin目录下。运行该程序如下:

    $GOPATH/bin/hello
    Hello, world.

     

    5:第一个库

    首先是确定package路径,并且在workspace中创建对应的目录:

    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 install命令,才能在pkg目录下生成package对象。

     

    接下来,修改hello.go文件如下:

    package main
    
    import (
        "fmt"
        "github.com/user/stringutil"
    )
    
    func main() {
        fmt.Printf(stringutil.Reverse("!oG ,olleH"))
    }

     

    当go编译安装package或二进制文件时,它也会安装它的依赖。所以,当安装hello时,它所依赖的stringutil也会被自动安装:

    go install github.com/user/hello
    

      

    运行新程序,结果如下:

    hello
    Hello, Go!

     

    现在,workspace的内容如下:

    bin/
        hello                 # command executable
    pkg/
        linux_amd64/          # this will reflect your OS and architecture
            github.com/user/
                stringutil.a  # package object
    src/
        github.com/user/
            hello/
                hello.go      # command source
            stringutil/
                reverse.go    # package source

    go install命令会将stringutil.a文件安装到pkg/linux_amd64目录中,对应于源码的子目录下。因此,后续编译时,编译器可以找到该package文件,避免不必要的重编译。”linux_amd64”主要是用于跨平台编译时,用于标识操作系统和CPU架构。

     

    go可执行程序是静态链接的,运行go程序时,package对象文件不是必须存在的。

     

    6:Package名

    go语言的处理单元是package而非文件,这意味着可以将包拆分成任意数量的文件。

    go源码文件中的第一条声明语句必须是:package name

    其中的name就是package的引用名,同一个package中的源码文件必须使用相同的名字。在go编译器看来,如果这些文件的包声明都是一样的,那么他们属于同一个包,这跟把所有内容放在一个单一的文件里是一样的。

    GO的惯例是package名就是引用路径的最后一个元素,比如引用路径为"crypto/rot13"的package,其名为rot13。

     

    可执行程序必须以main作为package名。

    多个package链接成一个二进制文件时,这些package的名字不一定必须是独一无二的,只要他们的引用路径不同即可。

     

    7:测试

    go具有一个轻量级的测试框架,该测试框架包含go test命令,以及testing package。

    编写测试代码时,源码文件名需要以”_test.go”结尾,函数的形式是:func TestXXX(t *testing.T)。

    测试框架运行每个测试函数,如果函数中调用到了t.Error或t.Fail,表示测试失败。

     

    比如,如果需要测试stringutil这个package,则可以创建文件$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 github.com/user/stringutil
    ok      github.com/user/stringutil 0.165s

    或者,如果当前就在package目录中,可以直接运行go test命令:

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

     

    8:远端package

    package的引用路径还可以用于描述如何从版本控制系统如git或mercurial中获取源码。go编译器可以使用该特性从远端库中获取package。

    比如上面例子中的代码也存在于GIT库:github.com/golang/example中。如果在源码中,引用路径使用的是该URL地址,则可以使用go get命令,该命令会从远端拉取package,并进行编译安装:

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

    如果package不在当前的workspace中,go get将会将其放置到GOPATH指定的workspace下,如果该package已经存在了,则go get会省略远端拉取的过程,剩下的动作与go install一样。

     

    运行完go get命令后,workspace目录层次结构如下:

    bin/
        hello                           # command executable
    pkg/
        linux_amd64/
            github.com/golang/example/
                stringutil.a            # package object
            github.com/user/
                stringutil.a            # package object
    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.com/user/hello/hello.go文件,将

    import "stringutil"

    改为

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

    这样,执行go get github.com/user/hello时,就会首先从远端下载stringutil这个package,然后再编译安装hello。

     

    https://golang.org/doc/code.html

  • 相关阅读:
    delphi string.split 按照任意字符串分割语句
    学习 TTreeView [16]
    学习 TTreeView [15]
    delphi TClientDatset资料
    delphi7 clientdataset 详解
    为TMenuItem增加指针Data属性
    构建一个用于产品介绍的WEB应用
    图片延迟加载技术-Lazyload的应用
    你想不到的压缩方法:将javascript文件压缩成PNG图像存储
    如何更快速加载你的JS页面
  • 原文地址:https://www.cnblogs.com/gqtcgq/p/7522748.html
Copyright © 2011-2022 走看看