练习 8.1: 修改clock2来支持传入参数作为端口号,然后写一个clockwall的程序,这个程序可以同时与多个clock服务器通信,从多服务器中读取时间,并且在一个表格中一次显示所有服务传回的结果,类似于你在某些办公室里看到的时钟墙.如果你有地理学上分布式的服务器可以用的话,让这些服务器跑在不同的机器上面:或者在同一台机器上跑多个不同的实例,这些实例监听不同的端口,假装自己在不同的时区.像下面这样: $ TZ=US/Eastern ./clock2 -port 8010 & $ TZ=As…
练习 8.9: 编写一个du工具,每隔一段时间将root目录下的目录大小计算并显示出来. package main import ( // "filepath" "flag" "fmt" "io/ioutil" "os" "path" "sync" "time" ) /* 练习 8.9: 编写一个du工具,每隔一段时间将root目录下的目录大小计算…
最简单的回声服务器: package main import ( "io" "net" "log" ) func main() { listener, err := net.Listen("tcp", ":8040") if err != nil { log.Fatal(err) } for { conn, err := listener.Accept() if err != nil { log.Print…
1.解决包级变量的依赖顺序,然后按照包级变量声明出现的顺序依次初始化 2.包中含有多个.go源文件,它们将按照发给编译器的顺序进行初始化 3.init初始化函数,在每个文件中的init初始化函数,在程序开始执行时按照它们声明的顺序被自动调用 4.每个包在解决依赖的前提下,以导入声明的顺序初始化,每个包只会被初始化一次,在main函数执行之前,所有依赖的包都已经完成初始化工作了 5.一个数字中含二进制1bit的个数算法,统计出一个int型数值中比特值为1的比特个数 &是二进制“与”运算,参加运算的…
1.每个包都有一个全局唯一的导入路径 2.按照惯例,一个包的名字和包的导入路径的最后一个字段相同 练习 2.2: 写一个通用的单位转换程序,用类似cf程序的方式从命令行读取参数,如果缺省的话则是从标准输入读取参数,然后做类似Celsius和Fahrenheit的单位转换,长度单位可以对应英尺和米,重量单位可以对应磅和公斤等. 1.创建目录mkdir /home/ubuntu/gobook/src/unitconv/ 2.目录下创建包源文件unitconv.go 包文件unitconv.go pa…
go语言圣经-并发获取多个URL 1.GO最新奇的特性就是对并发编程的支持,goroutine和channel 2.goroutine是一种函数的并发执行方式,而channel是用来在goroutine之间进行参数传递 go function则表示创建一个新的goroutine,并在这个新的goroutine中执行这个函数. 3.make函数创建了一个传递string类型参数的channel 4.io.Copy把响应的Body内容拷贝到ioutil.Discard输出流中,扔到一个垃圾桶 5.g…
Go语言圣经-web服务 1.Web服务程序,标准库里的方法已经帮我们完成了大量工作 2.main函数将所有发送到/路径下的请求和handler函数关联起来,/开头的请求其实就是所有发送到当前站点上的请求,服务监听8000端口 3.发送到这个服务的“请求”是一个http.Request类型的对象,这个对象中包含了请求中的一系列相关字段,其中就包括我们需要的URL. 4.用标准输出流fmt.Fprintf,把其发送到响应中,直接写到了http.ResponseWriter中 5.两个请求处理函数,…
https://books.studygolang.com/gopl-zh/ go语言圣经 1.Go语言有时候被描述为“C类似语言”,或者是“21世纪的C语言”. 2.Go语言中和并发编程相关的特性是全新的也是有效的,同时对数据抽象和面向对象编程的支持也很灵活.Go语言同时还集成了自动垃圾收集技术用于更好地管理内存. 3.Go语言尤其适合编写网络服务相关基础设施,同时也适合开发一些工具软件和系统软件. 4.Go语言有足够的类型系统以避免动态语言中那些粗心的类型错误,但是,Go语言的类型系统相比传…
Go语言圣经-接口1.接口类型是对其它类型行为的抽象和概括2.Go语言中接口类型的独特之处在于它是满足隐式实现的3.Go语言中还存在着另外一种类型:接口类型.接口类型是一种抽象的类型4.一个类型可以自由的使用另一个满足相同接口的类型来进行替换被称作可替换性(LSP里氏替换) 练习 7.1: 使用来自ByteCounter的思路,实现一个针对对单词和行数的计数器.你会发现bufio.ScanWords非常的有用. package main import ( "bufio" "f…
Go语言圣经-Panic异常1.当panic异常发生时,程序会中断运行,并立即执行在该goroutine中被延迟的函数(defer 机制)2.不是所有的panic异常都来自运行时,直接调用内置的panic函数也会引发panic异常:panic函数接受任何值作为参数.3.由于panic会引起程序的崩溃,因此panic一般用于严重错误,如程序内部的逻辑不一致,对于大部分漏洞,我们应该使用Go提供的错误机制,而不是panic4.为了方便诊断问题,runtime包允许输出堆栈信息 Go语言圣经-Reco…
Go语言圣经-匿名函数1.拥有函数名的函数只能在包级语法块中被声明,通过函数字面量(function literal),我们可绕过这一限制,在任何表达式中表示一个函数值2.通过这种方式定义的函数可以访问完整的词法环境(lexical environment),这意味着在函数中定义的内部函数可以引用该函数的变量3.函数值不仅仅是一串代码,还记录了状态,意味着匿名函数和父函数中,存在变量引用,函数值属于引用类型和函数值不可比较的原因.Go使用闭包(closures)技术实现函数值,Go程序员也把函数…
Go语言圣经-错误 1.panic异常.panic是来自被调函数的信号,表示发生了某个已知的bug 2.任何进行I/O操作的函数都会面临出现错误的可能 3.错误是软件包API和应用程序用户界面的一个重要组成部分,程序运行失败仅被认为是几个预期的结果之一 4.那些将运行失败看作是预期结果的函数,它们会返回一个额外的返回值,通常是最后一个,来传递错误信息 5.用户需要了解更多的错误信息.因此,额外的返回值不再是简单的布尔类型,而是error类型 6.内置的error是接口类型,error类型可能是n…
Go语言圣经-函数多返回值1.在Go中,一个函数可以返回多个值2.许多标准库中的函数返回2个值,一个是期望得到的返回值,另一个是函数出错时的错误信息3.如果一个函数将所有的返回值都显示的变量名,那么该函数的return语句可以省略操作数.这称之为bare return. 练习 5.5: 实现countWordsAndImages.(参考练习4.9如何分词) package main import ( "fmt" "golang.org/x/net/html" &qu…
Go语言圣经-文本和HTML模板 练习 4.14: 创建一个web服务器,查询一次GitHub,然后生成BUG报告.里程碑和对应的用户信息. 1.查看下文档godoc net/http |grep HandleFunc func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) 2.godoc fmt|grep Fprintf func Fprintf(w io.Writer, format string, a…
Go语言圣经-结构体 1.结构体是一种聚合的数据类型,是由零个或多个任意类型的值聚合成的实体 2.通常一行对应一个结构体成员,成员的名字在前类型在后,不过如果相邻的成员类型如果相同的话可以被合并到一行 3.如果结构体成员名字是以大写字母开头的,那么该成员就是导出的:这是Go语言导出规则决定的.一个结构体可能同时包含导出和未导出的成员. 4.一个命名为S的结构体类型将不能再包含S类型的成员:因为一个聚合的值不能包含它自身,S类型的结构体可以包含*S指针类型的成员 我们使用一个二叉树来实现一个插入排…
go语言圣经-复合数据类型 1.以不同的方式组合基本类型可以构造出来的复合数据类型 2.四种类型——数组.slice.map和结构体 3.数组是由同构的元素组成——每个数组元素都是完全相同的类型——结构体则是由异构的元素组成的 4.slice和map则是动态的数据结构,它们将根据需要动态增长 go语言圣经-数组 1.因为数组的长度是固定的,因此在Go语言中很少直接使用数组 2.数组字面值语法用一组值来初始化数组 3.数组的长度是数组类型的一个组成部分 4.Printf函数的%x副词参数,它用于指…
go语言圣经-复数 1.我们把形如a+bi(a,b均为实数)的数称为复数,其中a称为实部,b称为虚部,i称为虚数单位.两种精度的复数类型:complex64和complex128,分别对应float32和float64两种浮点数精度 2.complex函数用于构建复数,real和imag函数分别返回复数的实部和虚部 go语言圣经-布尔型 1.布尔值可以和&&(AND)和||(OR)操作符结合,并且有短路行为 2.&&的优先级比||高 go语言圣经-字符串 1.一个字符串是一…
go语言圣经-作用域 1.一个声明语句将程序中的实体和一个名字关联,比如一个函数或一个变量 2.一个变量的生命周期是指程序运行时变量存在的有效时间段;声明语句的作用域对应的是一个源代码的文本区域,它是一个编译时的属性 3.句法块是由花括弧所包含;我们可以把块(block)的概念推广到包括其他声明的群组,这些声明在代码中并未显式地使用花括号包裹起来,我们称之为词法块. 4.全局作用域 包级语法域 源文件级的作用域 局部作用域 函数级的作用域 5.从最内层的词法域向全局的作用域查找.内部的会覆盖外部…
go语言圣经-声明1.四种类型的声明语句:var.const.type和func,分别对应变量.常量.类型和函数实体对象的声明2.包一级声明语句声明的名字可在整个包对应的每个源文件中访问,局部声明的名字就只能在函数内部很小的范围被访问 go语言圣经-变量1.var 变量名字 类型 = 表达式2.零值初始化机制,数值类型零值是0,布尔类型变量对应的零值是false,字符串类型对应的零值是空字符串,接口或引用类型(包括slice.指针.map.chan和函数)变量对应的零值是nil3.同时声明一组变…
1.go test命令是一个按照约定和组织进行测试的程序2.竞争检查器 go run -race 附带一个运行期对共享变量访问工具的test,出现WARNING: DATA RACE 说明有数据竞争3.理想情况下是应该避免掉多余的工作的,称为duplicate suppression(重复抑制/避免) 4.设计并发,不重复,无阻塞 cache 1.并发: go func(){}()直接启动新的goroutine来实现 2.并发安全:使用sync.Mutex 互斥锁来实现 3.无阻塞:get之前锁…
练习 8.4: 修改reverb2服务器,在每一个连接中使用sync.WaitGroup来计数活跃的echo goroutine.当计数减为零时,关闭TCP连接的写入,像练习8.3中一样.验证一下你的修改版netcat3客户端会一直等待所有的并发“喊叫”完成,即使是在标准输入流已经关闭的情况下. 重点:等待所有的goroutine执行完成后再关闭TCP连接 package main import ( "bufio" "fmt" "log" &qu…
两种: crawler.go package main import ( "fmt" "links" //"log" "os" ) func main() { worklist := make(chan []string) // Start with the command-line arguments. go func() { worklist <- os.Args[1:] }() // Crawl the web c…
1.编译 go build hello.go 2.go get gopl.io/ch1/helloworld 命令,就会从网上获取代码,并放到对应目录中 下载的代码会放在$GOPATH/src/gopl.io/ch1/helloworld目录 3.Go语言不需要在语句或者声明的末尾添加分号,除非一行上有多条语句. 4.Go语言在代码格式上采取了很强硬的态度.gofmt工具把代码格式化为标准格式 gofmt -w hello.go 重写回源文件 5.goimports,可以根据代码需要, 自动地添…
1.一个字符串是一个不可改变的字节序列2.文本字符串通常被解释为采用UTF8编码的Unicode码点(rune)序列3.内置的len函数可以返回一个字符串中的字节数目4.第i个字节并不一定是字符串的第i个字符,因为对于非ASCII字符的UTF8编码会要两个或多个字节5.字符串操作基于原始字符串字节6.字符串面值方式编写,只要将一系列字节序列包含在双引号内即可,解释字符串,其中的相关的转义字符将被替换;反引号括起来,支持换行,非解释字符串7.每个符号都分配一个唯一的Unicode码点,Unicod…
Goroutines和线程: 1.动态栈: 1)线程都有一个固定大小的内存块(一般会是2MB)来做栈 2)一个goroutine会以一个很小的栈开始其生命周期,一般只需要2KB,不是固定的:栈的大小会根据需要动态地伸缩 2.Goroutine调度: 1)线程是使用硬件定时器进行的调度,速度慢 2)Go是使用的自己的调度器,在线程的基础上调度,不需要进入内核的上下文 3.GOMAXPROCS环境变量可以确定启动多少线程同时执行go代码4.goroutine没有可以被程序员获取到的身份(id)的概念…
package main import( "fmt" "sync" ) var balance int func Deposit(amount int) { balance = balance + amount } func Balance() int { return balance } /* 问题: 1.在Alice运行期间 balance = balance + amount 这一步运算可能会被Bob中间挤占 2.当运行到balance + amount的时候…
练习 8.8: 使用select来改造8.3节中的echo服务器,为其增加超时,这样服务器可以在客户端10秒中没有任何喊话时自动断开连接. reverb3.go package main import ( "bufio" "fmt" "log" "net" "strings" "sync" "time" ) func main() { listener, err :=…
练习 8.3: 在netcat3例子中,conn虽然是一个interface类型的值,但是其底层真实类型是*net.TCPConn,代表一个TCP连接.一个TCP连接有读和写两个部分,可以使用CloseRead和CloseWrite方法分别关闭它们.修改netcat3的主goroutine代码,只关闭网络连接中写的部分,这样的话后台goroutine可以在标准输入被关闭后继续打印从reverb1服务器传回的数据.(要在reverb2服务器也完成同样的功能是比较困难的:参考练习 8.4.) 1.n…
练习 7.3: 为在gopl.io/ch4/treesort (§4.4)的*tree类型实现一个String方法去展示tree类型的值序列. package main import( "fmt" "bytes" ) func main(){ //定义数组 arr:=[...]int{6,2,1,3,4,5} var t *tree for i:=0;i<len(arr);i++{ t=add(t,arr[i]) } //t1:=Sort(arr[:],t)…
练习 6.3: (*IntSet).UnionWith会用|操作符计算两个集合的交集,我们再为IntSet实现另外的几个函数IntersectWith(交集:元素在A集合B集合均出现),DifferenceWith(差集:元素出现在A集合,未出现在B集合),SymmetricDifference(并差集:元素出现在A但没有出现在B,或者出现在B没有出现在A). *练习6.4: 实现一个Elems方法,返回集合中的所有元素,用于做一些range之类的遍历操作. 练习 6.2: 定义一个变参方法(*…