前言
本章是go语言实战第二章,比较不错的是,这章直接以代码实现了一个程序,体现了go语言的特性,而非连篇累牍的文字说明
程序架构
如图为程序架构,是一个用三个goroutine执行搜索的查询程序,
主routine 从数据源获取数据进行搜索,并将结果给结果routine
搜索routine执行搜索,并把结果返回主routine,把结束通知给结果routine
结果routine等待到结果并且通知主routine
示例程序
这里列举了一个go程序,不同于单个go文件生成的可执行文件,如下图,它是具有一定的目录结构的
data中包含了数据源
matchers的rss中包含了数据源的切换请求逻辑
search中是匹配的业务逻辑
最外层的main是程序的入口
main.go
01 package main
02
03 import (
04 "log" //标准库导入只需要给出包名
05 "os"
06
07 _ "github.com/goinaction/code/chapter2/sample/matchers" //下划线让编译器接受对包做初始化操作,但是并不使用包里的标识符
08 "github.com/goinaction/code/chapter2/sample/search"
09 ) //导入所需包,
10
11 // init 在 main 之前调用
12 func init() {
13 // 将日志输出到标准输出
14 log.SetOutput(os.Stdout)
15 }
16
17 // main 是整个程序的入口
18 func main() {
19 // 使用特定的项做搜索,search就是包名,run是其中的函数名
20 search.Run("president")
21 }
search.go
// 注册用于搜索的匹配器的映射
var matchers = make(map[string]Matcher)
变量定义在函数外,则是包级变量
首字母大写的可以被包外直接访问,小写的不可以
由于map是引用类型,这里的make函数是用来构造map的,string是键,Matcher是值
不初始化时,初始值为0,空字符串,nil,false这些
run.go
// 获取需要搜索的数据源列表
feeds, err := RetrieveFeeds()
if err != nil {
log.Fatal(err)
}
这里用函数返回了一个切片和一个错误值,切片里包含数据源。如果错误了,fatal会输出到console,并终止程序
这种返回多个返回值的函数,在错误时不能引用另一个值,否则会引起程序崩溃
这里 := 意思是 声明一个变量并赋值的简写
// 创建一个无缓冲的通道,接收匹配后的结果
results := make(chan *Result)
channel是一种引用类型,通道实现的就是一组带类型的值,用于不同routine传递值,同时routine自带同步机制,保证了数据安全
基础命令
go build x.go
这个命令会编译出一个可执行文件,并且根据不同操作系统会编译出不同格式
目前支持系统如下
darwin
freebsd
linux
windows
android
dragonfly
netbsd
openbsd
plan9
solaris
处理器架构
arm
arm64
386
amd64
ppc64
ppc64le
mips64
mips64le
s390x
也可以直接生成指定的可执行文件,只需要指定GOOS,GOARCH两个参数,相当于临时修改环境变量
GOOS=linux GOARCH=amd64 go build flysnow.org/hello
go clean
# go clean 可以清除编译出的文件,避免提交到git库里
go run a.go
# go run 可以直接运行go文件,等效于go build 后运行
go env
# 查看当前编译环境
go install
# 作用类似go build,区别在于可以把库文件放到对应位置
go get
# get需要的依赖,第三方包,这样方便之后使用
go fmt
# 格式化代码,这里的格式化是指排版,不是删除那个格式化
go vet
#可以帮助排查代码中的问题
go test
# 运行测试文件
# 1.写有单元测试的文件名,必须以_test.go结尾。
# 2.测试文件要包含若干个测试函数。
# 3.这些测试函数要以Test为前缀,还要接收一个*testing.T类型的参数。