【Go语言入门教程】Go语言简介-程序员宅基地

技术标签: 2024年程序员学习  python  golang  开发语言  

总而言之,Go语言对于当前大多数主流语言来讲,最大的优势在于具有较高的生产效率、先进的依赖管理和类型系统,以及原生的并发计算支持。因此,Go语言自发布以来就受到了各个领域开发者的关注和青睐。

Go语言的劣势

下面,我们来客观地看一下目前Go语言需要加强或改进的地方(虽然有些 Gopher 并不这么认为)。

  1. 从分布式计算的角度来看,Go语言的成熟度不及 Erlang(现在已经出现了一些这方面的Go语言代码包,我们已经可以看到光明的未来了)。
  2. 从程序运行速度的角度来看,Go语言虽然已与 Java 不相上下,但还不及 C(差距正在不断地缩小)。
  3. 从第三方库的角度来看,Go语言的库数量还远远不及其他几门主流语言(比如 Java、Python、Ruby 等)。不过与Go语言的年纪相比,用它实现的第三方库已经相当多了,并且它们的数量在持续地飞速增长中。

另外,在更深的层面,Go语言标准库中也有些不尽如人意的的地方,具体如下。

  1. 从语言语法角度来看,Go语言语法里的语法糖并不多,这让许多 Python、Ruby 爱好者们对它不屑一顾。另外,变量赋值方式多得有点儿累赘了。最让人遗憾的也是我比较在意的一个地方是,Go语言不支持自定义的泛型类型。
  2. 从并发编程角度来看,Go语言提供的并发模型很强大,但也有一些编写规则需要了解。否则,很容易踩进“坑”里。其实不提倡把这叫作“坑”。因为这些所谓的“坑”,大都是我们由于对原理不熟悉而自己挖出来的。
  3. 从垃圾回收角度看,Go语言的垃圾回收采用的是并发的标记清除算法(Concurrent Mark and Sweep,CMS)。虽然是并发的操作,时间比串行操作短很多,但是还是会在垃圾回收期间停止所有用户程序的操作。这一点多少会影响到对实时性要求比较高的应用。不过,在Go语言 1.3 之后的版本中,这方面的问题已经得到了极大的改善。

虽然Go语言还有一些瑕疵,但从整体来看,它已经是一门非常优秀的通用编程语言了。并且,Go语言在今后的发展上会关注性能、可靠性、可移植性和一些功能增强,所以上述缺憾会随着版本的推进而逐渐减弱和消失。

Go语言的性能如何?

根据 Go 开发团队和基本的算法测试,Go语言与C语言的性能差距大概在 10%~20% 之间。虽然没有官方的性能标准,但是与其它各个语言相比已经拥有非常出色的表现。

时下流行的语言大都是运行在虚拟机上,如:Java 和 Scala 使用的 JVM,C# 和 VB.NET 使用的 .NET CLR。尽管虚拟机的性能已经有了很大的提升,但任何使用 JIT 编译器和脚本语言解释器的编程语言(Ruby、Python、Perl 和 JavaScript)在 C 和 C++ 的绝对优势下甚至都无法在性能上望其项背。

这里以国外的一个编程语言性能测试网站 http://benchmarksgame.alioth.debian.org/ 为测试基准和数据源。这个网站可以对常见的编程语言进行性能比较,网站使用都是最新的语言版本和常见的一些算法。

通过对 C(gcc)、C++、Java、JavaScript 和Go语言的测试。性能比较如下表所示,表中数据的单位为秒,数值越小表明运行性能越好。

编程语言↓ / 测试用例→ reverse-complement pidigits fannkuch-redux fasta spectral-norm n-body k-nucleotide mandelbrot binary-trees regex-redux
C语言 0.42 1.73 8.97 1.33 1.99 9.96 5.38 1.65 2.38 1.45
C++ 0.6 1.89 10.35 1.48 1.99 9.31 7.18 1.73 2.36 17.14
Go 0.49 2.02 14.49 2.17 3.96 21.47 14.79 5.46 35.18 29.29
Java 1.13 3.12 15.09 2.32 4.25 22.56 8.38 6.08 8.58 10.38
JavaScript 4.3 N/A 81.49 9.79 16.17 28.74 66.07 19.04 53.64 4.44

通过上表可以看出,Go语言在性能上更接近于 Java 语言,虽然在某些测试用例上不如经过多年优化的 Java 语言,但毕竟 Java 语言已经经历了多年的积累和优化。Go语言在未来的版本中会通过不断的版本优化提高单核运行性能。

Go语言标准库强大

学习编程语言,早已不是学一点语法规则那么简单。现在更习惯称作选择 Ecosystem(生态圈),而这其中标准库的作用和分量尤为明显。

在Go语言的安装文件里包含了一些可以直接使用的包,即标准库。Go语言的标准库(通常被称为语言自带的电池),提供了清晰的构建模块和公共接口,包含 I/O 操作、文本处理、图像、密码学、网络和分布式应用程序等,并支持许多标准化的文件格式和编解码协议。

在 Windows 下,标准库的位置在Go语言根目录下的子目录 pkg\windows_amd64 中;在 Linux 下,标准库在Go语言根目录下的子目录 pkg\linux_amd64 中(如果是安装的是 32 位,则在 linux_386 目录中)。一般情况下,标准包会存放在

G

O

R

O

O

T

/

p

k

g

/

GOROOT/pkg/

GOROOT/pkg/GOOS_$GOARCH/ 目录下。

Go语言的编译器也是标准库的一部分,通过词法器扫描源码,使用语法树获得源码逻辑分支等。Go语言的周边工具也是建立在这些标准库上。在标准库上可以完成几乎大部分的需求。

Go语言的标准库以包的方式提供支持,下表列出了Go语言标准库中常见的包及其功能。

Go语言标准库包名 功 能
bufio 带缓冲的 I/O 操作
bytes 实现字节操作
container 封装堆、列表和环形列表等容器
crypto 加密算法
database 数据库驱动和接口
debug 各种调试文件格式访问及调试功能
encoding 常见算法如 JSON、XML、Base64 等
flag 命令行解析
fmt 格式化操作
go Go语言的词法、语法树、类型等。可通过这个包进行代码信息提取和修改
html HTML 转义及模板系统
image 常见图形格式的访问及生成
io 实现 I/O 原始访问接口及访问封装
math 数学库
net 网络库,支持 Socket、HTTP、邮件、RPC、SMTP 等
os 操作系统平台不依赖平台操作封装
path 兼容各操作系统的路径操作实用函数
plugin Go 1.7 加入的插件系统。支持将代码编译为插件,按需加载
reflect 语言反射支持。可以动态获得代码中的类型信息,获取和修改变量的值
regexp 正则表达式封装
runtime 运行时接口
sort 排序接口
strings 字符串转换、解析及实用函数
time 时间接口
text 文本模板及 Token 词法器

当然,优秀第三方资源也是语言生态圈的重要组成部分。近年来崛起的几门语言中,Go 算是独树一帜,大批优秀作品频繁涌现,这也给我们学习 Go 提供了很好的参照。

Go语言上手简单

Go语言语法简单易懂,学习曲线平缓,不需要像 C/C++ 语言动辄需要两到三年的学习期。Go语言被称为“互联网时代的C语言”。互联网的短、频、快特性在Go语言中体现得淋漓尽致。一个熟练的开发者只需要短短的一周时间就可以从学习阶段转到开发阶段,并完成一个高并发的服务器开发。

Go语言是 Google 公司开发的一种静态型、编译型并自带垃圾回收和并发的编程语言。所以它是一门类型安全的语言,加上通过构建到本地代码,程序的执行速度也非常快。

Go语言的主要目标是将静态语言的安全性和高效性与动态语言的易开发性进行有机结合,达到完美平衡,从而使编程变得更加有乐趣,而不是在艰难抉择中痛苦前行。

Go语言在拥有一些动态语言的特性的同时,其语法风格类似于C语言。在C语言的基础上进行了大幅的简化,去掉了不需要的表达式括号,循环也只有 for 一种表示方法,就可以实现数值、键值等各种遍历。因此,Go语言上手非常容易。

很多读者表示自己是在看了介绍后才开始了解这门语言的,他们一般也会使用两到三门编程语言。Go语言对于他们来说,也就是一到两天的熟悉过程,之后就可以开始使用Go语言解决具体问题了,大约一周左右已经可以使用Go语言完成既定的任务了。

Go语言这种从零开始使用到解决问题的速度,在其他语言中是完全不可想象的。学过 C++ 的朋友都知道,一到两年大强度的理论学习和实战操练也只能学到这门语言的皮毛,以及知道一些基本的避免错误的方法。

那么,Go语言到底有多么简单?下面通过实现一个 HTTP 服务器来了解一下。

【实例】HTTP 文件服务器是常见的 Web 服务之一。开发阶段为了测试,需要自行安装 Apache 或 Nginx 服务器,下载安装配置需要大量的时间。使用Go语言实现一个简单的 HTTP 服务器只需要几行代码,如下所示。

package main
import (
“net/http”
)
func main() {
http.Handle(“/”, http.FileServer(http.Dir(“.”)))
http.ListenAndServe(“:8080”, nil)
}

