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

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

go語言的優(yōu)雅用法 go語言 gin

Go語言”奇怪用法“有哪些

1,go的變量聲明順序是:”先寫變量名,再寫類型名“,此與C/C++的語法孰優(yōu)孰劣,可見下文解釋:

成都創(chuàng)新互聯(lián)公司服務項目包括南開網(wǎng)站建設、南開網(wǎng)站制作、南開網(wǎng)頁制作以及南開網(wǎng)絡營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關系等,向廣大中小型企業(yè)、政府機構等提供互聯(lián)網(wǎng)行業(yè)的解決方案,南開網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟效益。目前,我們服務的客戶以成都為中心已經(jīng)輻射到南開省份的部分城市,未來相信會繼續(xù)擴大服務區(qū)域并繼續(xù)獲得客戶的支持與信任!

2,go是通過package來組織的(與python類似),只有package名為main的包可以包含main函數(shù),一個可執(zhí)行程序有且僅有一個main包,通過import關鍵字來導入其他非main包。

3,可見性規(guī)則。go語言中,使用大小寫來決定該常量、變量、類型、接口、結構或函數(shù)是否可以被外部包含調用。根據(jù)約定,函數(shù)名首字母小寫即為private,函數(shù)名首字母大寫即為public。

4,go內置關鍵字(25個均為小寫)。

5,函數(shù)不用先聲明,即可使用。

6,在函數(shù)內部可以通過 := 隱士定義變量。(函數(shù)外必須顯示使用var定義變量)

7,go程序使用UTF-8編碼的純Unicode文本編寫。

8,使用big.Int的陷阱:

9,從技術層面講,go語言的語句是以分號分隔的,但這些是由編譯器自動添加的,不用手動輸入,除非需要在同一行中寫入多個語句。沒有分號及只需少量的逗號和圓括號,使得go語言的程序更容易閱讀。

10,go語言只有一個循環(huán)結構——for循環(huán)。

11,go里的自增運算符只有——“后++”

12,go語言中的slice用法類似python中數(shù)組,關于slice的詳細用法可見:

13,函數(shù)也是一個值,使用匿名函數(shù)返回一個值。

14,函數(shù)閉包的使用,閉包是一個匿名函數(shù)值,會引用到其外部的變量。

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

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

Go語言保留著C中值和指針的區(qū)別,但是對于指針繁瑣用法進行了大量的簡化,引入引用的概念。所以在Go語言中,你幾乎不用擔心會因為直接操作內寸而引起各式各樣的錯誤。

2. 多參數(shù)返回

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

3. Array,slice,map等內置基本數(shù)據(jù)結構

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

4. Interface

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

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

5. OO

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

6. Goroutine

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

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

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

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

Go 優(yōu)雅退出實現(xiàn)方法 amp; context原理

1.通過endless包實現(xiàn)

2.通過shutdown實現(xiàn)

在go 1.8.x后,golang在http里加入了shutdown方法,用來控制優(yōu)雅退出。什么是優(yōu)雅退出? 簡單說就是不處理新請求,但是會處理正在進行的請求,把舊請求都處理完,也就是都response之后,那么就退出。

shutdown通過context上下文實現(xiàn) 。

社區(qū)里不少http graceful動態(tài)重啟,平滑重啟的庫,大多是基于http.shutdown做的。平滑啟動的原理很簡單,fork子進程,繼承l(wèi)isten fd, 老進程優(yōu)雅退出。

3.context原理

context 是 Go 并發(fā)編程中常用到一種編程模式。

在并發(fā)程序中,由于超時、取消操作或者一些異常情況,往往需要進行搶占操作或者中斷后續(xù)操作。熟悉 channel 的朋友應該都見過使用 done channel 來處理此類問題。比如以下這個例子:

上述例子中定義了一個 buffer 為0的 channel done , 子協(xié)程運行著定時任務。如果主協(xié)程需要在某個時刻發(fā)送消息通知子協(xié)程中斷任務退出,那么就可以讓子協(xié)程監(jiān)聽這個 done channel ,一旦主協(xié)程關閉 done channel ,那么子協(xié)程就可以推出了,這樣就實現(xiàn)了主協(xié)程通知子協(xié)程的需求。這很好,但是這也是有限的。

