《Go并发编程实战》读书笔记-初识Go语言
作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
在讲解怎样用Go语言之前,我们先介绍Go语言的特性,基础概念和标准命令。
一.语言特性
我们可以用几个关键词或短语来概括Go语言的主要特性。
1>.开放源代码
这显示来Go作者开放的态度以及营造语言生态的决心。顺便说一句,Go本事就是用Go语言编写的。
2>.静态类型和编译类型
在Go中,每个变量或常量都必须在声明时指定类型,且不可改变。另外,程序必须通过编译生成归档文件或可执行文件,而后才能被使用或执行。不过,其语法非常简洁,就像一些解释型脚本语言那样,易学易用。
3>.跨平台
这主要是指跨计算架构和操作系统。目前,它已经支持对大部分主流的计算架构和操作系统,并且这个范围还在不断的扩大。只要下载与之对应的Go语言安装包,并且经过简单的安装和设置,就可以使Go就绪了。除此之外,在编写Go语言程序的过程中,我们几乎感觉不到平台的差异。
4>.自动垃圾回收
程序在允运行过程中的垃圾回收工作一般由Go运行时系统全权负责。不过,Go也允许我们对此项工作进行干预。
5>.原生的并发编程
拥有自己的并发编程模型,其主要组成本分由goroutime(也可以称为Go例程)和channel(也可称为通道)。另外,还拥有一个特殊的关键字go。
6>.完善的构建工具
它自带来很多强大的命令和工具,通过他们,可以轻松地完成Go程序的获取,编译,测试,安装,运行,分析等一系列工作。
7>.多编程范式
Go支持函数式编程。函数类型为第一等类型,可以方便地传递和赋值。此外,它还支持面向对象编程,由接口类型与实现类型的概念,但用于嵌入替值。此外,它还支持面向对象编程,有接口类型与实现类型的概念,但用嵌入替代来集成。
8>.代码风格强制统一
Go安装包中有自己的代码格式化工具,可以用来统一程序的编码风格。
9>.高效的编程和运行
Go简洁,直接的语法使我们可以快速编写程序。加之它强大的运行时系统,程序可以充分利用计算环境飞快运行。
10>.丰富的标准库
Go是通用的编程语言,其标准库中有很多开箱即用的API。尤其是编写诸如系统级程序,Web程序和分布式程序时,我们几乎无需依赖第三方库。
二.安装和设置
安装Go相当简单,只要你的操作系统被Go语言支持即可。Go语言官方网站放出的每一个版本都会有主流平台的二进制安装包以及源码包,你可以自行选择对应的文件下载。Go的下载地址为:https://golang.google.cn/dl/(国内下载地址)和https://golang.org/dl/(国外下载地址,需VPN)。
如上图所示,我们从下载地址中挑选了“go1.11.4.darwin-amd64.tar.gz”文件并下载。注意,这个文件的名称中有两个关键词,一个是“darwin”,一个是“adm64”。前者标示该文件对应的操作系统种类,其他的同类词有“linux”,“freebsd”,“windows”等。或者标示该文件对应的计算架构种类,其中“adm64”表示64位的计算架构,另一个是386,表示32位的计算架构。实际上,这里的计算架构和操作系统可以统称为Go的计算平台或者计算环境。
解压该文件时会得到一个名为go的文件夹,其中包含所有的Go语言相关文件。该文件夹下还有很多文件夹和文件,下面简要说明其中主要文件夹的功用。如果你是Linux用户或者是window用户的话可参考我之前的笔记:初探GO语言。
bogon:~ yinzhengjie$ sudo mkdir /yinzhengjie
Password:
bogon:~ yinzhengjie$
bogon:~ yinzhengjie$ sudo chown yinzhengjie /yinzhengjie/
bogon:~ yinzhengjie$
bogon:~ yinzhengjie$ ls -ld /yinzhengjie/
drwxr-xr-x yinzhengjie wheel : /yinzhengjie/
bogon:~ yinzhengjie$
bogon:~ yinzhengjie$ mkdir /yinzhengjie/softwares/ #我习惯性将数据都存放到该目录下,因此我们需要创建出来它!
bogon:~ yinzhengjie$
bogon:~ yinzhengjie$ tar -zxf go1.11.4.darwin-amd64.tar.gz -C /yinzhengjie/softwares/
bogon:~ yinzhengjie$
bogon:~ yinzhengjie$ cd /yinzhengjie/softwares/go/
bogon:go yinzhengjie$ pwd
/yinzhengjie/softwares/go
bogon:go yinzhengjie$
bogon:go yinzhengjie$ ls -l
total
-rw-r--r-- yinzhengjie wheel : AUTHORS
-rw-r--r-- yinzhengjie wheel : CONTRIBUTING.md
-rw-r--r-- yinzhengjie wheel : CONTRIBUTORS
-rw-r--r-- yinzhengjie wheel : LICENSE
-rw-r--r-- yinzhengjie wheel : PATENTS
-rw-r--r-- yinzhengjie wheel : README.md
-rw-r--r-- yinzhengjie wheel : VERSION
drwxr-xr-x yinzhengjie wheel : api #用于存放依照Go版本顺序的API增量列表文件。这里所说的API包含公开的变量,常量,函数等。这些API增量列表文件用于Go语言API检查。
drwxr-xr-x yinzhengjie wheel : bin #用于存放祝哟啊的标准命令文件,包括go,godoc和gofmt。
drwxr-xr-x yinzhengjie wheel : doc #用于存放标准库的HTML格式的程序文档。我们可以通过godoc命令启动一个Web程序展现这些文档。
-rw-r--r-- yinzhengjie wheel : favicon.ico
drwxr-xr-x yinzhengjie wheel : lib #用于存放一些特殊的库文件。
drwxr-xr-x yinzhengjie wheel : misc #用于存放一些辅助类的说明和工具。
drwxr-xr-x yinzhengjie wheel : pkg #用于存放安装Go标准库的所有归档文件。注意,你会发现其中有名称为“darwin_amd64”的文件夹,我们成为平台相关目录。可以看到,这类文件夹的名称由对应的操作系统和计算架构的名称组合而成。通过“go install”命令,Go程序(这里是标准库中的程序)会被编译程成平台相关的归档文件存放到其中。另外,“pkg/tool/darwin_amd64”文件夹存放了使用Go制作软件时用到的很多强大的命令和工具。
-rw-r--r-- yinzhengjie wheel : robots.txt
drwxr-xr-x yinzhengjie wheel : src #用于存放Go本身,Go标准工具以及标准库的所有源码文件。深入探究Go,就考它了。
drwxr-xr-x yinzhengjie wheel : test #存放用来测试和验证Go本身的所有相关文件。
bogon:go yinzhengjie$
现在,你已经大致了解了go文件夹中的目录结构及其用途。我们需要把这个目录放在一个适当的位置,在Linux操作系统,Go官方推荐的目录是“/usr/local”,这也是我们源码安装惯于存放的路径。而我习惯将第三方下载的文件存放在指定的目录中“/yinzhengjie/softwares/”目录下。在这之后,我们需要设置一个环境变量,即:GOROOT。GOROOT的之应该是Go的根目录。这里是“/yinzhengjie/softwares/go”。另外,环境变量中PATH中也应该增加一项,即“$GOROOT/bin”。这样就可以在任意目录使用那几个Go命令了。具体操作如下:
bogon:go yinzhengjie$ pwd
/yinzhengjie/softwares/go
bogon:go yinzhengjie$
bogon:go yinzhengjie$ ls -l
total
-rw-r--r-- yinzhengjie wheel : AUTHORS
-rw-r--r-- yinzhengjie wheel : CONTRIBUTING.md
-rw-r--r-- yinzhengjie wheel : CONTRIBUTORS
-rw-r--r-- yinzhengjie wheel : LICENSE
-rw-r--r-- yinzhengjie wheel : PATENTS
-rw-r--r-- yinzhengjie wheel : README.md
-rw-r--r-- yinzhengjie wheel : VERSION
drwxr-xr-x yinzhengjie wheel : api
drwxr-xr-x yinzhengjie wheel : bin
drwxr-xr-x yinzhengjie wheel : doc
-rw-r--r-- yinzhengjie wheel : favicon.ico
drwxr-xr-x yinzhengjie wheel : lib
drwxr-xr-x yinzhengjie wheel : misc
drwxr-xr-x yinzhengjie wheel : pkg
-rw-r--r-- yinzhengjie wheel : robots.txt
drwxr-xr-x yinzhengjie wheel : src
drwxr-xr-x yinzhengjie wheel : test
bogon:go yinzhengjie$
bogon:go yinzhengjie$
bogon:go yinzhengjie$ sudo vi /etc/profile
Password:
bogon:go yinzhengjie$
bogon:go yinzhengjie$ tail - /etc/profile #编辑系统环境变量的配置文件
#Add by yinzhengjie
GOROOT=/yinzhengjie/softwares/go
export PATH=$PATH:$GOROOT/bin
bogon:go yinzhengjie$
bogon:go yinzhengjie$ source /etc/profile #重新家在配置文件
bogon:go yinzhengjie$
bogon:go yinzhengjie$ go version #查看golang的版本
go version go1.11.4 darwin/amd64
bogon:go yinzhengjie$
bogon:go yinzhengjie$
至此,Go已经安装好了,下面重点了解一下Go中的一些基本概念。
三.工程结构
Go是一门推崇软件工程理念的编程语言,它为开发周期的每个环节都提供了完备的工具和支持。Go 语言高度强调代码和项目的规范和统一,这集中体现在工程结构或者说代码*的细节之处。Go也是一门开放的语言,它本身就是开源软件。更重要的是,它让开发人员很容易通过“go get”命令从公共代码库(比如著名的代码托管网站GitHub)中下载开源代码并使用。这除了得益于Go自带命令的强大之外,还应该归功于Go工程结构的严谨和完善。
1>.工作区
一般情况下,Go源码文件必须放在工作区中。但是对于命令源码文件来说,这不是必需的。工作区其实就是一个对应特定工程的目录,它应包含3个子目录:
1.1>.src目录
用于以代码包的形式组织并保存Go源码文件,这里的代码包与src下子目录一一对应。例如,若一个源码文件被声明属于代码包log,那么它就应当保存在“src/log”目录中。当然,你也可以把Go源码文件直接放在src目录下,但这样的Go源码文件就只能被声明属于main代码包了。除非用于临时测试或演示,一般还是建议把Go源码文件存入特定的代码包中。
1.2>.pkg目录
用于存放通过go install命令安装后的代码包的归档文件。前提是代码包中必需包含Go库源码文件。归档文件是指那些名称以“.a”结尾的文件。该目录与GOROOT目录下的pkg目录功能类似。区别在于,工作区中的pkg目录专门用来存放用户代码的归档文件。编译和安装用户代码的过程一般会以代码包为单位进行。比如log包被编译安装后,将生成一个名为log.a的归档文件,并存放在档期啊你工作区的pkg目录喜爱的平台相关目录中。
1.3>.bin目录
与pkg目录类似,在通过“go install”命令完成安装后,保存由Go命令源码文件生成的可执行文件。在类Unix操作系统下,这个可执行文件一般来说名称与源码文件的主文件名相同。而在windows操作系统下,这个可执行文件的名称则是源码文件主文件名加“.exe”后缀。
注意:这里有必要声明一些Go语言的命令源码和库源码文件的区别。所谓命令源码文件,就是声明属于main代码包并且包含无参数声明和结果声明的main函数的源码文件。这类源码文件是程序的入口,它们可以独立运行(使用“go run”命令),也可以通过“go build”或者“go install”命令得到相应的可执行文件。所谓库源码文件,则是指存在与某个代码包中的普通源码文件。
2>.GOPATH
我们需要将工作区的目录路径添加到环境变量GOPATH中。否则,即使处于同一工作区(事实上,未被加入GOPATH中的目录不用管成为工作区),代码之间也无法通过绝对代码包路径调用。在实际开发环境中,工作区可以只有一个,也可以由多个,这些工作区的目录路径都需要添加到GOPATH中。与GOROOT一样,我们应确保GOPATH一直有效。
注意:GOPATH中不要包含GO语言的根目录,以便将Go语言本身的工作区同用户工作区严格分开。通过Go工具中的代码获取命令“go get”,可以指定项目的代码下载到我们在GOPATH中设定的第一个工作区中,并在其中完成编译和安装。
bogon:go yinzhengjie$ mkdir /yinzhengjie/workspace
bogon:go yinzhengjie$ mkdir /yinzhengjie/workspace/src
bogon:go yinzhengjie$ mkdir /yinzhengjie/workspace/pkg
bogon:go yinzhengjie$ mkdir /yinzhengjie/workspace/bin
bogon:go yinzhengjie$
bogon:go yinzhengjie$ sudo vi /etc/profile
bogon:go yinzhengjie$
bogon:go yinzhengjie$ tail - /etc/profile
#Add GOPATH Path by yinzhengjie
GOPATH=/yinzhengjie/workspace
export PATH=$PATH:$GOPATH
bogon:go yinzhengjie$
bogon:go yinzhengjie$ source /etc/profile
bogon:go yinzhengjie$
bogon:go yinzhengjie$ echo $GOPATH
/yinzhengjie/workspace
bogon:go yinzhengjie$
3>.源码文件
Go 源码文件有3个种类,即命令源码文件,库源码文件和测试源码文件,下面我们详细说明这3类源码文件。
3.1>.命名源码文件
如果一个源码文件被声明属于一个main包,且该文件代码中包含无参数声明和结果声明的main函数,则它是是命令源码文件。命令源码文件可通过“go run”命令直接运行。
3.2>.库源码文件
通常,库源码文件声明的包名会与它直接所属的代码包(目录)名一致,且库源码文件中不包含无参数声明和无结果声明的main函数。
3.3>.测试源码文件
测试源码文件是一种特殊的库文件,可以通过“go test”命令运行当前代码包下的所有测试源码文件。成为测试源码文件的充分必要条件有两个。一个是文件名需要以“_test.go”结尾。另一个是文件中需要至少包含一个名称以Test开头或Benchmark开头,且拥有一个类型为“*testing.T”或“*testing.B”的参数的函数。“*testing.T”和“*testing.B”是两个结构体类型。而“*testing.T”和“*testing.B”则分别为前两者的指针类型。它们分别为前两者的指针类型。它们分别是功能测试和基准测试所需的。
最后插一句,Go代码的文本文件需要以UTF-8编码存储。如果源码文件中出现来非UTF-8编码的字符,那么在运行,编译或安装的时候,Go命令会抛出“illegal UTF-8 squence”错误。
四.标准命令简述
Go本身包含来大量用于处理Go程序的命令和工具。go命令就是其中最常用的一个,它有许多子命令,下面来系统的了解一下吧:
1>.build
用于编译指定的代码包或Go语言源码文件。命令源码文件会被编译成可执行文件,并存放到命令执行的目录或指定目录下。而库源码文件被编译后,则不会在非临时目录中留下任何文件。
2>.clean
用于清除因执行其他go命令而遗留下来的临时目录和文件。
3>.doc
用于显示打印Go语言代码包以及程序实体的文档。
4>.env
用于打印Go语言相关的环境信息。
5>.fix
用于修正指定代码的源码文件中包含的过时语法和代码调用。这使得我们在升级Go语言版本时,可以非常方便地同步升级程序。
6>.fmt
用于格式化指定代码包中的Go源码文件。实际上,它是通过执行“gofmt”命令来实现功能的。
7>.generate
用于识别指定代码中资源文件中的“go:generate”注释,并执行其携带的任意命令。该命令独立于Go语言标准的编译和安装体系。如果你有需要解析的“go:generate”注释,就单独运行它。这个命令非常有用,我产用它自动生成或改动Go源码文件。
8>.get
用于下载,编译并安装指定改动代码包及其依赖包。从我们自己的代码中转站或第三方代码库上自动拉取代码,就全靠它了。
9>.install
用于编译并安装指定的代码包及其依赖包。安装命令源码文件后,代码包所在的工作区目录的bin子目录,或者当前环境变量GOBIN指向的目录中会生成相应的可执行文件。安装源码文件后,会在代码包所在的工作目录的pkg子目录中生成相应的归档文件。
10>.list
用于显示指定代码包的细腻下,它可谓是代码包分析的一大便利工具。利用Go语言标准代码库代码包“text/template”中规定的模版语法,你可以非常灵活的控制输出信息。
11>.run
用于编译并运行指定的代码源码文件。当你想不生成可执行文件而直接运行命令源码文件时,就需要用到它。
12>.test
用于测试指定的代码包,前提是该代码包目录中必须存在测试源代码文件。
13>.tool
用于运行Go语言的特殊工具。
14>.vet
用于检查指定代码包中的Go语言代码,并报告发现可疑代码问题。该命令提供了除编译之外的又一个程序检查方法,可用于找到程序中的潜在错误。
15>.version
用于显示当前安装的Go语言的版本信息以及计算环境。
执行上述命令时,可以通过附加一些额外的标记来定制命令的执行过程。下面是一个比较通用的标记。
-a:
用于强行重新编译所有涉及的Go语言代码包(包括Go语言标准库中的代码包),即使他们已经是最新的了。该标记可以让我们有机会通过改动更底层的代码包做一些实验。
-n:
使命令仅打印其执行过程中用到的所有命令,而不真正执行它们。如果只想查看或验证命令的执行过程,而不想改变任何东西,使用它正合适。
-race:
用于检测并报告指定Go语言程序中存在的数据竞争问题。当用Go语言编写并发程序时,这是很重要的检测手段之一。
-v:
用于打印命令执行过程中涉及的代码包。这一定包括我们指定的目标代码包,并且有时还会包括该代码包直接或间接依赖的那些代码包。这会让你知道哪些代码包被命令处理过了。
-work:
用于打印命令执行时生成和使用的临时工作目录的名字,且命令执行完成后不删除它。这个目录下的文件可能会对你有用,也可以从侧面了解命令的执行过程。如果不添加此标记,那么临时工作目录会在命令执行完毕前删除。
-x:
使命令打印其执行过程中用到的所有命令,同时执行它们。
我们可以把这些标记看作命令的特殊参数,他们都可以添加到命令名称和命令的真正参数中间。用于编译, 安装,运行和测试Go语言代码包或源码文件的命令都支持它们。上面提到了tool这个子命令,它用来运行一些特殊的Go语言工具。直接执行“go tool”命令,可以看到这些特殊工具。它们有的是其他Go标准命令的底层支持,有的规则是可以独当一面的利器。其中有两个工具值得特别介绍一下。
pprof:
用于以交互的方式访问一些性能概要文件。命令将会分析给定的概要文件,并根据要求提供高可读性的输出信息。这个工具可以分析的概要文件包括CPU概要文件,内存概要文件和程序阻塞概要文件。这些包含Go程序运行信息的概要文件,可以通过标准库代码runtime和runtime/pprof中的程序来生成。
trace:
用于读取Go程序踪迹文件,并以图形化的方式展现出来。它能够让我们深入了解Go程序在运行过程中的内部情况。比如,当前进程中堆的大小及使用情况。又比如,程序中的多个goruntime是怎样调度的,以及它们在某个时刻被调度的原因。Go程序踪迹文件可以通过标准代码包“runtime/trace”和“net/http/pprof”中的程序来生成。
上述的两个特殊的工具对Go程序调优非常有用。如果想探究程序运行的过程,或者想让程序跑的更快,更稳定,那么这两个工具是必知必会的。另外,这两个工具都受到“go test”命令的直接支持。因此你可以很方便地把它们融入到程序测试当中。
五.问候程序
/*
#!/usr/bin/env gorun
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
EMAIL:y1053419035@qq.com
*/ package main import (
"bufio"
"fmt"
"os"
) func main() {
//声明并初始化带缓冲带读取器,准备从标准输入读取内容
inputReader := bufio.NewReader(os.Stdin) //给用户一个提示信息
fmt.Println("Please input your name :") //以"\n"为分隔符读取一段内容
input,err := inputReader.ReadString('\n') if err != nil {
fmt.Printf("Found an error : %s\n",err)
}else {
//对input进行切片操作,去掉内容中最后一个字节"\n"
input = input[:len(input)-]
fmt.Printf("Hello, %s!\n",input)
}
}
请记住,学习一门编程语言最直接,最有效的途径就是多实验几次,多修改然后在运行一下看看效果。换句话说,多练习代码是学习编程最有效的途径!