下面是代码说明:

  • 第 1 行,标记当前文件为 main 包,main 包也是 Go 程序的入口包。
  • 第 3~5 行,导入 net/http 包,这个包的作用是 HTTP 的基础封装和访问。
  • 第 7 行,程序执行的入口函数 main()。
  • 第 8 行,使用 http.FileServer 文件服务器将当前目录作为根目录(/目录)的处理器,访问根目录,就会进入当前目录。
  • 第 9 行,默认的 HTTP 服务侦听在本机 8080 端口。

把这个源码保存为 main.go(Go语言的源文件后缀就是.go),安装Go语言的开发包(后续我们会讲解如何安装),在命令行输入如下命令:

$ go run main.go

在浏览器里输入http://127.0.0.1:8080即可浏览文件,这些文件正是当前目录在HTTP服务器上的映射目录。

Go语言工程结构简单

Go语言的源码无须头文件,编译的文件都来自于后缀名为.go的源码文件。

Go语言无须解决方案、工程文件和 Make File,只要将工程文件按照 GOPATH 的规则进行填充,即可使用 go build/go install 进行编译,编译完成的二进制可执行文件统一放在 bin 文件夹下。

后面的章节会介绍 GOPATH 及 go build/go install 的详细使用方法。

Go语言编译速度快

Go语言可以利用自己的特性实现并发编译,并发编译的最小元素是包。从 Go 1.9 版本开始,最小并发编译元素缩小到函数,整体编译速度提高了 20%。

另外,Go语言语法简单,具有严谨的工程结构设计、没有头文件、不允许包的交叉依赖等规则,在很大程度上加速了编译的过程。

Go语言代码风格清晰、简单

Go语言语法类似于C语言,因此熟悉C语言及其派生语言(C++C#、Objective-C 等)的人都会迅速熟悉这门语言。

C语言的有些语法会让代码可读性降低甚至发生歧义。Go语言在C语言的基础上取其精华,弃其糟粕,将C语言中较为容易发生错误的写法进行调整,做出相应的编译提示。

1) 去掉循环冗余括号

Go语言在众多大师的丰富实战经验的基础上诞生,去除了C语言语法中一些冗余、烦琐的部分。下面的代码是C语言的数值循环:

// C语言的for数值循环
for(int a = 0;a<10;a++){
// 循环代码
}

在Go语言中,这样的循环变为:

for a := 0;a<10;a++{
// 循环代码
}

for 两边的括号被去掉,int 声明被简化为:=,直接通过编译器右值推导获得 a 的变量类型并声明。

2) 去掉表达式冗余括号

同样的简化也可以在判断语句中体现出来,以下是C语言的判断语句:

if (表达式){
// 表达式成立
}

在Go语言中,无须添加表达式括号,代码如下:

if 表达式{
// 表达式成立
}

3) 强制的代码风格

Go语言中,左括号必须紧接着语句不换行。其他样式的括号将被视为代码编译错误。这个特性刚开始会使开发者有一些不习惯,但随着对Go语言的不断熟悉,开发者就会发现风格统一让大家在阅读代码时把注意力集中到了解决问题上,而不是代码风格上。

同时Go语言也提供了一套格式化工具。一些Go语言的开发环境或者编辑器在保存时,都会使用格式化工具对代码进行格式化,让代码提交时已经是统一格式的代码。

4) 不再纠结于 i++ 和 ++i

C语言非常经典的考试题为:

int a, b;
a = i++;
b = ++i;

这种题目对于初学者简直摸不着头脑。为什么一个简单的自增表达式需要有两种写法?

在Go语言中,自增操作符不再是一个操作符,而是一个语句。因此,在Go语言中自增只有一种写法:

i++

如果写成前置自增++i,或者赋值后自增a=i++都将导致编译错误。

Go语言是怎么完成编译的

Go语言是一门需要编译才能运行的编程语言,也就说代码在运行之前需要通过编译器生成二进制机器码,随后二进制文件才能在目标机器上运行,如果我们想要了解Go语言的实现原理,理解它的编译过程就是一个没有办法绕过的事情。

预备知识

想要深入了解Go语言的编译过程,需要提前了解一下编译过程中涉及的一些术语和专业知识。这些知识其实在我们的日常工作和学习中比较难用到,但是对于理解编译的过程和原理还是非常重要的。

1) 抽象语法树

在计算机科学中,抽象语法树(Abstract Syntax Tree,AST),或简称语法树(Syntax tree),是源代码语法结构的一种抽象表示。它以树状的形式表现编程语言的语法结构,树上的每个节点都表示源代码中的一种结构。

之所以说语法是“抽象”的,是因为这里的语法并不会表示出真实语法中出现的每个细节。比如,嵌套括号被隐含在树的结构中,并没有以节点的形式呈现。而类似于 if else 这样的条件判断语句,可以使用带有两个分支的节点来表示。

以算术表达式 1+3*(4-1)+2 为例,可以解析出的抽象语法树如下图所示:

抽象语法树
图:抽象语法树

抽象语法树可以应用在很多领域,比如浏览器,智能编辑器,编译器。

2) 静态单赋值

在编译器设计中,静态单赋值形式(static single assignment form,通常简写为 SSA form 或是 SSA)是中介码(IR,intermediate representation)的属性,它要求每个变量只分配一次,并且变量需要在使用之前定义。在实践中我们通常会用添加下标的方式实现每个变量只能被赋值一次的特性,这里以下面的代码举一个简单的例子:

x := 1
x := 2
y := x

从上面的描述所知,第一行赋值行为是不需要的,因为 x 在第二行被二度赋值并在第三行被使用,在 SSA 下,将会变成下列的形式:

x1 := 1
x2 := 2
y1 := x2

从使用 SSA 的中间代码我们就可以非常清晰地看出变量 y1 的值和 x1 是完全没有任何关系的,所以在机器码生成时其实就可以省略第一步,这样就能减少需要执行的指令来优化这一段代码。

根据 Wikipedia(维基百科)对 SSA 的介绍来看,在中间代码中使用 SSA 的特性能够为整个程序实现以下的优化:

  • 常数传播(constant propagation)
  • 值域传播(value range propagation)
  • 稀疏有条件的常数传播(sparse conditional constant propagation)
  • 消除无用的程式码(dead code elimination)
  • 全域数值编号(global value numbering)
  • 消除部分的冗余(partial redundancy elimination)
  • 强度折减(strength reduction)
  • 寄存器分配(register allocation)

因为 SSA 的主要作用就是代码的优化,所以是编译器后端(主要负责目标代码的优化和生成)的一部分。当然,除了 SSA 之外代码编译领域还有非常多的中间代码优化方法,优化编译器生成的代码是一个非常古老并且复杂的领域,这里就不展开介绍了。

3) 指令集架构

最后要介绍的一个预备知识就是指令集架构了,指令集架构(Instruction Set Architecture,简称 ISA),又称指令集或指令集体系,是计算机体系结构中与程序设计有关的部分,包含了基本数据类型,指令集,寄存器,寻址模式,存储体系,中断,异常处理以及外部 I/O。指令集架构包含一系列的 opcode 即操作码(机器语言),以及由特定处理器执行的基本命令。

指令集架构常见种类如下:

  • 复杂指令集运算(Complex Instruction Set Computing,简称 CISC);
  • 精简指令集运算(Reduced Instruction Set Computing,简称 RISC);
  • 显式并行指令集运算(Explicitly Parallel Instruction Computing,简称 EPIC);
  • 超长指令字指令集运算(VLIW)。

不同的处理器(CPU)使用了大不相同的机器语言,所以我们的程序想要在不同的机器上运行,就需要将源代码根据架构编译成不同的机器语言。

编译原理

Go语言编译器的源代码在 cmd/compile 目录中,目录下的文件共同构成了Go语言的编译器,学过编译原理的人可能听说过编译器的前端和后端,编译器的前端一般承担着词法分析、语法分析、类型检查和中间代码生成几部分工作,而编译器后端主要负责目标代码的生成和优化,也就是将中间代码翻译成目标机器能够运行的机器码。

img

Go的编译器在逻辑上可以被分成四个阶段:词法与语法分析、类型检查和 AST 转换、通用 SSA 生成和最后的机器代码生成,下面我们来分别介绍一下这四个阶段做的工作。

1) 词法与语法分析

所有的编译过程其实都是从解析代码的源文件开始的,词法分析的作用就是解析源代码文件,它将文件中的字符串序列转换成 Token 序列,方便后面的处理和解析,我们一般会把执行词法分析的程序称为词法解析器(lexer)。

而语法分析的输入就是词法分析器输出的 Token 序列,这些序列会按照顺序被语法分析器进行解析,语法的解析过程就是将词法分析生成的 Token 按照语言定义好的文法(Grammar)自下而上或者自上而下的进行规约,每一个 Go 的源代码文件最终会被归纳成一个 SourceFile 结构:

SourceFile = PackageClause “;” { ImportDecl “;” } { TopLevelDecl “;” }

