真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

go語言實(shí)現(xiàn)字典 go語言文檔

Go語言基礎(chǔ)語法(一)

本文介紹一些Go語言的基礎(chǔ)語法。

成都創(chuàng)新互聯(lián)公司專注于尚義網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠為您提供尚義營銷型網(wǎng)站建設(shè),尚義網(wǎng)站制作、尚義網(wǎng)頁設(shè)計(jì)、尚義網(wǎng)站官網(wǎng)定制、小程序定制開發(fā)服務(wù),打造尚義網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供尚義網(wǎng)站排名全網(wǎng)營銷落地服務(wù)。

先來看一個(gè)簡單的go語言代碼:

go語言的注釋方法:

代碼執(zhí)行結(jié)果:

下面來進(jìn)一步介紹go的基礎(chǔ)語法。

go語言中格式化輸出可以使用 fmt 和 log 這兩個(gè)標(biāo)準(zhǔn)庫,

常用方法:

示例代碼:

執(zhí)行結(jié)果:

更多格式化方法可以訪問中的fmt包。

log包實(shí)現(xiàn)了簡單的日志服務(wù),也提供了一些格式化輸出的方法。

執(zhí)行結(jié)果:

下面來介紹一下go的數(shù)據(jù)類型

下表列出了go語言的數(shù)據(jù)類型:

int、float、bool、string、數(shù)組和struct屬于值類型,這些類型的變量直接指向存在內(nèi)存中的值;slice、map、chan、pointer等是引用類型,存儲(chǔ)的是一個(gè)地址,這個(gè)地址存儲(chǔ)最終的值。

常量是在程序編譯時(shí)就確定下來的值,程序運(yùn)行時(shí)無法改變。

執(zhí)行結(jié)果:

執(zhí)行結(jié)果:

Go 語言的運(yùn)算符主要包括算術(shù)運(yùn)算符、關(guān)系運(yùn)算符、邏輯運(yùn)算符、位運(yùn)算符、賦值運(yùn)算符以及指針相關(guān)運(yùn)算符。

算術(shù)運(yùn)算符:

關(guān)系運(yùn)算符:

邏輯運(yùn)算符:

位運(yùn)算符:

賦值運(yùn)算符:

指針相關(guān)運(yùn)算符:

下面介紹一下go語言中的if語句和switch語句。另外還有一種控制語句叫select語句,通常與通道聯(lián)用,這里不做介紹。

if語法格式如下:

if ... else :

else if:

示例代碼:

語法格式:

另外,添加 fallthrough 會(huì)強(qiáng)制執(zhí)行后面的 case 語句,不管下一條case語句是否為true。

示例代碼:

執(zhí)行結(jié)果:

下面介紹幾種循環(huán)語句:

執(zhí)行結(jié)果:

執(zhí)行結(jié)果:

也可以通過標(biāo)記退出循環(huán):

--THE END--

為什么要使用 Go 語言?Go 語言的優(yōu)勢在哪里

1. 保留但大幅度簡化指針

Go語言保留著C中值和指針的區(qū)別,但是對(duì)于指針繁瑣用法進(jìn)行了大量的簡化,引入引用的概念。所以在Go語言中,你幾乎不用擔(dān)心會(huì)因?yàn)橹苯硬僮鲀?nèi)寸而引起各式各樣的錯(cuò)誤。

2. 多參數(shù)返回

還記得在C里面為了回饋多個(gè)參數(shù),不得不開辟幾段指針傳到目標(biāo)函數(shù)中讓其操作么?在Go里面這是完全不必要的。而且多參數(shù)的支持讓Go無需使用繁瑣的exceptions體系,一個(gè)函數(shù)可以返回期待的返回值加上error,調(diào)用函數(shù)后立刻處理錯(cuò)誤信息,清晰明了。

3. Array,slice,map等內(nèi)置基本數(shù)據(jù)結(jié)構(gòu)

如果你習(xí)慣了Python中簡潔的list和dict操作,在Go語言中,你不會(huì)感到孤單。一切都是那么熟悉,而且更加高效。如果你是C++程序員,你會(huì)發(fā)現(xiàn)你又找到了STL的vector 和 map這對(duì)朋友。

4. Interface

Go語言最讓人贊嘆不易的特性,就是interface的設(shè)計(jì)。任何數(shù)據(jù)結(jié)構(gòu),只要實(shí)現(xiàn)了interface所定義的函數(shù),自動(dòng)就implement了這個(gè)interface,沒有像Java那樣冗長的class申明,提供了靈活太多的設(shè)計(jì)度和OO抽象度,讓你的代碼也非常干凈。千萬不要以為你習(xí)慣了Java那種一條一條加implements的方式,感覺還行,等接口的設(shè)計(jì)越來越復(fù)雜的時(shí)候,無數(shù)Bug正在后面等著你。

同時(shí),正因?yàn)槿绱耍珿o語言的interface可以用來表示任何generic的東西,比如一個(gè)空的interface,可以是string可以是int,可以是任何數(shù)據(jù)類型,因?yàn)檫@些數(shù)據(jù)類型都不需要實(shí)現(xiàn)任何函數(shù),自然就滿足空interface的定義了。加上Go語言的type assertion,可以提供一般動(dòng)態(tài)語言才有的duck typing特性, 而仍然能在compile中捕捉明顯的錯(cuò)誤。

5. OO

Go語言本質(zhì)上不是面向?qū)ο笳Z言,它還是過程化的。但是,在Go語言中, 你可以很輕易的做大部分你在別的OO語言中能做的事,用更簡單清晰的邏輯。是的,在這里,不需要class,仍然可以繼承,仍然可以多態(tài),但是速度卻快得多。因?yàn)楸举|(zhì)上,OO在Go語言中,就是普通的struct操作。

