第一篇:兄弟連區塊鏈培訓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個工作日內聯系你,一經查實,本站將立刻刪除涉嫌侵權內容。