标准的 Golang 语法解析器使用的就是 LALR(1) 的文法,语法解析的结果其实就是上面介绍过的抽象语法树(AST),每一个 AST 都对应着一个单独的Go语言文件,这个抽象语法树中包括当前文件属于的包名、定义的常量、结构体和函数等。

如果在语法解析的过程中发生了任何语法错误,都会被语法解析器发现并将消息打印到标准输出上,整个编译过程也会随着错误的出现而被中止。

2) 类型检查

当拿到一组文件的抽象语法树 AST 之后,Go语言的编译器会对语法树中定义和使用的类型进行检查,类型检查分别会按照顺序对不同类型的节点进行验证,按照以下的顺序进行处理:

  • 常量、类型和函数名及类型;
  • 变量的赋值和初始化;
  • 函数和闭包的主体;
  • 哈希键值对的类型;
  • 导入函数体;
  • 外部的声明;

通过对每一棵抽象节点树的遍历,我们在每一个节点上都会对当前子树的类型进行验证保证当前节点上不会出现类型错误的问题,所有的类型错误和不匹配都会在这一个阶段被发现和暴露出来。

类型检查的阶段不止会对树状结构的节点进行验证,同时也会对一些内建的函数进行展开和改写,例如 make 关键字在这个阶段会根据子树的结构被替换成 makeslice 或者 makechan 等函数。

其实类型检查不止对类型进行了验证工作,还对 AST 进行了改写以及处理Go语言内置的关键字,所以,这一过程在整个编译流程中是非常重要的,没有这个步骤很多关键字其实就没有办法工作。

3) 中间代码生成

当我们将源文件转换成了抽象语法树,对整个语法树的语法进行解析并进行类型检查之后,就可以认为当前文件中的代码基本上不存在无法编译或者语法错误的问题了,Go语言的编译器就会将输入的 AST 转换成中间代码。

Go语言编译器的中间代码使用了 SSA(Static Single Assignment Form) 的特性,如果我们在中间代码生成的过程中使用这种特性,就能够比较容易的分析出代码中的无用变量和片段并对代码进行优化。

在类型检查之后,就会通过一个名为 compileFunctions 的函数开始对整个Go语言项目中的全部函数进行编译,这些函数会在一个编译队列中等待几个后端工作协程的消费,这些 Goroutine 会将所有函数对应的 AST 转换成使用 SSA 特性的中间代码。

4) 机器码生成

Go语言源代码的 cmd/compile/internal 目录中包含了非常多机器码生成相关的包,不同类型的 CPU 分别使用了不同的包进行生成 amd64、arm、arm64、mips、mips64、ppc64、s390x、x86 和 wasm,也就是说Go语言能够在几乎全部常见的 CPU 指令集类型上运行。

编译器入口

Go语言的编译器入口是 src/cmd/compile/internal/gc 包中的 main.go 文件,这个 600 多行的 Main 函数就是Go语言编译器的主程序,这个函数会先获取命令行传入的参数并更新编译的选项和配置,随后就会开始运行 parseFiles 函数对输入的所有文件进行词法与语法分析得到文件对应的抽象语法树:

func Main(archInit func(*Arch)) {
// …

lines := parseFiles(flag.Args())

接下来就会分九个阶段对抽象语法树进行更新和编译,就像我们在上面介绍的,整个过程会经历类型检查、SSA 中间代码生成以及机器码生成三个部分:

  • 检查常量、类型和函数的类型;
  • 处理变量的赋值;
  • 对函数的主体进行类型检查;
  • 决定如何捕获变量;
  • 检查内联函数的类型;
  • 进行逃逸分析;
  • 将闭包的主体转换成引用的捕获变量;
  • 编译顶层函数;
  • 检查外部依赖的声明;

了解了剩下的编译过程之后,我们重新回到词法和语法分析后的具体流程,在这里编译器会对生成语法树中的节点执行类型检查,除了常量、类型和函数这些顶层声明之外,它还会对变量的赋值语句、函数主体等结构进行检查:

for i := 0; i < len(xtop); i++ {
n := xtop[i]
if op := n.Op; op != ODCL && op != OAS && op != OAS2 && (op != ODCLTYPE || !n.Left.Name.Param.Alias) {
xtop[i] = typecheck(n, ctxStmt)
}
}
for i := 0; i < len(xtop); i++ {
n := xtop[i]
if op := n.Op; op == ODCL || op == OAS || op == OAS2 || op == ODCLTYPE && n.Left.Name.Param.Alias {
xtop[i] = typecheck(n, ctxStmt)
}
}
for i := 0; i < len(xtop); i++ {
n := xtop[i]
if op := n.Op; op == ODCLFUNC || op == OCLOSURE {
typecheckslice(Curfn.Nbody.Slice(), ctxStmt)
}
}
checkMapKeys()
for _, n := range xtop {
if n.Op == ODCLFUNC && n.Func.Closure != nil {
capturevars(n)
}
}
escapes(xtop)
for _, n := range xtop {
if n.Op == ODCLFUNC && n.Func.Closure != nil {
transformclosure(n)
}
}

类型检查会对传入节点的子节点进行遍历,这个过程会对 make 等关键字进行展开和重写,类型检查结束之后并没有输出新的数据结构,只是改变了语法树中的一些节点,同时这个过程的结束也意味着源代码中已经不存在语法错误和类型错误,中间代码和机器码也都可以正常的生成了。

initssaconfig()
peekitabs()
for i := 0; i < len(xtop); i++ {
n := xtop[i]
if n.Op == ODCLFUNC {
funccompile(n)
}
}
compileFunctions()
for i, n := range externdcl {
if n.Op == ONAME {
externdcl[i] = typecheck(externdcl[i], ctxExpr)
}
}
checkMapKeys()
}

在主程序运行的最后,会将顶层的函数编译成中间代码并根据目标的 CPU 架构生成机器码,不过这里其实也可能会再次对外部依赖进行类型检查以验证正确性。

总结

Go语言的编译过程其实是非常有趣并且值得学习的,通过对Go语言四个编译阶段的分析和对编译器主函数的梳理,我们能够对 Golang 的实现有一些基本的理解,掌握编译的过程之后,Go语言对于我们来讲也不再那么神秘,所以学习其编译原理的过程还是非常有必要的。

在Windows上安装Go语言开发包

通过前面几节的学习,相信大家已经对Go语言有了一定的了解,接下来将为大家介绍如何在我们的电脑上安装Go语言开发包,首先从 Windows 系统开始。

下载Go语言开发包