6. Goroutine

這個(gè)幾乎算是Go語言的招牌特性之一了,我也不想多提。如果你完全不了解Goroutine,那么你只需要知道,這玩意是超級(jí)輕量級(jí)的類似線程的東西,但通過它,你不需要復(fù)雜的線程操作鎖操作,不需要care調(diào)度,就能玩轉(zhuǎn)基本的并行程序。在Go語言里,觸發(fā)一個(gè)routine和erlang spawn一樣簡單?;旧弦莆誈o語言,以Goroutine和channel為核心的內(nèi)存模型是必須要懂的。不過請(qǐng)放心,真的非常簡單。

7. 更多現(xiàn)代的特性

和C比較,Go語言完全就是一門現(xiàn)代化語言,原生支持的Unicode, garbage collection, Closures(是的,和functional programming language類似), function是first class object,等等等等。

看到這里,你可能會(huì)發(fā)現(xiàn),我用了很多輕易,簡單,快速之類的形容詞來形容Go語言的特點(diǎn)。我想說的是,一點(diǎn)都不夸張,連Go語言的入門學(xué)習(xí)到提高,都比別的語言門檻低太多太多。在大部分人都有C的背景的時(shí)代,對(duì)于Go語言,從入門到能夠上手做項(xiàng)目,最多不過半個(gè)月。Go語言給人的感覺就是太直接了,什么都直接,讀源代碼直接,寫自己的代碼也直接。

go語言數(shù)組,切片和字典的區(qū)別和聯(lián)系

、數(shù)組 

與其他大多數(shù)語言類似,Go語言的數(shù)組也是一個(gè)元素類型相同的定長的序列。

(1)數(shù)組的創(chuàng)建。

數(shù)組有3種創(chuàng)建方式:[length]Type 、[N]Type{value1, value2, ... , valueN}、[...]Type{value1, value2, ... , valueN} 如下:

復(fù)制代碼代碼如下:

func test5() {

var iarray1 [5]int32

var iarray2 [5]int32 = [5]int32{1, 2, 3, 4, 5}

iarray3 := [5]int32{1, 2, 3, 4, 5}

iarray4 := [5]int32{6, 7, 8, 9, 10}

iarray5 := [...]int32{11, 12, 13, 14, 15}

iarray6 := [4][4]int32{{1}, {1, 2}, {1, 2, 3}}

fmt.Println(iarray1)

fmt.Println(iarray2)

fmt.Println(iarray3)

fmt.Println(iarray4)

fmt.Println(iarray5)

fmt.Println(iarray6)

}

結(jié)果:

[0 0 0 0 0]

[1 2 3 4 5]

[1 2 3 4 5]

[6 7 8 9 10]

[11 12 13 14 15]

[[1 0 0 0] [1 2 0 0] [1 2 3 0] [0 0 0 0]]

我們看數(shù)組 iarray1,只聲明,并未賦值,Go語言幫我們自動(dòng)賦值為0。再看 iarray2 和 iarray3 ,我們可以看到,Go語言的聲明,可以表明類型,也可以不表明類型,var iarray3 = [5]int32{1, 2, 3, 4, 5} 也是完全沒問題的。

(2)數(shù)組的容量和長度是一樣的。cap() 函數(shù)和 len() 函數(shù)均輸出數(shù)組的容量(即長度)。如:

復(fù)制代碼代碼如下:

func test6() {

iarray4 := [5]int32{6, 7, 8, 9, 10}

fmt.Println(len(iarray4))

fmt.Println(cap(iarray4))

}

輸出都是5。

(3)使用:

復(fù)制代碼代碼如下:

func test7() {

iarray7 := [5]string{"aaa", `bb`, "可以啦", "叫我說什么好", "()"}

fmt.Println(iarray7)

for i := range iarray7 {

fmt.Println(iarray7[i])

}

}

二、切片

Go語言中,切片是長度可變、容量固定的相同的元素序列。Go語言的切片本質(zhì)是一個(gè)數(shù)組。容量固定是因?yàn)閿?shù)組的長度是固定的,切片的容量即隱藏?cái)?shù)組的長度。長度可變指的是在數(shù)組長度的范圍內(nèi)可變。

(1)切片的創(chuàng)建。

切片的創(chuàng)建有4種方式:

1)make ( []Type ,length, capacity )

2) make ( []Type, length)

3) []Type{}

4) []Type{value1 , value2 , ... , valueN }

從3)、4)可見,創(chuàng)建切片跟創(chuàng)建數(shù)組唯一的區(qū)別在于 Type 前的“ [] ”中是否有數(shù)字,為空,則代表切片,否則則代表數(shù)組。因?yàn)榍衅情L度可變的。如下是創(chuàng)建切片的示例:

復(fù)制代碼代碼如下:

func test8() {

slice1 := make([]int32, 5, 8)

slice2 := make([]int32, 9)

slice3 := []int32{}

slice4 := []int32{1, 2, 3, 4, 5}

fmt.Println(slice1)

fmt.Println(slice2)

fmt.Println(slice3)

fmt.Println(slice4)

}

輸出為:

[0 0 0 0 0]

[0 0 0 0 0 0 0 0 0]

[]

[1 2 3 4 5]

如上,創(chuàng)造了4個(gè)切片,3個(gè)空切片,一個(gè)有值的切片。

(2)切片與隱藏?cái)?shù)組:

