社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
《Go并发编程实战》和在线免费教程《Go命令教程》的作者郝林
项目源码:
gcc2p项目—— https://github.com/hyper-carrot/goc2p
《Go 并发编程实战》的示例项目。
注意:在Go语言中,我们对程序实体的访问权限控制只能通过它们的名字来实现。
一、go的优劣势
二、go的安装
http://golang.org/dl/ 下载最新的二进制档案包
https://www.golangtc.com/download --------国内下载地址
(结合操作系统类型和位数--32 64)
linux下安装:
解压后 在 bin 目录下 执行 ./go version 查看安装包版本
将 解压文件移动到 /usr/local 下即可。--方便统一管理
linux下环境变量配置:
export GOROOT=/usr/local/go
#go安装的目录
export GOPATh=~/golib:~/goproject
#go语言的工作区的集合
export GOBIN=~/gobin
#存放go程序的可执行文件的目录
export PATH=$PATH:$GOROOT/bin:$GOBIN
#path 中加入go语言命令 和go的可执行文件目录
export GOROOT=/usr/local/go export GOPATh=~/golib:~/goproject export GOBIN=~/gobin export PATH=$PATH:$GOROOT/bin:$GOBIN |
验证配置结果:
go version
#查看go 版本信息
三、常用概念
3.1工作区和GOPATH
工作区是放置go源码文件的目录。
一般情况下,go源码文件都需要存放在工作区中。
但是对于【命令源码文件】来说,这不是必须的。
3.1.1工作区目录
/home/hypermind/golib
src/
用于存放源码文件
以代码包为组织形式
pkg/
用于存放归档文件(名称以.a为后缀的文件)
所有归档文件都会被存放到该目录下的平台相关目录 中,同样以代码包为组织形式。
bin/
用于存放当前工作区中的go程序的可执行文件
两种情况下 bin目录会无效:
1、当环境变量GOBIN已经有效设置时,该目录会无意义
2、当GOPATH的值中包含多个工作区的路径时,必须设置GOBIN,否则无法成功安装GO程序的可执行文件
3.1.2 平台相关目录
两个隐含的go语言环境变量:GOOS和GOARCH
GOOS:计算机操作系统
GOARCH:计算架构
以 $GOOS_$GOARCH 为命名方式,如:linux_amd64
3.2源码文件的分类和含义
3.2.1 GO源码文件
名称以.go 为后缀,内容以Go 语言代码组织的文件
多个Go 源码文件是需要用代码包组织起来的。
3.2.2 源码文件的分类和含义
分三类:
命令源码文件、库源码文件、测试源码文件
命令源码文件:
声明自己属于main代码包、包含无参数声明和结果声明的main函数
被安装后,相应的可执行文件会被存放到 GOBIN 指向的目录或<当前工作区目录> /bin 下
命令源码文件是Go程序的入口,但不建议把程序都写在一个文件中。
注意:同一个代码包中强烈不建议直接包含多个命令源码文件。
库源码文件:
不具备命令源码文件特征的文件。
测试源码文件:
1、不具备命令源码文件的那两个特征的文件
2、名称以 _test.go 为后缀
3、其中至少有一个函数的名称以Test 或 Benchmark 为前缀
并且,该函数接受一个 类型 为 *testing.T 或 *testing.B 的参数 ——指针类型
示例: func TestFind(t *testing.T){ //代码 } 基准测试函数、性能测试函数 |
3.3代码包相关知识
3.3.1 代码包的作用
编译和归档Go程序的最基本单位
代码划分、集结和依赖的有效组织形式,也是权限控制的辅助手段
3.3.2 代码包的规则
一个代码包实际上就是一个由导入路径代表的目录
导入路径即<工作区 目录> /src 或 <工作区目录> /pkg/<平台相关目录>之下的某子路径
3.3.3 代码包的声明
每个源码文件必须声明其所属的代码包
同一个代码包中的所有源码文件声明的代码包应该是相同的。
3.3.4 代码包的导入和声明的区别
3.3.4.1 代码包声明:
当前代码文件的目录名称
package pkgtool
#
3.3.4.2 代码包的导入:
1、 import ("包1","包2")
2、带别名的导入
iimport str "Strings"
3、本地化导入
import . "strings" ——》Hasprefx("abc","a")
不需要再用包名称去调用。
4、仅仅初始化
import _ 'strings" ==》仅执行代码包中的初始化函数,而不调用任何实体
3.3.5 代码包的初始化
1、代码包的初始化函数即: 无参数声明和结果声明的init 函数
init函数可以被声明在任何文件中,且可以有多个。
2、init函数的正时机——单元代码包内
对所有全局变量进行求职——》执行所有init函数。
注意: 一次导入多个包,所有被导入代码包的init 函数 没有先后执行顺序。不能假设谁先被执行。
依赖导入时,最先被依赖的包 最先执行。
A——》导入B——》导入C A导入B,B导入了C 在执行init的时候, Cinit最先被执行,接着是Binit 最后是 C init
每个init 函数只会 被执行一次。
四、go命令
4.1 go run
用于运行命令源码文件(只能接受一个命令源码文件以及若干个库源码文件作为文件参数)
4.1.2 ds 命令 和 pds 命令
4.1.3 命令案例演示
在 goc2p/src/helper/ds/showds.go 目录下 执行 : go run showds.go #会打印当前目录树。
4.1.3 go run 常用标记的使用
-a: 强制编译先关代码,无论代码是否已经是最新编译。
-n: 打印编译过程中所需运行的命令,单是不真正执行他们
-pn:并行编译,其中n为并行的数量。
n 为逻辑CPU的数量
-v :列出被编译的代码包的名称。
-a -v :列出所有被编译的代码包的名称。
-work: 显示编译时创建的临时工作目录的路径,并且不删除它。(默认的 go run 编译会删除临时目录)
-x:打印编译过程中所需运行的命令
-n:打印编译过程中所需的命令,但并不执行。
-x : 打印编译过程中所需的命令,并执行他们。
4.2 go build 和 go install
4.2.1 go build 简介
用于编译源码文件或代码包。
编译非命令源码文件不会产生任何结果文件。
编译命令源码文件会在该命令的执行目录中生成一个可执行文件。
go build 不加参数时,会试图把当前目录作为代码包并编译:
go build 以代码包的导入路径为参数时,代码包以及其依赖会被编译。
-a 标记: 所有涉及到的代码包都会被重新编译。
不加入-a标记,则只会编译归档文件不是最新的代码包。
go build 以若干源码文件为参数,只有这些文件会被编译。————列出的源码文件不全,这样容易报错。
4.2.2 go install
用于编译并安装代码包或源码文件
安装代码包会在当前工作区的pkg/<平台相关目录>下生成归档文件
安装命令源码文件会在当前工作区的bn目录或$GOBIN目录下生成可执行文件。
go install 不加参数时,会试图把当前目录作为代码包并安装。
go install 代码包的导入路径为参数,会把导入路径的代码包以及其依赖的代码包 会被安装————就可以在其他代码中导入此代码包了
go install 以命令源码文件及相关库源码文件作为参数,只有这些文件会被编译并安装
4.3 go get
用于从远程代码仓库(如 github)上下载并安装代码包。 (gitLlab Gogs)
受支持的代码版本控制系统有: git 、 Mercurial(hg) 、 SVN、Bazaar
指定的代码包会被下载到 $GOPATH 中包含的第一个工作区的src 目录中。
4.3.1 go get 案例
go get -x github.com/go-errors/errors
# -x 选项 可以看到 go get的 详细执行情况。 go get 调用的是 git clone 命令
echo $GOPATH 可以查看工作区目录情况。 会被下载到第一个工作区目录的 src 目录下。
4.3.2 go get 常用标记的使用(1)
-x: 显示 go get 进度
-d: 只执行下载动作,而不执行安装动作。
-fix: 在下载代码包后先执行修正动作,而后再进行编译和安装
-u:利用网络来更新已有的代码包及其依赖包
4.3.3 go get 标记案例
五、基本数据类型
5.1 go语言-程序实体和关键字
任何Go语言源码文件都由若干个程序实体组成的。在Go语言中,变量、常量、函数、结构体和接口被统称为“程序实体”,而它们的名字被统称为“标识符”。
标识符可以是任何Unicode编码可以表示的字母字符、数字以及下划线“_”。不过,首字母不能是数字或下划线。
注意:在Go语言中,我们对程序实体的访问权限控制只能通过它们的名字来实现。
名字首字母为大写的程序实体可以被任何代码包中的代码访问到。而名字首字母为小写的程序实体则只能被同一个代码包中的代码所访问。
go 关键字:
package main // 代码包声明语句。
// 代码包导入语句。 import ( "fmt" // 导入代码包fmt。 )
// main函数。 func main() {
// 打印函数调用语句。用于打印输出信息。 fmt.Println("Go语言编程实战") } |
5.2 Go语言-变量和常量
var 变量名 类型 = 值
const 常量名 类型 = 值
可以声明和赋值分开 。
var num2, num3 int = 2, 3 // 注释:平行赋值
var ( // 注释:多行赋值 num4 int = 4 num5 int = 5 )
注意:在实践中发现,常量可以不用大写, 变量可以不用显式的声明数据类型。但是一般按照标准的语法来。 并且如果声明变量而未使用会编译错误。
// 变量声明和赋值语句,由关键字var、变量名num、变量类型uint64、特殊标记=,以及值10组成。 var num uint64 = 65535 | // 短变量声明语句,由变量名size、特殊标记:=,以及值(需要你来填写)组成。 size := (64) |
5.3 go 整数类型的命名和宽度
Go语言-整数类型的命名和宽度 Go语言的整数类型一共有10个。
其中计算架构相关的整数类型有两个,即:有符号的整数类型int和无符号的整数类型uint。
顺便提一下,有符号的整数类型会使用最高位的比特(bit)表示整数的正负。显然,这会对它能表示的整数的范围有一定的损耗(使其缩小)。而无符号的整数类型会使用所有的比特位来表示数值。如此类型的值均为正数。这也是用“无符号的”来形容它们的原因。
言归正传,为什么说这两个整数类型是计算架构相关的呢?这是因为,在不同的计算架构的计算机之上,它们体现的宽度是不同的。宽度即指存储一个某类型的值所需要的空间。空间的单位可以是比特,也可以是字节(byte)。请看下表。 我想你应该已经能够悟到它们的对应关系了。
除了这两个计算架构相关的整数类型之外,还有8个可以显式表达自身宽度的整数类型。如下表所示。 可以看到,这8个整数类型的宽度已经表现在它们的名称中了 |
5.4 Go语言类型-整数类型值的表示法
Go语言-整数类型值的表示法
我们已经知道了每个整数类型的宽度,那么它们的宽度意味着什么呢?下面这张表已有所描述。
如上所示,类型int8的数值表示范围为[-128,127],而类型uint16的数值表示范围为[0,65535],等等。
以我们的常识知道,在数学中整数一般是以10进制来表示的,而在计算机中整数则必是以2进制来表示和存储的。当然,在计算机科学领域,整数的表示形式还包括了8进制和16进制。下面我们就来说说怎样这几种表示法在Go语言中表示整数。
最显而易见的是10进制表示法。如果我们要在声明一个名为num1的int类型变量时给它赋予12这个值,那么这样书写即可:
var num1 int = 12
这是最容易被我们理解的方式了。不过,如果我们要分别以8进制和16进制为变量num1赋值,那么需要:
num1 = 014 // 用“0”作为前缀以表明这是8进制表示法。
或:
num1 = 0xC // 用“0x”作为前缀以表明这是16进制表示法。
(注意,为已声明的变量赋值,无需再在等号左边加入关键字var和变量类型)
5.5 Go语言-浮点数类型
浮点数类型有两个,即float32和float64。你可能已经想到,存储这两个类型的值的空间分别需要4个字节和8个字节。
浮点数类型的值一般由整数部分、小数点“.”和小数部分组成。其中,整数部分和小数部分均由10进制表示法表示。不过还有另一种表示方法。那就是在其中加入指数部分。指数部分由“E”或“e”以及一个带正负号的10进制数组成。比如,3.7E-2表示浮点数0.037。又比如,3.7E+1表示浮点数37。
有时候,浮点数类型值的表示也可以被简化。比如,37.0可以被简化为37。又比如,0.037可以被简化为.037。
有一点需要注意,在Go语言里,浮点数的相关部分只能由10进制表示法表示,而不能由8进制表示法
5.6 Go语言-复数类型
复数类型同样有两个,即complex64和complex128。存储这两个类型的值的空间分别需要8个字节和16个字节。实际上,complex64类型的值会由两个float32类型的值分别表示复数的实数部分和虚数部分。而complex128类型的值会由两个float64类型的值分别表示复数的实数部分和虚数部分。
复数类型的值一般由浮点数表示的实数部分、加号“+”、浮点数表示的虚数部分,以及小写字母“i”组成。比如,3.7E+1 + 5.98E-2i。正因为复数类型的值由两个浮点数类型值组成,所以其表示法的规则自然需遵从浮点数类型的值表示法的相关规则。我们就不在这里赘述了。请你通过练习题来回顾一下相关表示法的规则。
5.7 byte与rune
byte与rune类型有一个共性,即:它们都属于别名类型。byte是uint8的别名类型,而rune则是int32的别名类型。
byte类型的值需用8个比特位表示,其表示法与uint8类型无异。因此我们就不再这里赘述了。我们下面重点说说rune类型。
一个rune类型的值即可表示一个Unicode字符。Unicode是一个可以表示世界范围内的绝大部分字符的编码规范。关于它的详细信息,大家可以参看其官网(http://unicode.org/)上的文档,或在Google上搜索。用于代表Unicode字符的编码值也被称为Unicode代码点。一个Unicode代码点通常由“U+”和一个以十六进制表示法表示的整数表示。例如,英文字母“A”的Unicode代码点为“U+0041”。
rune类型的值需要由单引号“'”包裹。例如,'A'或'郝'。这种表示方法一目了然。不过,我们还可以用另外几种形式表示rune类型值。请看下表。
大家需要根据实际情况选用上述表示法。在一般情况下,第一种表示法更为通用。因为它是最直观的。不过,在以其他几种方法表示的内容出现在屏幕上的时候,大家也要明白其含义。
另外,在rune类型值的表示中支持几种特殊的字符序列,即:转义符。它们由“\”和一个单个英文字符组成。如下表所示。
5.8 Go语言-字符串类型
顾名思义,一个字符串类型的值可以代表一个字符序列。这些字符必须是被Unicode编码规范支持的。虽然从表象上来说是字符序列,但是在底层,一个字符串值却是由若干个字节来表现和存储的。一个字符串(也可以说字符序列)会被Go语言用Unicode编码规范中的UTF-8编码格式编码为字节数组。
注意,我们在一个字符串值或者一个字符串类型的变量之上应用Go语言的内置函数len将会得到代表它的那个字节数组的长度。这可能与我们看到的表象是不同的。
字符串的表示法有两种,即:原生表示法和解释型表示法。若用原生表示法,需用反引号“`”把字符序列包裹起来。若用解释型表示法,则需用双引号“"”包裹字符序列。
二者的区别是,前者表示的值是所见即所得的(除了回车符)。在那对反引号之间的内容就是该字符串值本身。而后者所表示的值中的转义符会起作用并在程序编译期间被转义。所以,如此表示的字符串值的实际值可能会与我们看到的表象不相同。
最后要注意,字符串值是不可变的。也就是说,我们一旦创建了一个此类型的值,就不可能再对它本身做任何修改。
两种声明:
1、反引号 ··
在那对反引号之间的内容就是该字符串值本身。 所见即所得
2、双引号
所表示的值中的转义符会起作用并在程序编译期间被转义。 可以保函转移符号,被转义
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!