大家可以在Go语言官网(https://golang.google.cn/dl/)下载 Windows 系统下的Go语言开发包,如下图所示。

Go语言安装包下载页面

这里我们下载的是 64 位的开发包,如果读者的电脑是 32 位系统的话,则需要下载 32 位的开发包,在上图所示页面中向下滚动即可找到 32 位开发包的下载地址,如下图所示。

其他版本的Go语言安装包

注意:下载 Windows 版本的Go语言开发包时尽量选择 MSI 格式,因为它可以直接安装到系统,不需要额外的操作。

安装Go语言开发包

双击我们下载好的Go语言开发包即可启动安装程序,如下图所示,这是Go语言的用户许可协议,无需管它,直接勾选“I accept …”然后点击“Next”即可。

许可协议

在 Windows 系统下Go语言开发包会默认安装到 C 盘的 Go 目录下,推荐在这个目录下安装,使用起来较为方便。当然,你也可以选择其他的安装目录,确认无误后点击“Next”,如下图所示:

选择安装目录

Go语言开发包的安装没有其他需要设置的选项,点击“Install”即可开始安装,如下图所示:

img

等待程序完成安装,然后点击“Finish”退出安装程序。

完成安装

安装完成后,在我们所设置的安装目录下将生成一些目录和文件,如下图所示:

Go 安装目录

这个目录的结构遵守 GOPATH 规则,后面的章节会提到这个概念。目录中各个文件夹的含义如下表所示。

目录名 说明
api 每个版本的 api 变更差异
bin go 源码包编译出的编译器(go)、文档工具(godoc)、格式化工具(gofmt)
doc 英文版的 Go 文档
lib 引用的一些库文件
misc 杂项用途的文件,例如 Android 平台的编译、git 的提交钩子等
pkg Windows 平台编译好的中间文件
src 标准库的源码
test 测试用例

开发时,无须关注这些目录。如果读者希望深度了解底层原理,可以通过上面的介绍继续探索。

设置环境变量

开发包安装完成后,我们还需要配置一下GOPATH环境变量,之后才可以使用Go语言进行开发。GOPATH 是一个路径,用来存放开发中需要用到的代码包。

在桌面或者资源管理器右键“此电脑”(或者“我的电脑”)→“属性”→“高级系统设置”→“环境变量”,如下图所示。

设置环境变量

在弹出的菜单里找到 GOPATH 对应的选项点击编辑之后就可以修改了,没有的话可以选择新建,并将变量名填写为 GOPATH,变量值设置为任意目录均可(尽量选择空目录),例如 D:\Go。

GOPATH环境变量配置

提示:填写完成后,每个打开的窗口都需要点击“确定”来保存设置。

其它的环境变量安装包均会进行自动设置。在默认情况下,Go 将会被安装在目录 c:\go 下,但如果你在安装过程中修改安装目录,则可能需要手动修改所有的环境变量的值。

环境变量设置好后,可以通过go env命令来进行测试。

C:\Users\Administrator>go env
set GO111MODULE=
set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\Administrator\AppData\Local\go-build
set GOENV=C:\Users\Administrator\AppData\Roaming\go\env
set GOEXE=.exe
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=C:\Users\Administrator\go
set GOPRIVATE=
set GOPROXY=https://proxy.golang.org,direct
set GOROOT=c:\go
. . .

上面只显示了部分结果,如果执行go env命令后,出现类似上面的结果,说明我们的Go开发包已经安装成功了。

如果大家想了解更多关于 GOPATH 的介绍可以参考《GOPATH详解》一节。

在Linux上安装Go语言开发包

前面我们介绍了在 Windows 系统上来搭建Go语言开发包,本节将为大家讲解在 Linux 平台安装Go语言开发包,大家可以在Go语言官网找到对应的安装包(https://golang.google.cn/dl/),但是先不要急着下载。

提示:阅读本节需要对 Linux 系统及常用的命令有一定的了解,感兴趣的读者可以通过阅读《Linux入门教程》来了解更多 Linux 相关的知识。

Go语言官网

注意:开发包有 32 位和 64 位两个版本,需要根据读者电脑的情况选择不同的版本。

接下来将带领大家一步步的完成安装过程。

安装Go语言开发包

首先,复制Go语言开发包的下载链接(https://dl.google.com/go/go1.13.4.linux-amd64.tar.gz)。然后,在终端使用cd命令进入你用来存放安装包的目录中(这里使用的是 /usr/local/ 目录,读者也可以使用其它目录)。

root@ububtu:~# cd /usr/local/
root@ububtu:/usr/local#

使用wget命令下载Go语言开发包,如下所示。

root@ububtu:/usr/local# wget https://dl.google.com/go/go1.13.4.linux-amd64.tar.gz
–2019-11-06 10:47:23-- https://dl.google.com/go/go1.13.4.linux-amd64.tar.gz
正在解析主机 dl.google.com (dl.google.com)… 203.208.39.196, 203.208.39.193, 203.208.39.200, …
正在连接 dl.google.com (dl.google.com)|203.208.39.196|:443… 已连接。
已发出 HTTP 请求,正在等待回应… 200 OK
长度: 120054682 (114M) [application/octet-stream]
正在保存至: “go1.13.4.linux-amd64.tar.gz”

go1.13.4.linux 43% 49.44M 3.56MB/s 剩余 16s ^go1.13.4.linux 100% 114.49M 4.73MB/s 用时 31s

2019-11-06 10:47:56 (3.67 MB/s) - 已保存 “go1.13.4.linux-amd64.tar.gz” [120054682/120054682])

使用tar命令解压刚刚下载的Go语言开发包。

root@ububtu:/usr/local# tar -C /usr/local -xzf go1.13.4.linux-amd64.tar.gz

解压成功后会在当前目录下新增一个 go 目录,至此我们的Go语言开发包就安装完成了,使用cd命令进入该目录,然后执行bin/go version命令就可以查看当前Go语言的版本了。

root@ububtu:/usr/local/go# bin/go version
go version go1.13.4 linux/amd64

配置环境变量

我们需要配置 2 个环境变量分别是 GOROOT 和 PATH。

  • GOROOT 的值应该为Go语言的当前安装目录:export GOROOT=/usr/local/go
  • PATH 为了方便使用Go语言命令和 Go 程序的可执行文件,需要追加其值:export PATH=

P

A

T

H

:

PATH:

PATH:GOROOT/bin:$GOBIN

为了方便以后的使用,需要把这几个环境变量添加 profile 文件中(~/.bash_profile 或 /etc/profile)。如果是单用户使用,可以将环境变量添加在 home 目录下的 bash_profile 文件中,如果是多用户使用,需要添加在 /etc/profile 文件。(推荐大家在 /etc/profile 文件中设置环境变量)

使用vi /etc/profile命令打开 profile 文件,并将环境变量添加到文件末尾。

添加环境变量

添加完成后使用:wq命令保存并退出。

然后,使用source /etc/profile命令使配置文件生效,现在就可以在任意目录使用Go语言命令了。

验证安装

在任意目录下使用终端执行 go env 命令,输出如下结果说明Go语言开发包已经安装成功。

root@ububtu:~$ go env
GO111MODULE=“”
GOARCH=“amd64”
GOBIN=“”
GOCACHE=“/home/feng/.cache/go-build”
GOENV=“/home/feng/.config/go/env”
GOEXE=“”
GOFLAGS=“”
GOHOSTARCH=“amd64”
GOHOSTOS=“linux”
GONOPROXY=“”
GONOSUMDB=“”
GOOS=“linux”
GOPATH=“/home/feng/go”
GOPRIVATE=“”
GOPROXY=“https://proxy.golang.org,direct”
GOROOT=“/usr/local/go”
GOSUMDB=“sum.golang.org”
GOTMPDIR=“”
. . .

提示:上面只显示了部分结果。

在Mac OS上安装Go语言开发包

本节主要为大家讲解如何在Mac OS上安装Go语言开发包,大家可以在Go语言官网下载对应版本的的安装包(https://golang.google.cn/dl/),如下图所示。

下载Mac OS版Go语言开发包

安装Go语言开发包

Mac OS 的Go语言开发包是 .pkg 格式的,双击我们下载的安装包即可开始安装。

img

Mac OS 下是傻瓜式安装,一路点击“继续”即可,不再赘述。

img

安装包会默认安装在 /usr/local 目录下,如下所示。

Go 的安装目录

安装完成之后,在终端运行 go version,如果显示类似下面的信息,表明安装成功。

go version go1.13.4 darwin/amd64

设置 GOPATH 环境变量

开始写 go 项目代码之前,需要我们先配置好环境变量。编辑 ~/.bash_profile(在终端中运行 vi ~/.bash_profile 即可)来添加下面这行代码(如果你找不到 .bash_profile,那自己创建一个就可以了)

export GOPATH=$HOME/go

保存然后退出你的编辑器。然后在终端中运行下面命令

source ~/.bash_profile

提示:$HOME 是每个电脑下的用户主目录,每个电脑可能不同,可以在终端运行 echo $HOME 获取

GOROOT 也就是 Go 开发包的安装目录默认是在 /usr/local/go,如果没有,可以在 bash_profile 文件中设置。

export GOROOT=/usr/local/go

然后保存并退出编辑器,运行 source ~/.bash_profile命令即可。

Go语言集成开发环境(IDE)大汇总

前面我们介绍了Go语言的安装,本节我们来为大家介绍几款强大的Go语言集成开发环境(Integrated Development Environment,IDE)和编辑器。

如何挑选合适的编辑器或集成开发环境呢?下面列举了一些Go语言集成开发环境或编辑器应该具备的特性:

  • 语法高亮是必不可少的功能,这也是为什么每个开发工具都提供配置文件来实现自定义配置的原因。
  • 拥有较好的项目文件纵览和导航能力,可以同时编辑多个源文件并设置书签,能够匹配括号,能够跳转到某个函数或类型的定义部分。
  • 完美的查找和替换功能,替换之前最好还能预览结果。
  • 当有编译错误时,双击错误提示可以跳转到发生错误的位置。
  • 跨平台,能够在 Linux、Mac OS X 和 Windows 下工作,这样就可以专注于一个开发环境。
  • 能够通过插件架构来轻易扩展和替换某个功能。
  • 拥有断点、检查变量值、单步执行、逐过程执行标识库中代码的能力。
  • 能够方便的存取最近使用过的文件或项目。
  • 拥有对包、类型、变量、函数和方法的智能代码补全的功能。
  • 能够方便地在不同的 Go 环境之间切换。
  • 针对一些特定的项目有项目模板,如:Web 应用,App Engine 项目,从而能够更快地开始开发工作。

下面为大家推荐几款常用的适用于Go语言的编辑器或集成开发环境。

1) Goland

Goland 是由 JetBrains 公司开发的一个新的商业 IDE,旨在为 Go 开发者提供的一个符合人体工程学的新的商业 IDE。Goland 整合了 IntelliJ 平台(一个用于 java 语言开发的集成环境,也可用于其他开发语言),提供了针对Go语言的编码辅助和工具集成。

Goland

关于 Goland 的详细使用说明请参考《Goland 2019下载和安装》一节。

2) LiteIDE

LiteIDE是一款专门针对 Go 开发的集成开发环境,在编辑、编译和运行 Go 程序和项目方面都有非常好的支持。同时还包括了对源代码的抽象语法树视图和一些内置工具(此开发环境由国人 vfc 大叔开发)。

LiteIDE 是一款非常好用的轻量级 Go 集成开发环境(基于 QT、Kate 和 SciTE),包含了跨平台开发及其它必要的特性,对代码编写、自动补全和运行调试都有极佳的支持。它采用了 Go 项目的概念来对项目文件进行浏览和管理,它还支持在各个 Go 开发环境之间随意切换以及交叉编译的功能。

同时,它具备了抽象语法树视图的功能,可以清楚地纵览项目中的常量、变量、函数、不同类型以及他们的属性和方法。

LiteIDE界面

关于 LiteIDE 的安装和使用大家可以参考《LiteIDE搭建Go语言开发环境》一节。

3) Sublime Text