一個(gè)切片是一個(gè)隱藏?cái)?shù)組的引用,并且對(duì)于該切片的切片也引用同一個(gè)數(shù)組。如下示例,創(chuàng)建了一個(gè)切片slice0,并根據(jù)這個(gè)切片創(chuàng)建了2個(gè)切片 slice1 和 slice2:

復(fù)制代碼代碼如下:

func test9() {

slice0 := []string{"a", "b", "c", "d", "e"}

slice1 := slice0[2 : len(slice0)-1]

slice2 := slice0[:3]

fmt.Println(slice0, slice1, slice2)

slice2[2] = "8"

fmt.Println(slice0, slice1, slice2)

}

輸出為:

[a b c d e] [c d] [a b c]

[a b 8 d e] [8 d] [a b 8]

可見,切片slice0 、 slice1 和 slice2是同一個(gè)底層數(shù)組的引用,所以slice2改變了,其他兩個(gè)都會(huì)變。

(3)遍歷、修改切片:

復(fù)制代碼代碼如下:

func test10() {

slice0 := []string{"a", "b", "c", "d", "e"}

fmt.Println("\n~~~~~~元素遍歷~~~~~~")

for _, ele := range slice0 {

fmt.Print(ele, " ")

ele = "7"

}

fmt.Println("\n~~~~~~索引遍歷~~~~~~")

for index := range slice0 {

fmt.Print(slice0[index], " ")

}

fmt.Println("\n~~~~~~元素索引共同使用~~~~~~")

for index, ele := range slice0 {

fmt.Print(ele, slice0[index], " ")

}

fmt.Println("\n~~~~~~修改~~~~~~")

for index := range slice0 {

slice0[index] = "9"

}

fmt.Println(slice0)

}

如上,前三種循環(huán)使用了不同的for range循環(huán),當(dāng)for后面,range前面有2個(gè)元素時(shí),第一個(gè)元素代表索引,第二個(gè)元素代表元素值,使用 “_” 則表示忽略,因?yàn)間o語言中,未使用的值會(huì)導(dǎo)致編譯錯(cuò)誤。

只有一個(gè)元素時(shí),該元素代表索引。

只有用索引才能修改元素。如在第一個(gè)遍歷中,賦值ele為7,結(jié)果沒有作用。因?yàn)樵谠乇闅v中,ele是值傳遞,ele是該切片元素的副本,修改它不會(huì)影響原本值,而在第四個(gè)遍歷——索引遍歷中,修改的是該切片元素引用的值,所以可以修改。

結(jié)果為:

~~~~~~元素遍歷~~~~~~

a b c d e

~~~~~~索引遍歷~~~~~~

a b c d e

~~~~~~元素索引共同使用~~~~~~

aa bb cc dd ee

~~~~~~修改~~~~~~

[9 9 9 9 9]

(4)、追加、復(fù)制切片:

復(fù)制代碼代碼如下:

func test11() {

slice := []int32{}

fmt.Printf("slice的長度為:%d,slice為:%v\n", len(slice), slice)

slice = append(slice, 12, 11, 10, 9)

fmt.Printf("追加后,slice的長度為:%d,slice為:%v\n", len(slice), slice)

slicecp := make([]int32, (len(slice)))

fmt.Printf("slicecp的長度為:%d,slicecp為:%v\n", len(slicecp), slicecp)

copy(slicecp, slice)

fmt.Printf("復(fù)制賦值后,slicecp的長度為:%d,slicecp為:%v\n", len(slicecp), slicecp)

}

追加、復(fù)制切片,用的是內(nèi)置函數(shù)append和copy,copy函數(shù)返回的是最后所復(fù)制的元素的數(shù)量。

(5)、內(nèi)置函數(shù)append

內(nèi)置函數(shù)append可以向一個(gè)切片后追加一個(gè)或多個(gè)同類型的其他值。如果追加的元素?cái)?shù)量超過了原切片容量,那么最后返回的是一個(gè)全新數(shù)組中的全新切片。如果沒有超過,那么最后返回的是原數(shù)組中的全新切片。無論如何,append對(duì)原切片無任何影響。如下示例:

復(fù)制代碼代碼如下:

func test12() {

slice := []int32{1, 2, 3, 4, 5, 6}

slice2 := slice[:2]

_ = append(slice2, 50, 60, 70, 80, 90)

fmt.Printf("slice為:%v\n", slice)

fmt.Printf("操作的切片:%v\n", slice2)

_ = append(slice2, 50, 60)

fmt.Printf("slice為:%v\n", slice)

fmt.Printf("操作的切片:%v\n", slice2)

}

如上,append方法用了2次,結(jié)果返回的結(jié)果完全不同,原因是第二次append方法追加的元素?cái)?shù)量沒有超過 slice 的容量。而無論怎樣,原切片slice2都無影響。結(jié)果:

slice為:[1 2 3 4 5 6]

操作的切片:[1 2]

slice為:[1 2 50 60 5 6]

操作的切片:[1 2]

如何在 Go 語言中用 Beats 開發(fā) Logstash 插件

配置環(huán)境

在OSX系統(tǒng)上很容易安裝GO的可執(zhí)行文件:

brew?install?go

雖然Java或Ruby?(或者任何我知道的語言)?可以在本地文件系統(tǒng)的任何地方使用命令,,但是Go項(xiàng)目必須使用單一專用的地址,,并且在$GOPATH環(huán)境變量下可用。

第?1?段(可獲?1.54?積分)

R?e;?7個(gè)月前?

創(chuàng)建項(xiàng)目對(duì)于Logstash插件,Beats項(xiàng)目可以從模板創(chuàng)建。官方文檔的說明十分簡單。鑒于Go對(duì)文件系統(tǒng)上的位置的嚴(yán)格要求,只需按照以下說明生成一個(gè)新的即可使用的Go項(xiàng)目。默認(rèn)模板代碼將在控制臺(tái)中重復(fù)發(fā)送帶增量計(jì)數(shù)器的事件:./redditbeat?-e?-d?"*"