如果我們可以在簡單的通知上附加傳遞額外的信息來控制取消:為什么取消,或者有一個它必須要完成的最終期限,更或者有多個取消選項,我們需要根據(jù)額外的信息來判斷選擇執(zhí)行哪個取消選項。

考慮下面這種情況:假如主協(xié)程中有多個任務1, 2, …m,主協(xié)程對這些任務有超時控制;而其中任務1又有多個子任務1, 2, …n,任務1對這些子任務也有自己的超時控制,那么這些子任務既要感知主協(xié)程的取消信號,也需要感知任務1的取消信號。

如果還是使用 done channel 的用法,我們需要定義兩個 done channel ,子任務們需要同時監(jiān)聽這兩個 done channel 。嗯,這樣其實好像也還行哈。但是如果層級更深,如果這些子任務還有子任務,那么使用 done channel 的方式將會變得非常繁瑣且混亂。

我們需要一種優(yōu)雅的方案來實現(xiàn)這樣一種機制:

這個時候 context 就派上用場了。

我們首先看看 context 的結構設計和實現(xiàn)原理。

先看 Context 接口結構,看起來非常簡單。

Context 接口包含四個方法:

可以看到 Done 方法返回的 channel 正是用來傳遞結束信號以搶占并中斷當前任務; Deadline 方法指示一段時間后當前 goroutine 是否會被取消;以及一個 Err 方法,來解釋 goroutine 被取消的原因;而 Value 則用于獲取特定于當前任務樹的額外信息。而 context 所包含的額外信息鍵值對是如何存儲的呢?其實可以想象一顆樹,樹的每個節(jié)點可能攜帶一組鍵值對,如果當前節(jié)點上無法找到 key 所對應的值,就會向上去父節(jié)點里找,直到根節(jié)點,具體后面會說到。

emptyCtx 是一個 int 類型的變量,但實現(xiàn)了 context 的接口。 emptyCtx 沒有超時時間,不能取消,也不能存儲任何額外信息,所以 emptyCtx 用來作為 context 樹的根節(jié)點。

但我們一般不會直接使用 emptyCtx ,而是使用由 emptyCtx 實例化的兩個變量,分別可以通過調用 Background 和 TODO 方法得到,但這兩個 context 在實現(xiàn)上是一樣的。那么 Background 和 TODO 方法得到的 context 有什么區(qū)別呢?可以看一下官方的解釋:

Background 和 TODO 只是用于不同場景下:

Background 通常被用于主函數(shù)、初始化以及測試中,作為一個頂層的 context ,也就是說一般我們創(chuàng)建的 context 都是基于 Background ;

而 TODO 是在不確定使用什么 context 的時候才會使用。

下面將介紹兩種不同功能的基礎 context 類型: valueCtx 和 cancelCtx 。

valueCtx 利用一個 Context 類型的變量來表示父節(jié)點 context ,所以當前 context 繼承了父 context 的所有信息; valueCtx 類型還攜帶一組鍵值對,也就是說這種 context 可以攜帶額外的信息。 valueCtx 實現(xiàn)了 Value 方法,用以在 context 鏈路上獲取 key 對應的值,如果當前 context 上不存在需要的 key ,會沿著 context 鏈向上尋找 key 對應的值,直到根節(jié)點。

WithValue 用以向 context 添加鍵值對:

這里添加鍵值對不是在原 context 結構體上直接添加,而是以此 context 作為父節(jié)點,重新創(chuàng)建一個新的 valueCtx 子節(jié)點,將鍵值對添加在子節(jié)點上,由此形成一條 context 鏈。獲取 value 的過程就是在這條 context 鏈上由尾部上前搜尋:

跟 valueCtx 類似, cancelCtx 中也有一個 context 變量作為父節(jié)點;變量 done 表示一個 channel ,用來表示傳遞關閉信號; children 表示一個 map ,存儲了當前 context 節(jié)點下的子節(jié)點; err 用于存儲錯誤信息表示任務結束的原因。

再來看一下 cancelCtx 實現(xiàn)的方法:

可以發(fā)現(xiàn) cancelCtx 類型變量其實也是 canceler 類型,因為 cancelCtx 實現(xiàn)了 canceler 接口。 Done 方法和 Err 方法沒必要說了, cancelCtx 類型的 context 在調用 cancel 方法時會設置取消原因,將 done channel 設置為一個關閉 channel 或者關閉 channel ,然后將子節(jié)點 context 依次取消,如果有需要還會將當前節(jié)點從父節(jié)點上移除。