一个革命性的跨平台(Linux、Mac OS X、Windows)文本编辑器,它支持编写非常多的编程语言代码。对于 Go 而言,它有一个插件叫做 GoSublime 来支持代码补全和代码模版。

4) GoClipse

是一款 Eclipse IDE 的插件,拥有非常多的特性以及通过 GoCode 来实现代码补全功能。其依附于著名的 Eclipse 这个大型开发环境,虽然需要安装 JVM 运行环境,但却可以很容易地享有 Eclipse 本身所具有的诸多功能。这是一个非常好的编辑器,完善的代码补全、抽象语法树视图、项目管理和程序调试功能。

GoClipse界面

如果你对集成开发环境都不是很熟悉,那就使用 LiteIDE 吧,另外使用 GoClipse 或者 IntelliJ Idea Plugin 也是不错的选择。

代码补全一般都是通过内置 GoCode 实现的(如:LiteIDE、GoClipse),如果需要手动安装 GoCode,在命令行输入指令 go get -u github.com/nsf/gocode 即可(务必事先配置好 Go 环境变量) 。

5) Visual Studio Code(简称VS Code)

是一款由微软公司开发的,能运行在 Mac OS X、Windows 和 Linux 上的跨平台开源代码编辑器。

VS Code 使用 JSON 格式的配置文件进行所有功能和特性的配置,同时它还可以通过扩展程序为编辑器实现编程语言高亮、参数提示、编译、调试、文档生成等各种功能。

Go语言工程结构详述

一般的编程语言往往对工程(项目)的目录结构是没有什么规定的,但是Go语言却在这方面做了相关规定,本节我们就来聊聊Go语言在工程结构方面的有关知识。

我们前面讲搭建Go语言开发环境时提到的环境变量 GOPATH,项目的构建主要是靠它来实现的。这么说吧,如果想要构建一个项目,就需要将这个项目的目录添加到 GOPATH 中,多个项目之间可以使用;分隔。

如果不配置 GOPATH,即使处于同一目录,代码之间也无法通过绝对路径相互调用。

目录结构

一个Go语言项目的目录一般包含以下三个子目录:

  • src 目录:放置项目和库的源文件;
  • pkg 目录:放置编译后生成的包/库的归档文件;
  • bin 目录:放置编译后生成的可执行文件。

三个目录中我们需要重点关注的是 src 目录,其他两个目录了解即可,下面来分别介绍一下这三个目录。

src 目录

用于以包(package)的形式组织并存放 Go 源文件,这里的包与 src 下的每个子目录是一一对应。例如,若一个源文件被声明属于 log 包,那么它就应当保存在 src/log 目录中。

并不是说 src 目录下不能存放 Go 源文件,一般在测试或演示的时候也可以把 Go 源文件直接放在 src 目录下,但是这么做的话就只能声明该源文件属于 main 包了。正常开发中还是建议大家把 Go 源文件放入特定的目录中。

包是Go语言管理代码的重要机制,其作用类似于Java中的 package 和 C/C++ 的头文件。Go 源文件中第一段有效代码必须是package <包名>的形式,如 package hello。

另外需要注意的是,Go语言会把通过go get命令获取到的库源文件下载到 src 目录下对应的文件夹当中。

pkg 目录

用于存放通过go install命令安装某个包后的归档文件。归档文件是指那些名称以“.a”结尾的文件。

该目录与 GOROOT 目录(也就是Go语言的安装目录)下的 pkg 目录功能类似,区别在于这里的 pkg 目录专门用来存放项目代码的归档文件。

编译和安装项目代码的过程一般会以代码包为单位进行,比如 log 包被编译安装后,将生成一个名为 log.a 的归档文件,并存放在当前项目的 pkg 目录下。

bin 目录

与 pkg 目录类似,在通过go install命令完成安装后,保存由 Go 命令源文件生成的可执行文件。在类 Unix 操作系统下,这个可执行文件的名称与命令源文件的文件名相同。而在 Windows 操作系统下,这个可执行文件的名称则是命令源文件的文件名加 .exe 后缀。

源文件

上面我们提到了命令源文件和库源文件,它们到底是什么呢?

  • 命令源文件:如果一个 Go 源文件被声明属于 main 包,并且该文件中包含 main 函数,则它就是命令源码文件。命令源文件属于程序的入口,可以通过Go语言的go run命令运行或者通过go build命令生成可执行文件。
  • 库源文件:库源文件则是指存在于某个包中的普通源文件,并且库源文件中不包含 main 函数。

不管是命令源文件还是库源文件,在同一个目录下的所有源文件,其所属包的名称必须一致的。

Go语言依赖管理

早期的Go语言被很多开发者所吐槽的一个问题就是没有依赖包的管理,不过随着版本的不断更迭,Go语言依赖管理方面也在不断的完善。

为什么需要依赖管理

最初的时候Go语言所依赖的所有的第三方包都放在 GOPATH 目录下面,这就导致了同一个包只能保存一个版本的代码,如果不同的项目依赖同一个第三方的包的不同版本,应该怎么解决呢?

godep

godep 是一个Go语言官方提供的通过 vender 模式来管理第三方依赖的工具,类似的还有由社区维护的准官方包管理工具 dep。

Go语言从 1.5 版本开始开始引入 vendor 模式,如果项目目录下有 vendor 目录,那么Go语言编译器会优先使用 vendor 内的包进行编译、测试等。

安装godep工具

我们可以通过go get命令来获取 godep 工具。

go get github.com/tools/godep

命令执行成功后会将 godep 工具的源码下载到 GOPATH 的 src 目录下对应的文件夹中,同时还会在 GOPATH 的 bin 目录下生成一个名为 godep.exe 的可执行文件,如下图所示。

获取 godep 工具

为了方便使用 godep 工具,我们需要将存放 godep.exe 文件的目录添加到环境变量 PATH 中。在系统变量中找到并选中“Path”一行,点击“编辑”按钮,在新弹出的窗口中点击“新建”,然后在最下面一行中填入对应的目录信息。确认无误后点击“确定”。

将存放 godep 工具的目录添加的环境变量中

环境变量设置的打开方式我们在《安装Go语言开发包》一节中已经介绍过了,这里不再赘述。

godep工具的基本命令

完成上面的操作后,我们就可以在命令行窗口(CMD)中使用 godep 工具了,godep 支持的命令如下表所示:

命令 作用
godep save 将依赖包的信息保存到 Godeps.json 文件中
godep go 使用保存的依赖项运行 go 工具
godep get 下载并安装指定的包
godep path 打印依赖的 GOPATH 路径
godep restore 在 GOPATH 中拉取依赖的版本
godep update 更新选定的包或 go 版本
godep diff 显示当前和以前保存的依赖项集之间的差异
godep version 查看版本信息

使用godep help [命令名称]可以查看命令的帮助信息,如下所示。

C:\Users\Administrator>godep help go
Args: godep go [-v] [-d] command [arguments]

Go runs the go tool with a modified GOPATH giving access to
dependencies saved in Godeps.

Any go tool command can run this way, but “godep go get”
is unnecessary and has been disabled. Instead, use
“godep go install”.

If -v is given, verbose output is enabled.

If -d is given, debug output is enabled (you probably don’t want this, see -v).

使用godep工具

执行godep save命令,会在当前目录中创建 Godeps 和 vender 两个文件夹。Godeps 文件夹下会生成一个 Godeps.json 文件,用来记录项目中所依赖的包信息;vender 目录则是用来保存当前项目所依赖的所有第三方包。

godep save 命令执行成功后生成的两个文件夹

生成的 Godeps.json 文件的结构如下所示:

{
“ImportPath”: “main”,
“GoVersion”: “go1.13”,
“GodepVersion”: “v80”,
“Deps”: [
{
“ImportPath”: “github.com/go-gomail/gomail”,
“Comment”: “2.0.0-23-g81ebce5”,
“Rev”: “81ebce5c23dfd25c6c67194b37d3dd3f338c98b1”
}
]
}

其中,“ImportPath”为项目的路径信息,“GoVersion”为Go语言的版本号,“GodepVersion”为 godep 工具的版本号,“Deps”为当前依赖包的路径、版本号信息等等。

提示:当引用的第三方包要升级时,只需要修改 Godep.json 里面的依赖包的版本号,然后再次执行 godep save 命令即可。

godep 工具的主要功能就是控制Go语言程序编译时依赖包搜索路径的优先级。例如查找项目的某个依赖包,首先会在项目根目录下的 vender 文件夹中查找,如果没有找到就会去 GOAPTH/src 目录下查找。

go module

go module 是Go语言从 1.11 版本之后官方推出的版本管理工具,并且从 Go1.13 版本开始,go module 成为了Go语言默认的依赖管理工具。

GO111MODULE