2016/12/13?22:55:56.013362?beat.go:267:?INFO

Home?path:?[/Users/i303869/projects/private/go/src/github.com/nfrankel/redditbeat]

Config?path:?[/Users/i303869/projects/private/go/src/github.com/nfrankel/redditbeat]

Data?path:?[/Users/i303869/projects/private/go/src/github.com/nfrankel/redditbeat/data]

Logs?path:?[/Users/i303869/projects/private/go/src/github.com/nfrankel/redditbeat/logs]

2016/12/13?22:55:56.013390?beat.go:177:?INFO?Setup?Beat:?redditbeat;?Version:?6.0.0-alpha1

2016/12/13?22:55:56.013402?processor.go:43:?DBG??Processors:?

2016/12/13?22:55:56.013413?beat.go:183:?DBG??Initializing?output?plugins

2016/12/13?22:55:56.013417?logp.go:219:?INFO?Metrics?logging?every?30s

2016/12/13?22:55:56.013518?output.go:167:?INFO?Loading?template?enabled.?Reading?template?file:

/Users/i303869/projects/private/go/src/github.com/nfrankel/redditbeat/redditbeat.template.json

2016/12/13?22:55:56.013888?output.go:178:?INFO?Loading?template?enabled?for?Elasticsearch?2.x.?Reading?template?file:

/Users/i303869/projects/private/go/src/github.com/nfrankel/redditbeat/redditbeat.template-es2x.json

2016/12/13?22:55:56.014229?client.go:120:?INFO?Elasticsearch?url:?

2016/12/13?22:55:56.014272?outputs.go:106:?INFO?Activated?elasticsearch?as?output?plugin.

2016/12/13?22:55:56.014279?publish.go:234:?DBG??Create?output?worker

2016/12/13?22:55:56.014312?publish.go:276:?DBG??No?output?is?defined?to?store?the?topology.

The?server?fields?might?not?be?filled.

2016/12/13?22:55:56.014326?publish.go:291:?INFO?Publisher?name:?LSNM33795267A

2016/12/13?22:55:56.014386?async.go:63:?INFO?Flush?Interval?set?to:?1s

2016/12/13?22:55:56.014391?async.go:64:?INFO?Max?Bulk?Size?set?to:?50

2016/12/13?22:55:56.014395?async.go:72:?DBG??create?bulk?processing?worker?(interval=1s,?bulk?size=50)

2016/12/13?22:55:56.014449?beat.go:207:?INFO?redditbeat?start?running.

2016/12/13?22:55:56.014459?redditbeat.go:38:?INFO?redditbeat?is?running!?Hit?CTRL-C?to?stop?it.

2016/12/13?22:55:57.370781?client.go:184:?DBG??Publish:?{

"@timestamp":?"2016-12-13T22:54:47.252Z",

"beat":?{

"hostname":?"LSNM33795267A",

"name":?"LSNM33795267A",

"version":?"6.0.0-alpha1"

},

"counter":?1,

"type":?"redditbeat"

}

第?2?段(可獲?0.73?積分)

R?e;?7個(gè)月前?

關(guān)于命令行參數(shù):-e記錄到標(biāo)準(zhǔn)err,而-d“*”啟用所有調(diào)試選擇器。有關(guān)參數(shù)的完整列表,請(qǐng)鍵入./redditbeat?--help。編碼Go代碼位于.go文件中(令人驚訝...)在$?GOPATH?/?src文件夾的項(xiàng)目子文件夾中。配置類型第一個(gè)有趣的文件是config?/?config.go,它定義了一個(gè)結(jié)構(gòu)來聲明Beat的可能參數(shù)。至于前面的Logstash插件,讓我們添加一個(gè)subreddit參數(shù),并設(shè)置它的默認(rèn)值:type?Config?struct?{

Period?time.Duration?`config:"period"`

Subreddit?string?`config:"subreddit"`

}

var?DefaultConfig?=?Config?{

Period:?15?*?time.Second,

Subreddit:?"elastic",

}

第?3?段(可獲?0.89?積分)

R?e;?7個(gè)月前?

Beater?TypeBeat本身的代碼在beater?/?redditbean.go中找到。默認(rèn)模板為Beat和三個(gè)函數(shù)創(chuàng)建一個(gè)struct:Beat構(gòu)造函數(shù)—用來讀取配置:?func?New(b?*beat.Beat,?cfg?*common.Config)?(beat.Beater,?error)?{?...?}?

Run?函數(shù)-?需要覆蓋Beat的主要功能:?func?(bt?*Redditbeat)?Run(b?*beat.Beat)?error?{?...?}?

Stop?函數(shù)管理優(yōu)雅關(guān)閉:?func?(bt?*Redditbeat)?Stop()?{?...?}?

Note?1:在Go中沒有明確的接口實(shí)現(xiàn)。實(shí)現(xiàn)了?interface?中的所有方法,即創(chuàng)建一個(gè)隱式繼承關(guān)系.?出于寫文檔的目的,這是?Beater?接口:type?Beater?interface?{

Run(b?*Beat)?error

Stop()

}

第?4?段(可獲?0.93?積分)

R?e;?7個(gè)月前?