WithCancel 函數(shù)用來創(chuàng)建一個可取消的 context ,即 cancelCtx 類型的 context 。 WithCancel 返回一個 context 和一個 CancelFunc ,調用 CancelFunc 即可觸發(fā) cancel 操作。直接看源碼:

之前說到 cancelCtx 取消時,會將后代節(jié)點中所有的 cancelCtx 都取消, propagateCancel 即用來建立當前節(jié)點與祖先節(jié)點這個取消關聯(lián)邏輯。

這里或許有個疑問,為什么是祖先節(jié)點而不是父節(jié)點?這是因為當前 context 鏈可能是這樣的:

當前 cancelCtx 的父節(jié)點 context 并不是一個可取消的 context ,也就沒法記錄 children 。

timerCtx 是一種基于 cancelCtx 的 context 類型,從字面上就能看出,這是一種可以定時取消的 context 。

timerCtx 內部使用 cancelCtx 實現(xiàn)取消,另外使用定時器 timer 和過期時間 deadline 實現(xiàn)定時取消的功能。 timerCtx 在調用 cancel 方法,會先將內部的 cancelCtx 取消,如果需要則將自己從 cancelCtx 祖先節(jié)點上移除,最后取消計時器。

WithDeadline 返回一個基于 parent 的可取消的 context ,并且其過期時間 deadline 不晚于所設置時間 d 。

與 WithDeadline 類似, WithTimeout 也是創(chuàng)建一個定時取消的 context ,只不過 WithDeadline 是接收一個過期時間點,而 WithTimeout 接收一個相對當前時間的過期時長 timeout :

首先使用 context 實現(xiàn)文章開頭 done channel 的例子來示范一下如何更優(yōu)雅實現(xiàn)協(xié)程間取消信號的同步:

這個例子中,只要讓子線程監(jiān)聽主線程傳入的 ctx ,一旦 ctx.Done() 返回空 channel ,子線程即可取消執(zhí)行任務。但這個例子還無法展現(xiàn) context 的傳遞取消信息的強大優(yōu)勢。

閱讀過 net/http 包源碼的朋友可能注意到在實現(xiàn) http server 時就用到了 context , 下面簡單分析一下。

1、首先 Server 在開啟服務時會創(chuàng)建一個 valueCtx ,存儲了 server 的相關信息,之后每建立一條連接就會開啟一個協(xié)程,并攜帶此 valueCtx 。

2、建立連接之后會基于傳入的 context 創(chuàng)建一個 valueCtx 用于存儲本地地址信息,之后在此基礎上又創(chuàng)建了一個 cancelCtx ,然后開始從當前連接中讀取網(wǎng)絡請求,每當讀取到一個請求則會將該 cancelCtx 傳入,用以傳遞取消信號。一旦連接斷開,即可發(fā)送取消信號,取消所有進行中的網(wǎng)絡請求。

3、讀取到請求之后,會再次基于傳入的 context 創(chuàng)建新的 cancelCtx ,并設置到當前請求對象 req 上,同時生成的 response 對象中 cancelCtx 保存了當前 context 取消方法。

這樣處理的目的主要有以下幾點:

在整個 server 處理流程中,使用了一條 context 鏈貫穿 Server 、 Connection 、 Request ,不僅將上游的信息共享給下游任務,同時實現(xiàn)了上游可發(fā)送取消信號取消所有下游任務,而下游任務自行取消不會影響上游任務。

context 主要用于父子任務之間的同步取消信號,本質上是一種協(xié)程調度的方式 。另外在使用 context 時有兩點值得注意:上游任務僅僅使用 context 通知下游任務不再需要,但不會直接干涉和中斷下游任務的執(zhí)行,由下游任務自行決定后續(xù)的處理操作,也就是說 context 的取消操作是無侵入的; context 是線程安全的,因為 context 本身是不可變的( immutable ),因此可以放心地在多個協(xié)程中傳遞使用。


新聞名稱:go語言的優(yōu)雅用法 go語言 gin
網(wǎng)站地址:http://weahome.cn/article/ddjhejj.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部