在Go语言 1.12 版本之前,要启用 go module 工具首先要设置环境变量 GO111MODULE,不过在Go语言 1.13 及以后的版本则不再需要设置环境变量。通过 GO111MODULE 可以开启或关闭 go module 工具。

  • GO111MODULE=off 禁用 go module,编译时会从 GOPATH 和 vendor 文件夹中查找包。
  • GO111MODULE=on 启用 go module,编译时会忽略 GOPATH 和 vendor 文件夹,只根据 go.mod 下载依赖。
  • GO111MODULE=auto(默认值),当项目在 GOPATH/src 目录之外,并且项目根目录有 go.mod 文件时,开启 go module。

Windows 下开启 GO111MODULE 的命令为:

set GO111MODULE=on 或者 set GO111MODULE=auto

MacOS 或者 Linux 下开启 GO111MODULE 的命令为:

export GO111MODULE=on 或者 export GO111MODULE=auto

在开启 GO111MODULE 之后就可以使用 go module 工具了,也就是说在以后的开发中就没有必要在 GOPATH 中创建项目了,并且还能够很好的管理项目依赖的第三方包信息。

使用 go module 的go mod init命令后会在当前目录下生成一个 go. mod 文件,并且在编译/运行当前目录下代码或者使用go get命令的时候会在当前目录下生成一个 go.sun 文件。

使用 go mod init 命令生成的两个文件

go.mod 文件记录了项目所有的依赖信息,其结构大致如下:

module main.go

go 1.13

require (
github.com/astaxie/beego v1.12.0
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 // indirect
)

其中,module 为 go.mod 文件所属的包,require 为项目所依赖的包及版本号,indirect 表示间接引用。

go.sum 文件则是用来记录每个依赖包的版本及哈希值,如下所示。

github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/OwnLocal/goes v1.0.0/go.mod h1:8rIFjBGTue3lCU0wplczcUgt9Gxgrkkrw7etMIcn8TM=
github.com/astaxie/beego v1.12.0 h1:MRhVoeeye5N+Flul5PoVfD9CslfdoH+xqC/xvSQ5u2Y=
github.com/astaxie/beego v1.12.0/go.mod h1:fysx+LZNZKnvh4GED/xND7jWtjCR6HzydR2Hh2Im57o=

常用的 go mod 命令如下表所示:

命令 作用
go mod download 下载依赖包到本地(默认为 GOPATH/pkg/mod 目录)
go mod edit 编辑 go.mod 文件
go mod graph 打印模块依赖图
go mod init 初始化当前文件夹,创建 go.mod 文件
go mod tidy 增加缺少的包,删除无用的包
go mod vendor 将依赖复制到 vendor 目录下
go mod verify 校验依赖
go mod why 解释为什么需要依赖
GOPROXY

proxy 顾名思义就是代理服务器的意思。大家都知道,国内的网络有防火墙的存在,这导致有些Go语言的第三方包我们无法直接通过go get命令获取。GOPROXY 是Go语言官方提供的一种通过中间代理商来为用户提供包下载服务的方式。要使用 GOPROXY 只需要设置环境变量 GOPROXY 即可。

目前公开的代理服务器的地址有:

  • goproxy.io
  • goproxy.cn:(推荐)由国内的七牛云提供。

Windows 下设置 GOPROXY 的命令为:

go env -w GOPROXY=https://goproxy.cn,direct

MacOS 或 Linux 下设置 GOPROXY 的命令为:

export GOPROXY=https://goproxy.cn

Go语言在 1.13 版本之后 GOPROXY 默认值为 https://proxy.golang.org,在国内可能会存在下载慢或者无法访问的情况,所以十分建议大家将 GOPROXY 设置为国内的 goproxy.cn。

使用go get命令下载指定版本的依赖包

执行go get命令,在下载依赖包的同时还可以指定依赖包的版本。

  • 运行go get -u命令会将项目中的包升级到最新的次要版本或者修订版本;
  • 运行go get -u=patch命令会将项目中的包升级到最新的修订版本;
  • 运行go get [包名]@[版本号]命令会下载对应包的指定版本或者将对应包升级到指定的版本。

提示:go get [包名]@[版本号]命令中版本号可以是 x.y.z 的形式,例如 go get [email protected],也可以是 git 上的分支或 tag,例如 go get foo@master,还可以是 git 提交时的哈希值,例如 go get foo@e3702bed2。

第一个Go语言程序

通过前面学习大家已经对Go语言有了一定的了解,那要怎么来创建一个Go语言程序呢?本节就来带领大家实现一个简单的程序——在控制台输出“Hello World!”。

在控制台输出“Hello World!”非常简单,仅需要几行代码就可以搞定,如下所示:

package main // 声明 main 包
import (
“fmt” // 导入 fmt 包,打印字符串是需要用到
)
func main() { // 声明 main 主函数
fmt.Println(“Hello World!”) // 打印 Hello World!
}

大家也许不明白这些代码的含义,没关系,下面就来一一介绍。

package(创建包)

Go语言以“包”作为管理单位,每个 Go 源文件必须先声明它所属的包,所以我们会看到每个 Go 源文件的开头都是一个 package 声明,格式如下:

package name

其中 package 是声明包名的关键字,name 为包的名字。

Go语言的包与文件夹是一一对应的,它具有以下几点特性:

  • 一个目录下的同级文件属于同一个包。
  • 包名可以与其目录名不同。
  • main 包是Go语言程序的入口包,一个Go语言程序必须有且仅有一个 main 包。如果一个程序没有 main 包,那么编译时将会出错,无法生成可执行文件。
import(导入包)

在包声明之后,是 import 语句,用于导入程序中所依赖的包,导入的包名使用双引号""包围,格式如下:

import “name”

其中 import 是导入包的关键字,name 为所导入包的名字。

代码第 4 行导入了 fmt 包,这行代码会告诉 Go 编译器,我们需要用到 fmt 包中的函数或者变量等,fmt 包是Go语言标准库为我们提供的,用于格式化输入输出的内容(类似于C语言中的 stdio.h 头文件),类似的还有 os 包、io 包等,后面我们会详细介绍。

另外有一点需要注意,导入的包中不能含有代码中没有使用到的包,否则Go编译器会报编译错误,例如imported and not used: "xxx",“xxx” 表示包名。

也可以使用一个 import 关键字导入多个包,此时需要用括号( )将包的名字包围起来,并且每个包名占用一行,也就是写成下面的样子:

import(
“name1”
“name2”
)

main 函数

代码的第 7 行创建了一个 main 函数,它是Go语言程序的入口函数,也即程序启动后运行的第一个函数。main 函数只能声明在 main 包中,不能声明在其他包中,并且,一个 main 包中也必须有且仅有一个 main 函数。

C/C++ 程序的入口函数也是 main(),一个 C/C++ 程序有且只能有一个 main() 函数。

main 函数是自定义函数的一种,在Go语言中,所有函数都以关键字 func 开头的,定义格式如下所示:

func 函数名 (参数列表) (返回值列表){
函数体
}

格式说明如下:

  • 函数名:由字母、数字、下画线_组成,其中,函数名的第一个字母不能为数字,并且,在同一个包内,函数名称不能重名。
  • 参数列表:一个参数由参数变量和参数类型组成,例如func foo( a int, b string )
  • 返回值列表:可以是返回值类型列表,也可以是参数列表那样变量名与类型的组合,函数有返回值时,必须在函数体中使用 return 语句返回。
  • 函数体:能够被重复调用的代码片段。

注意:Go语言函数的左大括号{ 必须和函数名称在同一行,否则会报错。

打印 Hello World

代码的第 8 行fmt.Println("Hello World!")中,Println 是 fmt 包中的一个函数,它用来格式化输出数据,比如字符串、整数、小数等,类似于C语言中的 printf 函数。这里我们使用 Println 函数来打印字符串,也就是( )里面使用""包裹的部分。

注意,Println 函数打印完成后会自动换行,ln是 line 的缩写。

点号.是Go语言运算符的一种,这里表示调用 fmt 包中的 Println 函数。

另外,代码fmt.Println("Hello World!")的结尾,不需要使用;来作为结束符,Go 编译器会自动帮我们添加,当然,在这里加上;也是可以的。

到这里,相信大家已经知道如何创建一个简单的Go语言程序了,赶快动手试试吧!下一节将为大家演示,如何运行我们所编写的Go语言程序。

Go语言程序的编译和运行

Go语言是编译型的静态语言(和C语言一样),所以在运行Go语言程序之前,先要将其编译成二进制的可执行文件。

可以通过Go语言提供的go build或者go run命令对Go语言程序进行编译:

  • go build命令可以将Go语言程序代码编译成二进制的可执行文件,但是需要我们手动运行该二进制文件;
  • go run命令则更加方便,它会在编译后直接运行Go语言程序,编译过程中会产生一个临时文件,但不会生成可执行文件,这个特点很适合用来调试程序。

下面就来演示一下,如何运行我们上一节中编写的Go语言程序。

因为之前我们已经配置好了环境变量,所以可以直接使用 Windows 自带的命令行工具(也叫 CMD 窗口或者命令提示符)来编译Go语言程序。微软后来对命令行工具进行了一次升级,并更名为 Powershell,power 是更加强大的意思。

打开命令行工具的方式多种多样,下面列出了比较常用的两种:

  • 可以在开始菜单中打开命令行工具,然后 cd 到 Go 源文件所在的目录。
  • 也可以在 Go 源文件所在目录的空白处按住 Shift 键并单击鼠标右键,然后在弹出菜单中选择“在此处打开命令行窗口”或者“在此处打开 Powershell 窗口”,这样会自动 cd 到 Go 源文件所在的目录,如下图所示。这种方式更加方便,推荐大家使用。

提示:cd 是命令行工具的一个命令,用来改变当前所在的目录,是 change directory 的缩写。

img
Win7 下选择“在此处打开命令窗口”

img
Win10 下选择“在此处打开 Powershell 窗口”

go build 命令

go build命令用来启动编译,它可以将Go语言程序与相关依赖编译成一个可执行文件,其语法格式如下。

go build fileName

其中 fileName 为所需要的参数,可以是一个或者多个 Go 源文件名(当有多个参数时需要使用空格将两个相邻的参数隔开),也可以省略不写。

使用 go build 命令进行编译时,不同参数的执行结果也是不同的。

1) 当参数不为空时