因此,由于Beat結(jié)構(gòu)實(shí)現(xiàn)了Run和Stop,它是一個(gè)Beater。Note?2:?在Go中沒有類的概念,所以方法不能在一個(gè)具體類型上聲明。但是,它存在擴(kuò)展函數(shù)的概念:可以添加行為到一個(gè)類型(在單個(gè)包中)的函數(shù)。它需要聲明receiver?類型:這是在fun關(guān)鍵字和函數(shù)名之間完成的?-?這里是指Redditbeat類型(或者更準(zhǔn)確地說,是一個(gè)指向Redditbeat類型的指針,但是這里有一個(gè)隱式轉(zhuǎn)換)。構(gòu)造函數(shù)和Stop函數(shù)可以保持不變,無論什么特性都應(yīng)該在Run函數(shù)中。在這種情況下,功能是調(diào)用Reddit?REST?API并為每個(gè)Reddit帖子發(fā)送一條消息。

第?5?段(可獲?1.59?積分)

R?e;?7個(gè)月前?

最終代碼如下所示:func?(bt?*Redditbeat)?Run(b?*beat.Beat)?error?{

bt.client?=?b.Publisher.Connect()

ticker?:=?time.NewTicker(bt.config.Period)

reddit?:=?""?+?bt.config.Subreddit?+?"/.json"

client?:=?http.Client?{}

for?{

select?{

case?-bt.done:

return?nil

case?-ticker.C:

}

req,?reqErr?:=?http.NewRequest("GET",?reddit,?nil)

req.Header.Add("User-Agent",?"Some?existing?header?to?bypass?429?HTTP")

if?(reqErr?!=?nil)?{

panic(reqErr)

}

resp,?getErr?:=?client.Do(req)

if?(getErr?!=?nil)?{

panic(getErr)

}

body,?readErr?:=?ioutil.ReadAll(resp.Body)

defer?resp.Body.Close()

if?(readErr?!=?nil)?{

panic(readErr)

}

trimmedBody?:=?body[len(prefix):len(body)?-?len(suffix)]

messages?:=?strings.Split(string(trimmedBody),?separator)

for?i?:=?0;?i??len(messages);?i?++?{

event?:=?common.MapStr{

"@timestamp":?common.Time(time.Now()),

"type":???????b.Name,

"message":????"{"?+?messages[i]?+?"}",

}

bt.client.PublishEvent(event)

}

}

}

第?6?段(可獲?0.09?積分)

R?e;?7個(gè)月前?

這里是對(duì)最重要的幾部分的解釋:line?4:?通過連接字符串創(chuàng)建Reddit?REST?URL,包括配置Subreddit參數(shù)。記住,它的默認(rèn)值已在config.go文件中定義。line?5:?引用httpClient類型line?12:?創(chuàng)建新的HTTP請(qǐng)求。注意Go允許多個(gè)返回值。line?13:?如果沒有設(shè)置標(biāo)準(zhǔn)請(qǐng)求頭,Reddit的API將返回429狀態(tài)碼。line?14:?Go標(biāo)準(zhǔn)錯(cuò)誤不通過異常處理,而是隨著常規(guī)返回值返回。根據(jù)Golang?wiki:指示調(diào)用者的錯(cuò)誤條件,應(yīng)通過返回錯(cuò)誤值來完成line?15:?panic()?函數(shù)類似于在Java中拋出異常,?被處理時(shí)推到棧頂。?有關(guān)詳細(xì)信息,請(qǐng)查看相關(guān)文檔。line?17:?執(zhí)行HTTP請(qǐng)求。line?21:?將響應(yīng)主體讀入字節(jié)數(shù)組。line?22:?關(guān)閉主體流。注意defer關(guān)鍵字:defer語句延遲函數(shù)的執(zhí)行,直到環(huán)繞的函數(shù)返回。line?26:?創(chuàng)建整個(gè)響應(yīng)主體字節(jié)數(shù)組的切片?-?對(duì)數(shù)組的一部分的引用。實(shí)質(zhì)上,它刪除了前綴和后綴以保持相關(guān)的JSON值。之后將字節(jié)數(shù)組解析成JSON。line?27:?分割切片以單獨(dú)獲取每個(gè)JSON片段。line?29:?將消息創(chuàng)建為簡單的字典結(jié)構(gòu)。line?34:?發(fā)送。

第?7?段(可獲?3.11?積分)

R?e;?7個(gè)月前?

配置,?構(gòu)建,?運(yùn)行默認(rèn)配置參數(shù)可以在項(xiàng)目根目錄下的redditbeat.yml文件中找到。請(qǐng)注意,redditbeat.full.yml中列出了其他常見的Beat參數(shù),以及相關(guān)注釋。關(guān)于Beats的一個(gè)有趣的事情是,他們的消息可以直接發(fā)送到Elasticsearch或Logstash進(jìn)行進(jìn)一步處理。這在上述配置文件中配置。redditbeat:

period:?10s

output.elasticsearch:

hosts:?["localhost:9200"]

output.logstash:

hosts:?["localhost:5044"]

enabled:?true

第?8?段(可獲?0.78?積分)

R?e;?7個(gè)月前?

此配置片段將每10秒循環(huán)運(yùn)行Run方法,并將消息發(fā)送到在localhost上運(yùn)行的Logstash實(shí)例在端口5044上。這可以在運(yùn)行Beat時(shí)被覆蓋(見下文)。注意:為了使Logstash接受來自Beats的消息,必須安裝Logstash?Beat插件,并且必須為Beats配置Logstash的input:input?{

beats?{

port?=?5044

}

}

要構(gòu)建項(xiàng)目,請(qǐng)?jiān)陧?xiàng)目的根目錄中鍵入make。它將創(chuàng)建一個(gè)可以運(yùn)行的可執(zhí)行文件。./redditbeat?-e?-E?redditbeat.subreddit=java

