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:\Users\YourName\go。

通过设置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.\n")
}

接下来就可以编译、构建并安装该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

如何编写go代码的更多相关文章

  1. [转]通过Visual Studio为Linux编写C++代码

    Build 2016大会上Microsoft首次公布的Visual Studio 2015扩展提供了在VS2015中编写C++代码,随后通过Linux/UNIX计算机进行编译和执行的能力.这种想法非常 ...

  2. 基于CkEditor实现.net在线开发之路(2)编写C#代码,怎么调用它。

    上一章简约的介绍了CkEditor编辑器,可以编辑js逻辑代码,css,html,C#代码,这章我根据实际例子,讲解怎么编写C#代码和怎么调用它. 大家都还记得刚刚接触程序编时的hello Word吧 ...

  3. 解决VS2012编写JQuery代码不能智能提示的问题(其他js库的代码提示设置估计类似)

    VS默认设置下编写jQuery代码是这样的: 解决办法: 1.在项目的"管理NuGet程序包"中安装JQuery: 2.打开:工具 -> 选项 -> 文本编辑器 -&g ...

  4. JNI技术基础(2)——从零开始编写JNI代码

    书接上文: <JNI技术基础(1)——从零开始编写JNI代码> 2.编译源程序HelloWorld.java并生成HelloWorld.class 3.生成头文件HelloWorld.h ...

  5. 最新的JavaScript核心语言标准——ES6,彻底改变你编写JS代码的方式!【转载+整理】

    原文地址 本文内容 ECMAScript 发生了什么变化? 新标准 版本号6 兑现承诺 迭代器和for-of循环 生成器 Generators 模板字符串 不定参数和默认参数 解构 Destructu ...

  6. AppleWatch开发教程之Watch应用对象新增内容介绍以及编写运行代码

    AppleWatch开发教程之Watch应用对象新增内容介绍以及编写运行代码 添加Watch应用对象时新增内容介绍 Watch应用对象添加到创建的项目中后,会包含两个部分:Watch App 和 Wa ...

  7. mvn编写主代码与测试代码

    maven编写主代码与测试代码 3.2 编写主代码 项目主代码和测试代码不同,项目的主代码会被打包到最终的构件中(比如jar),而测试代码只在运行测试时用到,不会被打包.默认情况下,Maven假设项目 ...

  8. [JS进阶] 编写可维护性代码 (1)

    今天的web应用大至成千上万行的javascript代码,执行各种复杂的过程,这种演化让我们开发者必须得对可维护性有一定的认识!编写可维护性代码很重要,很多情况下我们是以他人的工作成果为基础,确保代码 ...

  9. Java认证:JavaRunnable线程编写接口代码

    Java认证:JavaRunnable线程编写接口代码.JavaRunnable线程如何才能更好的适应目前的编程环境呢?下面我们就看看如何才能更好的进行相关环境.希望下面的文章对大家有所帮助.Java ...

  10. 编写css代码的方式

            css(层叠样式表) 在一个网页中主要负责了页面的数据样式.       编写css代码的方式:       第一种: 在style标签中编写css代码. 只能用于本页面中,复用性不强 ...

随机推荐

  1. FamilyFilter(4)

    3.1. 基于列族过滤数据的FamilyFilter 构造函数: FamilyFilter(CompareFilter.CompareOp familyCompareOp, ByteArrayComp ...

  2. HBase入门实例: Table中Family和Qualifier的关系与区别

    Table中Family和Qualifier的关系与区别 就像用MySQL一样,我们要做的是表设计,MySQL中的表,行,列的在HBase已经有所区别了,在HBase中主要是Table和Family和 ...

  3. 2019-1-29-dotnet-使用-Qpush-快速从电脑到手机推送文字

    title author date CreateTime categories dotnet 使用 Qpush 快速从电脑到手机推送文字 lindexi 2019-01-29 16:22:56 +08 ...

  4. Leetcode551.Student Attendance Record I学生出勤记录1

    给定一个字符串来代表一个学生的出勤纪录,这个纪录仅包含以下三个字符: 'A' : Absent,缺勤 'L' : Late,迟到 'P' : Present,到场 如果一个学生的出勤纪录中不超过一个' ...

  5. Redis源码解析:22sentinel(三)客观下线以及故障转移之选举领导节点

    八:判断实例是否客观下线 当前哨兵一旦监测到某个主节点实例主观下线之后,就会向其他哨兵发送"is-master-down-by-addr"命令,询问其他哨兵是否也认为该主节点主观下 ...

  6. thinkphp用swiftmailer发邮件demo

    QQ邮箱 include_once APPPATH . 'libraries/swiftmailer/swift_required.php'; $transport = Swift_SmtpTrans ...

  7. windows 和 mac 文件夹共享问题汇总

    目标:windows上的文件夹,共享给MAC,mac可以将文件复制到windows上来 windows设置共享文件夹,然后在mac上访问 假设win的ip地址是10.10.27.11,则mac上远程方 ...

  8. memcache缓存使用详解

    初始化一个Memcache的对象:$mem = new Memcache(); 连接到我们的Memcache服务器端,第一个参数是服务器的IP地址,也可以是主机名,第二个参数是Memcache的开放的 ...

  9. CesiumLab地形处理成果在Tomcat和IIS上发布

    地形瓦片(散列文件)可以直接放到tomcat或iis下发布,而不用进行额外的开发,从而满足普通用户的需求.下面我们来介绍下如何通过cesiumlab生成的瓦片发布并在前端展示. 1.数据准备: 首先通 ...

  10. ArrayList,LinkedList,Vestor

    Collection是最基本的集合接口,声明了适用于JAVA集合的通用方法,list和set都继承自collection接口. Collection接口的方法 boolean add(Object o ...