如果 fileName 为同一 main 包下的所有源文件名(可能有一个或者多个),编译器将生成一个与第一个 fileName 同名的可执行文件(如执行go build abc.go def.go ...会生成一个 abc.exe 文件);如果 fileName 为非 main 包下的源文件名,编译器将只对该包进行语法检查,不生成可执行文件。

2) 当参数为空时

如果当前目录下存在 main 包,则会生成一个与当前目录名同名的“目录名.exe”可执行文件(如在 hello 目录中执行go build命令时,会生成 hello.exe 文件);如果不存在 main 包,则只对当前目录下的程序源码进行语法检查,不会生成可执行文件。

使用go build命令对我们上一节编写的程序进行编译,运行结果如下所示:

D:\code> go build .\demo.go
D:\code> .\demo.exe
Hello World!

其中D:\code>对应的是当前目录,也就是 D 盘下的 code 文件夹,它是命令行工具自动添加的,不属于编译命令的一部分。

第 1 行go build命令后面的参数中,.\表示当前目录。在Windows 系统中,当前目录使用.\表示;在类 Unix 系统(例如 Linux、MacOS 等)中,当前目录使用./表示。

注意,这里的go build命令中.\可以省略不写,不会影响编译。

另外,go build命令只有在执行出错的情况下才会有返回信息,执行成功的话是没有返回信息的,但是会在当前目录生成一个与 main 包文件同名的 .exe 可执行文件,如下图所示。

img

第 2 行中的.\demo.exe表示执行当前目录下的 demo.exe 程序。

第 3 行则是 demo.exe 程序的运行结果。

go run 命令

除了使用go build命令外,Go语言还为我们提供了go run命令,go run命令将编译和执行指令合二为一,会在编译之后立即执行Go语言程序,但是不会生成可执行文件。

go run命令的语法格式如下:

go run fileName

其中 fileName 为所需要的参数,参数必须是同一 main 包下的所有源文件名,并且不能为空。

使用go run命令对我们上一节编写的程序进行编译,运行结果如下所示:

D:\code> go run demo.go
Hello World!

可以看到第 1 行的go run命令执行后,直接在第 2 行输出了程序的运行结果。

除了本节中所讲的,go build命令和go run命令还有很多其他的编译方法,我们将在后面为大家详细介绍。

Goland 2019下载和安装(带破解补丁和汉化包)

工欲善其事必先利其器,命令行工具虽然能够满足我们一些基本操作的需求,但实际工作中怎么能没有一款趁手的开发工具呢?

学习Go语言同样如此,一个强大的集成开发环境(IDE)能够大大提高我们的开发效率,目前市面上比较流行的有下面这几种:

  • GoLand:由 JetBrains 公司开发的一个新的商业 IDE;
  • LiteIDE X:一款简单、开源、跨平台的Go语言 IDE;
  • 第三方插件:Sublime Text、VS Code 等编辑器都有Go语言的相关插件。

本节我们主要介绍 Windows 系统上 Goland 的安装和配置过程。

Goland 简介

Goland 是由 JetBrains 公司开发的一个新的商业 IDE,旨在为 Go 开发者提供的一个符合人体工程学的新的商业 IDE。Goland 整合了 IntelliJ 平台(一个用于 java 语言开发的集成环境,也可用于其他开发语言),提供了针对Go语言的编码辅助和工具集成。

Goland 下载和安装

大家可以从 Goland 的官网下载对应版本的 Goland 的安装包:(教程中使用的版本是 2019.2.3)

  • 官网下载地址:https://www.jetbrains.com/go/download/other.html;
  • **(推荐)**直接复制本条链接到迅雷中下载:https://download.jetbrains.com/go/goland-2019.2.3.exe。

Goland 官网下载页面
Goland 官网的下载页面

下载完成后直接双击运行安装包。

Goland 安装包
运行下载好的安装包

首先看到的是一个欢迎页面,不用管它,直接点击 Next 就行。

欢迎页面
直接点击 Next 即可

自定义安装目录,默认是安装在 C 盘,大家可以自行选择合适的位置安装,选择好后点击 Next 进入下一步操作。

自定义安装目录
点击 Browse 即可修改安装目录

下面是一些安装选项,选项中的一些信息大家可以根据自己的需要勾选,确认无误后点击 Next。

安装选项
安装选项

在开始菜单中为 Goland 的快捷方式选择一个文件夹,这一步我们不需要修改,直接点击 Install。

选择一个开始菜单中的文件夹
选择一个开始菜单中的文件夹

开始安装,等待安装完成即可。

安装中...

安装完成,勾选 Run Goland 并点击 Finish,结束安装并启动 Goland。

安装完成
结束安装,并启动Goland

运行 Goland 并激活

第一次启动 Goland 时会提示我们导入设置信息,这里我们选择第二项,不导入设置信息。

导入设置信息
导入设置信息

点击 OK 后发现需要激活,免费试用的话也仅有 30 天的时间,这就尴尬了!别急下面就来告诉大家怎么破解它。首先点击 Exit 关闭正在运行的 Goland 程序。

激活界面
激活界面

然后,大家可以【点击这里】下载相关的破解补丁,如下所示:

下载破解补丁

将下载好的文件解压,并将破解补丁“jetbrains-agent.jar”复制到 Goland 安装目录下的 bin 目录中,放到这里没有什么特殊的意义,只是为了防止误删。

将破解补丁复制到bin目录
将破解补丁复制到 bin 目录

在 Goland 安装目录的 bin 目录下找到“goland.exe.vmoptions”和“goland64.exe.vmoptions”两个文件。用记事本将它们打开,并分别在两个文件的最后面追加“-javaagent:Goland 的安装目录\bin\jetbrains-agent.jar”,注意将路径修改成你电脑上 Goland 的安装目录,例如 “-javaagent:D:\anzhuang\GoLand\bin\jetbrains-agent.jar”,修改完成后记得保存。

修改配置文件
修改配置文件

运行 Goland 进入激活界面,选择“Activate”,激活方式选择“Activation code”使用激活码激活,并将激活码粘贴到下面,点击 OK 即可。激活码可以在下载的破解补丁中找到。

复制激活码

复制激活码

到这里 Goland 已经成功激活了,在开始敲代码之前需要先创建一个项目,选择“New Project”新建一个项目。

img

选择一个目录作为项目的根目录,并选择合适的Go语言版本,点击“Create”完成创建。

创建新项目
创建新项目

项目创建完成,终于可以开始敲代码了。

img

Goland 汉化

汉化在这里的意思是中文化,因为 Goland 的菜单都是英文的,这对于刚刚接触它的新手来说会造成一定的困扰,那要怎么实现中文呢?这里需要用到一些特殊的方法。

首先关闭 Goland ,然后在我们下载的破解补丁中找到“resources_cn.jar”,并将它复制到 Goland 安装目录下的 lib 目录中,如下图所示:

复制汉化补丁
复制汉化补丁

然后,同样在 lib 目录中找到“resources_en.jar”文件,它是 Goland 内置的一个英文补丁,这里需要将它删除或者重命名,建议大家选择重命名的方式,因为想要恢复英文的话还需要用到它。

重命名 resources_en.jar
重命名 resources_en.jar

运行 Goland ,你会发现 Goland 中的菜单已经变成我们熟悉的中文了。

汉化后的效果

汉化后的效果

提示:汉化补丁并没有实现百分之百的汉化,仍然存在部分英文。

Goland入门指南(使用Goland创建并运行项目)

上一节详细介绍了 Goland 的安装和破解,本节我们来介绍一下怎么使用 Goland 来创建并运行一个项目。

创建项目

首先,在“文件”菜单中找到“New”,并在下一级菜单中选择“Project”来创建一个新项目。

新建项目
在菜单中选择新建项目

为项目选择一个目录(尽量选择空目录),并点击“Create”完成创建。

img

创建项目

编辑运行/调试配置

每次创建项目之后,我们都需要对 Goland 进行一些配置,在 Goland 的右上方找到“Add Configuration”并单击。