-E參數(shù)可以覆蓋在的redditbeat.yml配置文件中找到的參數(shù)(見上文)。在這里,它設(shè)置subreddit讀為“java”,而不是默認(rèn)的“elastic”。

第?9?段(可獲?1.3?積分)

R?e;?7個(gè)月前?

輸出如下所示:2016/12/17?14:51:19.748329?client.go:184:?DBG??Publish:?{

"@timestamp":?"2016-12-17T14:51:19.748Z",

"beat":?{

"hostname":?"LSNM33795267A",

"name":?"LSNM33795267A",

"version":?"6.0.0-alpha1"

},

"message":?"{

\"kind\":?\"t3\",?\"data\":?{

\"contest_mode\":?false,?\"banned_by\":?null,?

\"domain\":?\"blogs.oracle.com\",?\"subreddit\":?\"java\",?\"selftext_html\":?null,?

\"selftext\":?\"\",?\"likes\":?null,?\"suggested_sort\":?null,?\"user_reports\":?[],?

\"secure_media\":?null,?\"saved\":?false,?\"id\":?\"5ipzgq\",?\"gilded\":?0,?

\"secure_media_embed\":?{},?\"clicked\":?false,?\"report_reasons\":?null,?

\"author\":?\"pushthestack\",?\"media\":?null,?\"name\":?\"t3_5ipzgq\",?\"score\":?11,?

\"approved_by\":?null,?\"over_18\":?false,?\"removal_reason\":?null,?\"hidden\":?false,?

\"thumbnail\":?\"\",?\"subreddit_id\":?\"t5_2qhd7\",?\"edited\":?false,?

\"link_flair_css_class\":?null,?\"author_flair_css_class\":?null,?\"downs\":?0,?

\"mod_reports\":?[],?\"archived\":?false,?\"media_embed\":?{},?\"is_self\":?false,?

\"hide_score\":?false,?\"spoiler\":?false,?

\"permalink\":?\"/r/java/comments/5ipzgq/jdk_9_will_no_longer_bundle_javadb/\",?

\"locked\":?false,?\"stickied\":?false,?\"created\":?1481943248.0,?

\"url\":?\"\",?

\"author_flair_text\":?null,?\"quarantine\":?false,?

\"title\":?\"JDK?9?will?no?longer?bundle?JavaDB\",?\"created_utc\":?1481914448.0,?

\"link_flair_text\":?null,?\"distinguished\":?null,?\"num_comments\":?4,?

\"visited\":?false,?\"num_reports\":?null,?\"ups\":?11

}

}",

"type":?"redditbeat"

}

Go語言設(shè)計(jì)與實(shí)現(xiàn)(上)

基本設(shè)計(jì)思路:

類型轉(zhuǎn)換、類型斷言、動(dòng)態(tài)派發(fā)。iface,eface。

反射對(duì)象具有的方法:

編譯優(yōu)化:

內(nèi)部實(shí)現(xiàn):

實(shí)現(xiàn) Context 接口有以下幾個(gè)類型(空實(shí)現(xiàn)就忽略了):

互斥鎖的控制邏輯:

設(shè)計(jì)思路:

(以上為寫被讀阻塞,下面是讀被寫阻塞)

總結(jié),讀寫鎖的設(shè)計(jì)還是非常巧妙的:

設(shè)計(jì)思路:

WaitGroup 有三個(gè)暴露的函數(shù):

部件:

設(shè)計(jì)思路:

結(jié)構(gòu):

Once 只暴露了一個(gè)方法:

實(shí)現(xiàn):

三個(gè)關(guān)鍵點(diǎn):

細(xì)節(jié):

讓多協(xié)程任務(wù)的開始執(zhí)行時(shí)間可控(按順序或歸一)。(Context 是控制結(jié)束時(shí)間)

設(shè)計(jì)思路: 通過一個(gè)鎖和內(nèi)置的 notifyList 隊(duì)列實(shí)現(xiàn),Wait() 會(huì)生成票據(jù),并將等待協(xié)程信息加入鏈表中,等待控制協(xié)程中發(fā)送信號(hào)通知一個(gè)(Signal())或所有(Boardcast())等待者(內(nèi)部實(shí)現(xiàn)是通過票據(jù)通知的)來控制協(xié)程解除阻塞。

暴露四個(gè)函數(shù):

實(shí)現(xiàn)細(xì)節(jié):

部件:

包: golang.org/x/sync/errgroup

作用:開啟 func() error 函數(shù)簽名的協(xié)程,在同 Group 下協(xié)程并發(fā)執(zhí)行過程并收集首次 err 錯(cuò)誤。通過 Context 的傳入,還可以控制在首次 err 出現(xiàn)時(shí)就終止組內(nèi)各協(xié)程。

設(shè)計(jì)思路:

結(jié)構(gòu):

暴露的方法:

實(shí)現(xiàn)細(xì)節(jié):

注意問題:

包: "golang.org/x/sync/semaphore"

作用:排隊(duì)借資源(如錢,有借有還)的一種場景。此包相當(dāng)于對(duì)底層信號(hào)量的一種暴露。

設(shè)計(jì)思路:有一定數(shù)量的資源 Weight,每一個(gè) waiter 攜帶一個(gè) channel 和要借的數(shù)量 n。通過隊(duì)列排隊(duì)執(zhí)行借貸。

結(jié)構(gòu):

暴露方法:

細(xì)節(jié):

部件:

細(xì)節(jié):

包: "golang.org/x/sync/singleflight"

作用:防擊穿。瞬時(shí)的相同請(qǐng)求只調(diào)用一次,response 被所有相同請(qǐng)求共享。

