第一篇:兄弟连区块链培训Go语言爬虫编写
兄弟连区块链培训Go语言爬虫编写
兄弟连教育建议,用户在考虑培训周期时要切实结合自身目前所掌握的区块链知识的多少、培训的目的是简单的认知提升还是借此高薪就业等等。兄弟连Go全栈与区块链培训课程设置为5个半月共计22周的学习时长,由浅入深进行讲解,助力于小白用户向区块链工程师的转型。
课程体系设计架构包括了区块链的基础语言Go语言、区块链后端技术体系、区块链公链、区块链分布式应用开发等内容讲解,以及到最后的面试指导和项目实战。课程由清华微软谷歌名师团队精心打造,历时半年时间共同研发而出。
上次用Scala写了个爬虫。最近在闲工夫之时,学习Go语言,便用Go移植了那个用Scala写的爬虫,代码如下: package main
import(“fmt”
“io/ioutil”
“net/http”
“regexp”)
var(ptnIndexItem
= regexp.MustCompile(`(.+)`)
ptnContentRough = regexp.MustCompile(`(?s).*
ptnBrTag
= regexp.MustCompile(`
`)
ptnHTMLTag
= regexp.MustCompile(`(?s)?.*?>`)
ptnSpace
= regexp.MustCompile(`(^s+)|()`))
func Get(url string)(content string, statusCode int){
resp, err1 := http.Get(url)
if err1!= nil {
statusCode =-100
return
}
defer resp.Body.Close()
data, err2 := ioutil.ReadAll(resp.Body)
if err2!= nil {
statusCode =-200
return
}
statusCode = resp.StatusCode
content = string(data)
return }
type IndexItem struct {
url
string
title string }
func findIndex(content string)(index []IndexItem, err error){
matches := ptnIndexItem.FindAllStringSubmatch(content, 10000)
index = make([]IndexItem, len(matches))
for i, item := range matches {
index[i] = IndexItem
}
return }
func readContent(url string)(content string){
raw, statusCode := Get(url)
if statusCode!= 200 {
fmt.Print(“Fail to get the raw data from”, url, “n”)
return
}
match := ptnContentRough.FindStringSubmatch(raw)
if match!= nil {
content = match[1]
} else {
return
}
content = ptnBrTag.ReplaceAllString(content, “rn”)
content = ptnHTMLTag.ReplaceAllString(content, “")
content = ptnSpace.ReplaceAllString(content, ”“)
return }
func main(){
fmt.Println(`Get index...`)
s, statusCode := Get
if statusCode!= 200 {
return
}
index, _ := findIndex(s)
fmt.Println(`Get contents and write to file...`)
for _, item := range index {
fmt.Printf(”Get content %s from %s and write to file.n“, item.title, item.url)
fileName := fmt.Sprintf(”%s.txt“, item.title)
content := readContent(item.url)
ioutil.WriteFile(fileName, []byte(content), 0644)
fmt.Printf(”Finish writing to %s.n", fileName)
} }
代码行数比Scala版的有一定增加,主要原因有以下几方面原因: golang 重视代码书写规范,或者说代码格式,很多地方写法比较固定,甚至比较麻烦。比如就算是if判断为真后的执行语句只有一句话,按照代码规范,也要写出带大括号的三行,而在Scala和很多其他语言中,一行就行; golang 的strings包和regexp包提供的方法并不特别好用,特别是和Scala相比,使用起来感觉Scala的正则和字符串处理要舒服的多; scala版的爬虫里面用到了Scala标准库中的实用类和方法,它们虽然不是语法组成,但用起来感觉像是语法糖,这里很多方法和函数式编程有关,golang的函数式编程还没有去仔细学习。
当然golang版的爬虫也有一个优势,就是编译速度很快,执行速度在现在的写法里面体现不出优势;golang的特性goroutine在这里没有用到,这段代码今后会不断改进。
第二篇:兄弟连区块链培训教程Go语言区块链共识算法分布式一致性算法Raft
兄弟连Go语言区块链培训教程区块链共识算法(1)分布式一致性算法Raft
很多人喜欢Go语言,其实是因为Go语言有其独特的语言属性在支撑着其在编程语言界的发展,今天兄弟连Go语言+区块链培训老师给大家介绍一下关于Go语言区块链共识算法(1)分布式一致性算法Raft,下面我们一起来看一下吧。
# 分布式一致性算法Raft
Paxos自1990年提出以后,相当长时间内几乎已成为分布式一致性算法的代名词。
但因其难以理解和实现,目前知名实现仅有Chubby、Zookeeper、libpaxos几种,其中Zookeeper使用的ZAB对Paxos做了大量改进。
为此,2013年斯坦福的Diego Ongaro、John Ousterhout,提出了新的更易理解和实现的一致性算法,即Raft。
Raft和Paxos均只要保证n/2+1节点正常,即可服务。相比Paxos,其优势即为易于理解和实现。
Raf将算法分解为:选择领导者、日志复制、安全性等几个子问题。
它的流程即为:开始时在集群中选举出Leader负责日志复制的管理,Leader接收来自客户端的事务请求(日志),并将它们复制给集群中的其他节点,然后通知集群中的其他节点提交日志,Leader负责保证其他节点与它的日志同步。
当Leader宕机时,集群其他节点重新发起选举,选出的新的Leader。
### 角色
Raft涉及三种角色:
* Leader:即领导者,负责处理来自客户端的请求,管理日志复制、以及与Follower保持心跳以维持其领导者地位。
* Follower:即追随者,负责响应来自Leader的日志复制请求,响应来自Candidate的选举请求。初始时所有节点均为Follower。
* Candidate:即候选者,负责发起选举投票,Raft启动后或Leader宕机后,一个节点从Follower转为Candidate,并发起选举,选举成功后,由Candidate转为Leader。
如下为Raft角色状态转换图:
(1 Raft)
### Term(任期)
在Raft中使用了Term(任期)的概念,一轮选举即为一个Term(任期),一个Term中仅能产生一个Leader。
Term使用连续递增的编号表示,初始时所有Follower的Term均为1。
其中某个Follower定时器到期触发选举,其状态转换为Candidate,此时Term加1变为2,然后开始选举,有如下几种可能:
/ 3
*
1、如果当前Term为2的任期内没有选举出Leader或出现异常,Term递增为3,并开始新一轮选举。
*
2、此轮Term为2的任期内选举出Leader后,如果Leader宕机,此时其他Follower转为Candidate,Term递增,并发起新的选举。
*
3、如果Leader或Candidate发现自己的Term比其他Follower小时,Leader或Candidate转为Follower,Term递增。
*
4、如果Follower发现自己的Term比其他Follower小时,更新Term与其他Follower保持一致。
每次Term递增都将发生新一轮选举,在Raft正常运行过程中,所有节点Term均一致。
如果节点不发生故障,一个Term(任期)会一直保持下去,当某节点收到的请求中Term比当前Term小时拒绝请求。
### 选举
初始时所有节点均为Follower,且定时器时间不同。
某个节点定时器触发选举后,Term递增,该节点由Follower转换为Candidate,向其他节点发起投票请求(RequestVote RPC)。
有如下几种可能:
*
1、收到过半数节点(n/2+1)投票,由Candidate转换为Leader,向其他节点发送心跳以维持领导者地位。
*
2、如果收到其他节点发送的AppendEntries RPC请求,且该节点Term大于当前节点Term,即发现了新的有效领导者,转换为Follower,否则保持Candidate拒绝该请求。
*
3、选举超时,Term递增,重新发起选举。
每轮Term期间,每个节点均只能投票1次,如果多个Candidate均没有接收到过半数投票,则每个Candidate Term递增,重启定时器并重新发起选举。
因定时器时间随机,因此不会多次出现多个Candidate同时发起投票的问题。
### 日志复制
保证节点的一致性,就要保证所有节点都按顺序执行相同的操作序列,日志复制目的即为此。
*
1、Leader接收到客户端事务请求(即日志),先将日志追加到本地Log中,并通过AppendEntries RPC复制给其他Follower。
*
2、Follower接收到日志后,追加到本地Log中,并向Leader发送ACK消息。
*
3、Leader收到过半数Follower的ACK消息后,将日志置为已提交并正式提交日志,通知客户端,并发送AppendEntries RPC请求通知Follower提交日志。
### 安全性
/ 3
*
1、每个Term期间只能选举一个Leader。
*
2、Leader不会删除或覆盖已有日志条目,只会追加。
*
3、如果相同索引位置的日志条目Term任期号相同,那么认为从头到这个索引位置均相同。
*
4、如果某个日志条目在某任期内提交,那么这个日志条目必然出现在更大的Term任期号的所有领导中。
*
5、如果Leader在某索引位置的日志条目已提交,那么其他节点相同索引位置不会提交不同的日志条目。
### RequestVote RPC和AppendEntries RPC
Raft中节点通信使用两种RPC,即RequestVote RPC和AppendEntries RPC:
RequestVote RPC:即请求投票,由Candidate在选举期间发起。
AppendEntries RPC:即附加条目RPC,由Leader发起,用于日志复制和心跳机制。
### 后记
本文总结的Raft,及之前文章中的Paxos、2PC、3PC均为基于非拜占庭容错的分布式一致性算法,即除考虑消息的丢失、超时、乱序,但不考虑消息被篡改。
从下个文章起,将总结基于拜占庭容错的分布式一致性算法,该算法在比特币、以太坊、及其他区块链产品中广泛使用。
/ 3
第三篇:黑马程序员C语言教程: CC++培训专家-编写高效C语言的四大绝招
传智播客C/C++培训专家:编写高效C语言的四大绝招
C语言是很多程序猿的入门语言,而且C语言也是一门用不过时的语言。编写高效简洁的C语言代码,是许多软件工程师追求的目标。今天传智播客C/C++培训专家针对编程工作中的一些体会和经验给大家做相关的阐述。
第一招:以空间换时间
计算机程序中最大的矛盾是空间和时间的矛盾,那么,从这个角度出发逆向思维来考虑程序的效率问题,我们就有了解决问题的第1招--以空间换时间。比如说字符串的赋值: 方法A:通常的办法 #define LEN 32 char string1 [LEN];memset(string1, 0, LEN);strcpy(string1, “This is a example!”);方法B:
const char string2[LEN] =“This is a example!”;char * cp;cp = string2;
从上面的例子可以看出,A和B的效率是不能比的。在同样的存储空间下,B直接使用指针就可以操作了,而A需要调用两个字符函数才能完成。B的缺点在于灵活性没有A好。在需要频繁更改一个字符串内容的时候,A具有更好的灵活性;如果采用方法B,则需要预存许多字符串,虽然占用了大量的内存,但是获得了程序执行的高效率。
第二招:数学方法解决问题
现在我们演绎高效C语言编写的第二招--采用数学方法来解决问题。数学是计算机之母,没有数学的依据和基础,就没有计算机的发展,所以在编写程序的时候,采用一些数学方法会对程序的执行效率有数量级的提高。举例如下,求 1~100的和。方法C: int I , j;for(I = 1;I<=100;I ++){ j += I;} 方法D int I;I =(100 *(1+100))/ 2;
这个例子是我印象最深的一个数学用例,是我的计算机启蒙老师考我的。当时我只有小学三年级,可惜我当时不知道用公式 N×(N+1)
/ 2 来解决这个问题。方法E循环了100次才解决问题,也就是说最少用了100个赋值,100个判断,200个加法(I和j);而方法F仅仅用了1个加法,1 次乘法,1次除法。效果自然不言而喻。所以,现在我在编程序的时候,更多的是动脑筋找规律,最大限度地发挥数学的威力来提高程序运行的效率。
第三招:使用位操作
实现高效的C语言编写的第三招——使用位操作。减少除法和取模的运算。在计算机程序中数据的位是可以操作的最小数据单位,理论上可以用“位运算”来完成所有的运算和操作。一般的位操作是用来控制硬件的,或者做数据变换使用,但是,灵活的位操作可以有效地提高程序运行的效率。举例如下: 方法E int I,J;I = 257 /8;J = 456 % 32;方法F int I,J;I = 257 >>3;J = 456-(456 >> 4 << 4);在字面上好像F比E麻烦了好多,但是,仔细查看产生的汇编代码就会明白,方法E调用了基本的取模函数和除法函数,既有函数调用,还有很多汇编代码和寄存器参与运算;而方法F则仅仅是几句相关的汇编,代码更简洁,效率更高。当然,由于编译器的不同,可能效率的差距不大,但是,以我目前遇到的MS C ,ARM C 来看,效率的差距还是不小。相关汇编代码就不在这里列举了。
运用这招需要注意的是,因为CPU的不同而产生的问题。比如说,在PC上用这招编写的程序,并在PC上调试通过,在移植到一个16位机平台上的时候,可能会产生代码隐患。所以只有在一定技术进阶的基础下才可以使用这招。用移位实现乘除法运算
a=a*4;
b=b/4;
可以改为:
a=a<<2;
b=b>>2;
说明:
除2 = 右移1位 乘2 = 左移1位
除4 = 右移2位 乘4 = 左移2位
除8 = 右移3位 乘8 = 左移3位
......通常如果需要乘以或除以2的n次方,都可以用移位的方法代替。大部分的C编译器,用移位的方法得到代码比调用乘除法子程序生成的代码效率高。
第四招:汇编嵌入
高效C语言编程的必杀技,第四招——嵌入汇编。“在熟悉汇编语言的人眼里,C语言编写的程序都是垃圾”。这种说法虽然偏激了一些,但是却有它的道理。汇编语言是效率最高的计算机语言,但是,不可能靠着它来写一个操作系统吧?所以,为了获得程序的高效率,我们只好采用变通的方法--嵌入汇编,混合编程。举例如下,将数组一赋值给数组二,要求每一字节都相符。char string1[1024],string2[1024];方法G int i;for(i =0;i<1024;i++)*(string2 + i)= *(string1 + i)方法H #ifdef _PC_ int I;for(I =0;I<1024;I++)*(string2 + I)= *(string1 + I);#else #ifdef _ARM_ __asm
{ MOV R0,string1 MOV R1,string2 MOV R2,#0 loop: LDMIA R0!, [R3-R11] STMIA R1!, [R3-R11] ADD R2,R2,#8 CMP R2, #400 BNE loop } #endif 方法G是最常见的方法,使用了1024次循环;方法H则根据平台不同做了区分,在ARM平台下,用嵌入汇编仅用128次循环就完成了同样的操作。这里有朋友会说,为什么不用标准的内存拷贝函数呢?这是因为在源数据里可能含有数据为0的字节,这样的话,标准库函数会提前结束而不会完成我们要求的操作。这个例程典型应用于LCD数据的拷贝过程。根据不同的CPU,熟练使用相应的嵌入汇编,可以大大提高程序执行的效率。
虽然是必杀技,但是如果轻易使用会付出惨重的代价。这是因为,使用了嵌入汇编,便限制了程序的可移植性,使程序在不同平台移植的过程中,卧虎藏龙,险象环生!同时该招数也与现代软件工程的思想相违背,只有在迫不得已的情况下才可以采用。
今天分享到这里,大家有遇到什么问题可以向“传智播客C/C++培训专家”留言哦!
文档为doc格式
声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:645879355@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。