点击 Add Configuration
点击 Add Configuration

在弹出的窗口中点击“+”,并在下拉菜单中选择“Go Build”。

编辑配置信息
编辑配置信息

点击“Go Build”之后,在窗口中填写对应的信息,如下所示。

img

上图中有以下几点需要注意:

  • 名称:为本条配置信息的名称,可以自定义,也可以使用系统默认的值;
  • Run kind:这里需要设置为“Directory”;
  • Directory:用来设置 main 包所在的目录,不能为空;
  • Output directory:用来设置编译后生成的可执行文件的存放目录,可以为空,为空时默认不生成可执行文件;
  • Working directory:用来设置程序的运行目录,可以与“Directory”的设置相同,但是不能为空。

提示:除了上面提到的几点外,其余的配置项使用系统的默认值即可,无需修改。

编写并运行代码

将 Goland 配置好后,就可以在项目文件夹下编写代码了。首先新建一个 Go 源文件,在项目文件夹上点击右键,然后在弹出的菜单中找到“新建”,并在下一级菜单中选择“Go File”,最后在弹出框中输入文件名(红框处)并选择“Empty file”,无误后按“Enter”键进行确认。

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Go语言工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Go语言全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Golang知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Go)
img

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

-blog.csdnimg.cn/img_convert/fd6df80691228d48de0540f2a327a305.gif)

创建项目

编辑运行/调试配置

每次创建项目之后,我们都需要对 Goland 进行一些配置,在 Goland 的右上方找到“Add Configuration”并单击。

点击 Add Configuration
点击 Add Configuration

在弹出的窗口中点击“+”,并在下拉菜单中选择“Go Build”。

编辑配置信息
编辑配置信息

点击“Go Build”之后,在窗口中填写对应的信息,如下所示。

img

上图中有以下几点需要注意:

  • 名称:为本条配置信息的名称,可以自定义,也可以使用系统默认的值;
  • Run kind:这里需要设置为“Directory”;
  • Directory:用来设置 main 包所在的目录,不能为空;
  • Output directory:用来设置编译后生成的可执行文件的存放目录,可以为空,为空时默认不生成可执行文件;
  • Working directory:用来设置程序的运行目录,可以与“Directory”的设置相同,但是不能为空。

提示:除了上面提到的几点外,其余的配置项使用系统的默认值即可,无需修改。

编写并运行代码

将 Goland 配置好后,就可以在项目文件夹下编写代码了。首先新建一个 Go 源文件,在项目文件夹上点击右键,然后在弹出的菜单中找到“新建”,并在下一级菜单中选择“Go File”,最后在弹出框中输入文件名(红框处)并选择“Empty file”,无误后按“Enter”键进行确认。

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Go语言工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Go语言全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-zHZV0aM1-1712924118927)]
[外链图片转存中…(img-l3CGwCss-1712924118928)]
[外链图片转存中…(img-RxoKpry3-1712924118928)]
[外链图片转存中…(img-aPVGzEp4-1712924118929)]
[外链图片转存中…(img-K8hIoIMz-1712924118929)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Golang知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Go)
[外链图片转存中…(img-T54WVHLc-1712924118930)]

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/2301_82257383/article/details/137693480

智能推荐

linux4.15之后国家码使用(CRDA)_linux5 regdb-程序员宅基地

文章浏览阅读2.7k次。(1)需要开启以下宏:CONFIG_CFG80211_REQUIRE_SIGNED_REGDB=yCONFIG_CFG80211_USE_KERNEL_REGDB_KEYS=y(2)下载regulatory.dbandregulatory.db.p7s. Place them into/lib/firmware/directory.Index of /pub/software/network/wireless-regdb/https://mirrors.edge.kernel...._linux5 regdb

sqlite创建索引最佳实践-程序员宅基地

文章浏览阅读2.2k次。创建索引可以使 SQLite 数据库更快地执行查询,但是也会增加插入、更新和删除的时间。因此,在创建索引时,应该考虑查询和修改操作的平衡。在创建索引时,有几点可以遵循的最佳实践:使用 WHERE 子句中经常出现的列创建索引。使用列上的唯一约束或主键创建唯一索引。这有助于防止重复的值。避免使用过于长的索引,因为这会增加存储和维护索引的成本。如果表中有大量的 INSERT、UPDAT..._sqlite 创建索引

%d输出float类型,%f输出int类型_int型能用%f输出吗-程序员宅基地

文章浏览阅读3.6k次,点赞3次,收藏22次。// 输出格式与类型不一致,输出结果实际上与存储有关 // 1.int以%f格式输出,结果一般为0.000000 // 2.long long 类型的很大的数,用printf(“%f”)打印出来可能为一个小数; // 3.double、float以%d格式输出(输出时,float会转化为double存储形式;%d取低32位) // (1)结果一般为绝对值很大的数(当浮点数不能精确表示时,低32位不为0) // _int型能用%f输出吗

目标检测标注数据的检查和可视化_目标标注信息统计可视化-程序员宅基地

文章浏览阅读4.6k次。标注数据是一件十分枯燥的重复性工作。在标注数据时,有时因为数据量大,类别多,会出现错标、误标的情况,这时就需要对标注数据进行检查并且修改。_目标标注信息统计可视化

flutter 项目实践2_jj2d.top-程序员宅基地

文章浏览阅读2.5k次。本片文章来自与我自己的有道云笔记 要看图片请点击链接文档:Day 4_3 项目实践2.md链接:http://note.youdao.com/noteshare?id=f28e3058fea4d26f1b32bdc21f1a220c&sub=A3757D0FAF4C4BC29A8CF2E6F1C8DBD6上次做了什么我们把框架搭好了IndexedStack 分开了基础的页面制作了简单的首页 读取json文件 然后展示我们的首页基本就算制作完了然后我们想做一些展示home_cont_jj2d.top

elasticsearch-head连接问题_elasticsearch 开启xpack head如何连接-程序员宅基地

文章浏览阅读2.8k次。场景:最近打算使用elasticsearch做日志搜索,使用elasticsearch-head作为一个图形化界面查看index、type、document信息。elasticsearch 7.14.1mobz/elasticsearch-head:5地址:https://github.com/mobz/elasticsearch-head看完这个readme文档后,计划使用docker方式进行部署。1.更改elasticsearch.yml文件,包括xpack等配置,示例如下:_elasticsearch 开启xpack head如何连接

随便推点

6-1单链表逆转(C语言)_给定存储若干整数的单链表,实现单链表逆转c-程序员宅基地

文章浏览阅读571次。6-1单链表逆转(C语言)本题要求实现一个函数,将给定的单链表逆转。函数接口定义List Reverse( List L );其中List结构定义如下:typedef struct Node *PtrToNode;struct Node { ElementType Data; /* 存储结点数据 */ PtrToNode Next; /* 指向下一个结点的指针 */};typedef PtrToNode List; /* 定义单链表类型 */L是给定单链表,函数R_给定存储若干整数的单链表,实现单链表逆转c

关于GEE导出数据时 含空值的栅格图像_selfmask-程序员宅基地

文章浏览阅读3.9k次,点赞8次,收藏25次。GEE提供的卫星数据大多数是有丢失的,若不加操作直接导出为tif,matlab读出来的矩阵该是空值的都是nan,然而arcgis并不能识别空值为nodata,导致制图非常难受。加上unmask函数可以让空值变为某个数字,这里设为-9999,方便后续处理。selfMask()则可以将图像的负值都判定为空。Export.image.toDrive({ image: xinjiang_CH4_anomaly.unmask(-9999), description: 'xinjiang_ch4_anom_selfmask

jmeter聚个报告怎么看qps_jmeter 聚合报告参数详解及TPS 解析-程序员宅基地

文章浏览阅读2.1k次。1、获得TPS插件https://www.cnblogs.com/beginner-boy/p/7806220.html 参见,已保存百度云盘2、添加后,记得使用调度器——每秒50个并发,持续60秒,观察TPS3、TPS,执行一次事务(包括请求、请求服务器、等待服务器返回等等,比如一个TPS事务,可能触发3个QPS请求)PS:一秒钟处理的事务数。TPS值越大,一秒钟处理的事务数就越多,说明处理速..._jmeter查看qps

浙大 PAT 甲级 1077 Kuchiguse_pat甲级可以用翻译吗-程序员宅基地

文章浏览阅读135次。读题目真是要笑死我了…太不正经了。很简单的20分~将题意翻译成代码即可。#include<iostream>#include<string>using namespace std;int main(){ int N; scanf("%d", &N); getchar(); string base; getlin..._pat甲级可以用翻译吗

centos7 svn服务器搭建_svn co authentication方法-程序员宅基地

文章浏览阅读1.5k次。基于centos7 的svn服务器配置_svn co authentication方法

capilot激活时遇到Sign in failed: Error: network error_sign in failed. reason: could not log in with devi-程序员宅基地

文章浏览阅读922次。capilot激活遇到问题,Sign in failed: Error: network error_sign in failed. reason: could not log in with device flow on cocopilot.org:

推荐文章

热门文章

相关标签