設(shè)計(jì)思路:按請(qǐng)求的 key 分組(一個(gè) *call 是一個(gè)組,用 map 映射存儲(chǔ)組),每個(gè)組只進(jìn)行一次訪問,組內(nèi)每個(gè)協(xié)程會(huì)獲得對(duì)應(yīng)結(jié)果的一個(gè)拷貝。

結(jié)構(gòu):

邏輯:

細(xì)節(jié):

部件:

如有錯(cuò)誤,請(qǐng)批評(píng)指正。

Python開發(fā)者在轉(zhuǎn)到Go語言之前需要了解什么?

轉(zhuǎn)載請(qǐng)參見文章末尾處的要求。【感謝張佳偉(@ghosert)的熱心翻譯。如果其他朋友也有不錯(cuò)的原創(chuàng)或譯文,可以嘗試推薦給伯樂在線?!窟@是一篇(長)博文, 介紹了我們?cè)?Repustate 遷移大量 Python/Cython 代碼到 Go 語言的經(jīng)驗(yàn)。如果你想了解整個(gè)故事,背景和所有的事情,請(qǐng)繼續(xù)往下讀。如果你只是想了解 Python 開發(fā)者在一頭扎進(jìn) Go 語言前需要了解什么,請(qǐng)點(diǎn)擊一下鏈接:從Python遷移到Go的建議(Tips Tricks) 背景在Repustate,我們完成過的最棒的技術(shù)成就之一是實(shí)現(xiàn)了阿拉伯語的情感分析。阿拉伯語是一塊難啃的硬骨頭,因?yàn)樗脑~形變化相當(dāng)復(fù)雜。比起譬如英語,阿拉伯語的分詞(將一個(gè)句子切分呈幾個(gè)獨(dú)立的單詞)也更困難,因?yàn)榘⒗Z的單詞本身還可能會(huì)包含空白字符(例如:“阿列夫”在一個(gè)單詞里的位置)。這也談不上是泄密,Repustate 使用支持向量機(jī)(SVM)來獲取一個(gè)句子背后最有可能的含義,并在其中加上情感元素。 總體上來說,我們使用了 22 種模型(22 個(gè) SVM) 并且在一篇文檔中,每一個(gè)單詞我們都會(huì)加以分析。因此如果你有一篇 500 字的文檔,那么基于 SVM,會(huì)進(jìn)行十萬次的比較。 PythonRepustate 幾乎完全就是一個(gè) Python 商店。我們使用 Django 來實(shí)現(xiàn) API 和網(wǎng)站。因此(目前)為了保持代碼一致,同時(shí)使用 Python 來實(shí)現(xiàn)阿拉伯語情感引擎是合情合理的。只是做原型和實(shí)現(xiàn)的話,Python 是很好的選擇。它的表達(dá)能力很強(qiáng)悍,第三方類庫等等也很好。如果你就是為了Web服務(wù),Python 很完美。但是當(dāng)你進(jìn)行低級(jí)別的計(jì)算,大量依賴于哈希表(Python 里的字典類型)做比較的時(shí)候,一切都變慢了。我們每秒能處理大約兩到三個(gè)阿拉伯文檔,但是這太慢了。比較下來,我們的英語情感引擎每秒能處理大約五百份文檔。 瓶頸因此我們開啟了 Python 分析器,開始調(diào)查是什么地方用了那么長時(shí)間。還記得我前面說過我們有 22 個(gè) SVM 并且每個(gè)單詞都需要經(jīng)過處理嗎?好吧,這些都是線性處理的,非并行處理。所以我們的第一反應(yīng)是把線性處理改成 map/reduce 那樣的操作。簡單來說:Python 不太適合用作 map/reduce。當(dāng)你需要并發(fā)的時(shí)候,Python 算上好用。在 2013 Python 大會(huì)上(譯者:PyCon 2013),Guido 談到了 Tulip,他的這個(gè)新項(xiàng)目正在彌補(bǔ) Python 這方面的不足,不過得過段一段時(shí)間才能推出,但是如果已經(jīng)有了更好用的東西,我們?yōu)槭裁催€要等呢? 選Go 語言,還是回家算了?我在Mozilla的朋友告訴我,Mozilla 內(nèi)部正在將他們大量的基礎(chǔ)日志架構(gòu)切換到 Go 語言上,部分原因是因?yàn)閺?qiáng)大的 [goroutines]。Go 語言是 Google 的人設(shè)計(jì)的,并且在設(shè)計(jì)之初就把支持并發(fā)作為第一要?jiǎng)?wù),而不是像 Python 的各種解決方案那樣是事后才加上去的。因此我們開始著手把 Python 換成 Go 語言。雖然Go 代碼還不算正式上線的產(chǎn)品,但是結(jié)果非常令人鼓舞。我們現(xiàn)在能做到每秒處理一千份文檔,使用更少的內(nèi)存,還不用調(diào)試你在 Python 里遇到:丑陋的多進(jìn)程/gevent/“為什么 Control-C 殺不了進(jìn)程”這些問題。 為什么我們喜歡 Go 語言任何人,對(duì)編程語言是如何工作(解釋型 vs 編譯型, 動(dòng)態(tài)語言 vs 靜態(tài)語言)有一點(diǎn)理解的話,會(huì)說,“切,當(dāng)然 Go 語言會(huì)更快”。是的,我們也可以用 Java 把所有的東西重寫一遍,也能看到類似更快的改善,但那不是 Go 語言勝出的原因。你用 Go 寫的代碼好像就是對(duì)的。我搞不清楚到底是怎么回事,但是一旦代碼被編譯了(編譯速度很快),你就會(huì)覺得這代碼能工作(不只是跑起來不會(huì)錯(cuò),而且甚至邏輯上也是對(duì)的)。我知道,這聽上去不太靠譜,但是確實(shí)如此。這和 Python 在冗余(或非冗余)方面非常類似,它把函數(shù)作為第一目標(biāo),因此函數(shù)編程會(huì)很容易想明白。而且當(dāng)然,go 線程和通道讓你的生活更容易,你可以得到靜態(tài)類型帶來的性能大提升,還能更精細(xì)的控制內(nèi)存分配,而你卻不必為此在語言表達(dá)力上付出太多的代價(jià)。 希望能早點(diǎn)知道的事情(Tips Tricks)除去所有這些贊美之詞以后,有時(shí)你真的需要在處理 Go 代碼的時(shí)候,相對(duì)于 Python,改變一下思維方式。因此這是我在遷移代碼時(shí)記錄的筆記清單 —— 只是在我把 Python 代碼轉(zhuǎn)換到 Go 時(shí)從我腦子里隨機(jī)冒出來的點(diǎn)子:沒有內(nèi)建的集合類型(必須使用map,并檢查是否存在)因?yàn)闆]有集合,必須自己寫交集,并集之類的方法沒有tuples 類型,必須寫你自己的結(jié)構(gòu),或者使用 slices (即數(shù)組)沒有類似 \__getattr__() 的方法,你必須總是檢查存在性,而不是設(shè)置默認(rèn)值,例如,在 Python 里,你可以這樣寫 value = dict.get(“a_key”, “default_value”)必須總是檢查錯(cuò)誤(或者顯式的忽略錯(cuò)誤)不能有變量/包沒被使用,因此簡單的測試也需要有時(shí)注掉一些代碼在[] byte 和 string 之間轉(zhuǎn)換。 regexp 使用 [] byte (不可變)。這是對(duì)的,但是老把一些變量轉(zhuǎn)換來轉(zhuǎn)換去很煩人Python 更寬松。你可以使用超出范圍的索引在字符串里取一個(gè)片段,而且不會(huì)出錯(cuò)。你還可以用負(fù)數(shù)取出片段,但是 Go 不行你不能混合數(shù)據(jù)結(jié)構(gòu)類型。也許這樣也不太干凈,但是有時(shí)在 Python 里,我會(huì)使用值是混合了字符串和列表的字典。但是 Go 不行,你不得不清理干凈你的數(shù)據(jù)結(jié)構(gòu)或者使用自定義的結(jié)構(gòu)不能解包一個(gè) tuple 或者 list 到幾個(gè)不同的變量(例如:x, y, z = [1, 2, 3])駝峰式命名風(fēng)格(如果你沒有首字大寫方法名/結(jié)構(gòu)名,他們不會(huì)被暴露給其它的包)。我更喜歡 Python 的小寫字母加下劃線命名風(fēng)格。必須顯式檢查是否有錯(cuò)誤 != nil, 不像在 Python 里,許多類型可以像 bool 那樣檢查 (0, “”, None 都可以被解釋成 “非” 集合)文檔在一些模塊上太散亂了,例如(crypto/md5),但是 IRC 上的 go-nuts 很好用,提供了巨大的幫助。從數(shù)字到字符串的轉(zhuǎn)換(int64 - string) 和 []byte - string (只要使用 string([]byte))不太一樣。需要使用 strconv。閱讀Go 代碼比起 Python 那樣寫起來如偽代碼的語言更像一門編程語言, Go 有更多的非字母數(shù)字字符,并且使用 || 和 , 而不是 “or”和“and”寫一個(gè)文件的話,有 File.Write([]byte) 和 File.WriteString(string), 這點(diǎn)和 Python 開發(fā)者的 Python 之道:“解決問題就一種方法 ”相違背。修改字符串很困難,必須經(jīng)常重排 fmt.Sprintf沒有構(gòu)造函數(shù),因此慣用法是創(chuàng)建 NewType() 方法來返回你要的結(jié)構(gòu)Else (或者 else if)必須正確格式化,else 得和 if 配對(duì)的大括號(hào)在同一行。奇怪。賦值運(yùn)算符取決于在函數(shù)內(nèi)還是函數(shù)外,例如,= 和 :=如果我只想要“鍵”或者只想要 “值”,譬如: dict.keys() 或者 dict.values(),或者一個(gè) tuples 的列表,例如:dict.items(),在 Go 語言里沒有等價(jià)的東西,你只能自己枚舉 map 來構(gòu)造你的列表類型我有時(shí)使用一種習(xí)慣用法:構(gòu)造一個(gè)值是函數(shù)的字典類型,我想通過給定的鍵值調(diào)用這些函數(shù),你在 Go 里可以做到,但是所有的函數(shù)必須接受,返回相同的東西,例如:相同的方法簽名如果你使用 JSON 并且 你的 JSON 是一個(gè)復(fù)合類型,恭喜你。 你必須構(gòu)造自定義的結(jié)構(gòu)匹配 JSON 塊里的格式,然后把原始 JSON 解析到你自定義結(jié)構(gòu)的實(shí)例中去。比起 Python 世界里 object = json.loads(json_blob) 要做更多的工作 是不是值得?值得,一百萬倍的值得。速度的提升太多了,以致很難舍棄。同時(shí),我認(rèn)為, Go 是目前趨勢所在,因此在招新員工的時(shí)候,我認(rèn)為把 Go 當(dāng)作 Repustate 技術(shù)積累的重要一環(huán)會(huì)很有幫助。]


當(dāng)前題目:go語言實(shí)現(xiàn)字典 go語言文檔
網(wǎng)頁路徑:http://weahome.cn/article/doodcci.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部