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

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

go語言怎么入?yún)?go調(diào)用接口

怎么樣使用Go語言中函數(shù)的參數(shù)傳遞與調(diào)用

按值傳遞函數(shù)參數(shù),是拷貝參數(shù)的實(shí)際值到函數(shù)的形式參數(shù)的方法調(diào)用。在這種情況下,參數(shù)在函數(shù)內(nèi)變化對(duì)參數(shù)不會(huì)有影響。

成都創(chuàng)新互聯(lián)主要從事成都網(wǎng)站建設(shè)、成都網(wǎng)站制作、網(wǎng)頁設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)始興,10多年網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專業(yè),歡迎來電咨詢建站服務(wù):13518219792

默認(rèn)情況下,Go編程語言使用調(diào)用通過值的方法來傳遞參數(shù)。在一般情況下,這意味著,在函數(shù)內(nèi)碼不能改變用來調(diào)用所述函數(shù)的參數(shù)??紤]函數(shù)swap()的定義如下。

代碼如下:

/* function definition to swap the values */

func swap(int x, int y) int {

var temp int

temp = x /* save the value of x */

x = y /* put y into x */

y = temp /* put temp into y */

return temp;

}

現(xiàn)在,讓我們通過使實(shí)際值作為在以下示例調(diào)用函數(shù)swap():

代碼如下:

package main

import "fmt"

func main() {

/* local variable definition */

var a int = 100

var b int = 200

fmt.Printf("Before swap, value of a : %d\n", a )

fmt.Printf("Before swap, value of b : %d\n", b )

/* calling a function to swap the values */

swap(a, b)

fmt.Printf("After swap, value of a : %d\n", a )

fmt.Printf("After swap, value of b : %d\n", b )

}

func swap(x, y int) int {

var temp int

temp = x /* save the value of x */

x = y /* put y into x */

y = temp /* put temp into y */

return temp;

}

讓我們把上面的代碼放在一個(gè)C文件,編譯并執(zhí)行它,它會(huì)產(chǎn)生以下結(jié)果:

Before swap, value of a :100

Before swap, value of b :200

After swap, value of a :100

After swap, value of b :200

這表明,參數(shù)值沒有被改變,雖然它們已經(jīng)在函數(shù)內(nèi)部改變。

通過傳遞函數(shù)參數(shù),即是拷貝參數(shù)的地址到形式參數(shù)的參考方法調(diào)用。在函數(shù)內(nèi)部,地址是訪問調(diào)用中使用的實(shí)際參數(shù)。這意味著,對(duì)參數(shù)的更改會(huì)影響傳遞的參數(shù)。

要通過引用傳遞的值,參數(shù)的指針被傳遞給函數(shù)就像任何其他的值。所以,相應(yīng)的,需要聲明函數(shù)的參數(shù)為指針類型如下面的函數(shù)swap(),它的交換兩個(gè)整型變量的值指向它的參數(shù)。

代碼如下:

/* function definition to swap the values */

func swap(x *int, y *int) {

var temp int

temp = *x /* save the value at address x */

*x = *y /* put y into x */

*y = temp /* put temp into y */

}

現(xiàn)在,讓我們調(diào)用函數(shù)swap()通過引用作為在下面的示例中傳遞數(shù)值:

代碼如下:

package main

import "fmt"

func main() {

/* local variable definition */

var a int = 100

var b int= 200

fmt.Printf("Before swap, value of a : %d\n", a )

fmt.Printf("Before swap, value of b : %d\n", b )

/* calling a function to swap the values.

* a indicates pointer to a ie. address of variable a and

* b indicates pointer to b ie. address of variable b.

*/

swap(a, b)

fmt.Printf("After swap, value of a : %d\n", a )

fmt.Printf("After swap, value of b : %d\n", b )

}

func swap(x *int, y *int) {

var temp int

temp = *x /* save the value at address x */

*x = *y /* put y into x */

*y = temp /* put temp into y */

}

讓我們把上面的代碼放在一個(gè)C文件,編譯并執(zhí)行它,它會(huì)產(chǎn)生以下結(jié)果:

Before swap, value of a :100

Before swap, value of b :200

After swap, value of a :200

After swap, value of b :100

這表明變化的功能以及不同于通過值調(diào)用的外部體現(xiàn)的改變不能反映函數(shù)之外。

go語言實(shí)現(xiàn)一個(gè)簡(jiǎn)單的簡(jiǎn)單網(wǎng)關(guān)

網(wǎng)關(guān)=反向代理+負(fù)載均衡+各種策略,技術(shù)實(shí)現(xiàn)也有多種多樣,有基于 nginx 使用 lua 的實(shí)現(xiàn),比如 openresty、kong;也有基于 zuul 的通用網(wǎng)關(guān);還有就是 golang 的網(wǎng)關(guān),比如 tyk。

這篇文章主要是講如何基于 golang 實(shí)現(xiàn)一個(gè)簡(jiǎn)單的網(wǎng)關(guān)。

轉(zhuǎn)自: troy.wang/docs/golang/posts/golang-gateway/

整理:go語言鐘文文檔:

啟動(dòng)兩個(gè)后端 web 服務(wù)(代碼)

這里使用命令行工具進(jìn)行測(cè)試

具體代碼

直接使用基礎(chǔ)庫 httputil 提供的NewSingleHostReverseProxy即可,返回的reverseProxy對(duì)象實(shí)現(xiàn)了serveHttp方法,因此可以直接作為 handler。

具體代碼

director中定義回調(diào)函數(shù),入?yún)?http.Request,決定如何構(gòu)造向后端的請(qǐng)求,比如 host 是否向后傳遞,是否進(jìn)行 url 重寫,對(duì)于 header 的處理,后端 target 的選擇等,都可以在這里完成。

director在這里具體做了:

modifyResponse中定義回調(diào)函數(shù),入?yún)?http.Response,用于修改響應(yīng)的信息,比如響應(yīng)的 Body,響應(yīng)的 Header 等信息。

最終依舊是返回一個(gè)ReverseProxy,然后將這個(gè)對(duì)象作為 handler 傳入即可。

參考 2.2 中的NewSingleHostReverseProxy,只需要實(shí)現(xiàn)一個(gè)類似的、支持多 targets 的方法即可,具體實(shí)現(xiàn)見后面。

作為一個(gè)網(wǎng)關(guān)服務(wù),在上面 2.3 的基礎(chǔ)上,需要支持必要的負(fù)載均衡策略,比如:

隨便 random 一個(gè)整數(shù)作為索引,然后取對(duì)應(yīng)的地址即可,實(shí)現(xiàn)比較簡(jiǎn)單。

具體代碼

使用curIndex進(jìn)行累加計(jì)數(shù),一旦超過 rss 數(shù)組的長(zhǎng)度,則重置。

具體代碼

輪詢帶權(quán)重,如果使用計(jì)數(shù)遞減的方式,如果權(quán)重是5,1,1那么后端 rs 依次為a,a,a,a,a,b,c,a,a,a,a…,其中 a 后端會(huì)瞬間壓力過大;參考 nginx 內(nèi)部的加權(quán)輪詢,或者應(yīng)該稱之為平滑加權(quán)輪詢,思路是:

后端真實(shí)節(jié)點(diǎn)包含三個(gè)權(quán)重:

操作步驟:

具體代碼

一致性 hash 算法,主要是用于分布式 cache 熱點(diǎn)/命中問題;這里用于基于某 key 的 hash 值,路由到固定后端,但是只能是基本滿足流量綁定,一旦后端目標(biāo)節(jié)點(diǎn)故障,會(huì)自動(dòng)平移到環(huán)上最近的那么個(gè)節(jié)點(diǎn)。

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

具體代碼

每一種不同的負(fù)載均衡算法,只需要實(shí)現(xiàn)添加以及獲取的接口即可。

然后使用工廠方法,根據(jù)傳入的參數(shù),決定使用哪種負(fù)載均衡策略。

具體代碼

作為網(wǎng)關(guān),中間件必不可少,這類包括請(qǐng)求響應(yīng)的模式,一般稱作洋蔥模式,每一層都是中間件,一層層進(jìn)去,然后一層層出來。

中間件的實(shí)現(xiàn)一般有兩種,一種是使用數(shù)組,然后配合 index 計(jì)數(shù);一種是鏈?zhǔn)秸{(diào)用。

具體代碼

golang中interface如何傳參?

Golang的interface,和別的語言是不同的。它不需要顯式的implements,只要某個(gè)struct實(shí)現(xiàn)了interface里的所有函數(shù),編譯器會(huì)自動(dòng)認(rèn)為它實(shí)現(xiàn)了這個(gè)interface。

SICP里詳細(xì)解釋了為什么同一個(gè)接口,需要根據(jù)不同的數(shù)據(jù)類型,有不同的實(shí)現(xiàn);以及如何做到這一點(diǎn)。在這里沒有OO的概念,先把OO放到一邊,從原理上看一下這是怎么做到的。

先把大概原理放在這里,然后再舉例子。為了實(shí)現(xiàn)多態(tài),需要維護(hù)一張全局的查找表,它的功能是根據(jù)類型名和方法名,返回對(duì)應(yīng)的函數(shù)入口。當(dāng)我增加了一種類型,需要把新類型的名字、相應(yīng)的方法名和實(shí)際函數(shù)入口添加到表里。這基本上就是所謂的動(dòng)態(tài)綁定了,類似于C++里的vtable。對(duì)于SICP中使用的lisp語言來說,這些工作需要手動(dòng)完成。而對(duì)于java,則通過implements完成了這項(xiàng)工作。而golang則用了更加激進(jìn)的方式,連implements都省了,編譯器自動(dòng)發(fā)現(xiàn)自動(dòng)綁定。

golang中定義的某個(gè)interface作為函數(shù)的入?yún)r(shí)

函數(shù)的入?yún)⑹悄硞€(gè)interface,那么函數(shù)里調(diào)用interface里的方法時(shí),如果方法里有修改結(jié)構(gòu)體變量,會(huì)修改原有的變量么?

1.方法的接收器是指針,結(jié)構(gòu)體的成員變量是指針變量。變量被修改了。

2.方法的接收器是指針,結(jié)構(gòu)體的成員變量不是指針變量。變量被修改了。

3.方法的接收器不是指針,結(jié)構(gòu)體的成員變量不是指針變量。變量沒有被修改了。

4.方法的接收器不是指針,結(jié)構(gòu)體的成員變量是指針變量。變量被修改了。

也就是方法的接收器或者成員變量有一方是指針,那么原來結(jié)構(gòu)體的成員變量就會(huì)被修改。

http.ServeMux

HTTP協(xié)議全稱超文本傳輸協(xié)議(HyperText Transfer Protocol)是互聯(lián)網(wǎng)上應(yīng)用最為廣泛的一種網(wǎng)絡(luò)協(xié)議,它詳細(xì)規(guī)定了瀏覽器和WWW服務(wù)器之間通信的規(guī)則,通過Internet傳送WWW文檔的數(shù)據(jù)傳送協(xié)議。

Web服務(wù)是HTTP協(xié)議的一個(gè)服務(wù),HTTP協(xié)議承載在TCP協(xié)議之上。Web服務(wù)工作流程

基于HTTP構(gòu)建的服務(wù)標(biāo)準(zhǔn)模型包括客戶端和服務(wù)端,HTTP請(qǐng)求從客戶端發(fā)出,服務(wù)端接收到請(qǐng)求后進(jìn)行處理,然后將響應(yīng)返回給客戶端。

HTTP服務(wù)端核心工作是如何接收來自客戶端的請(qǐng)求,并向客戶端返回響應(yīng)。當(dāng)HTTP服務(wù)器接收到客戶端請(qǐng)求時(shí),首先會(huì)進(jìn)入路由模塊,路由又稱為服務(wù)復(fù)用器(Multiplexer),路由的工作在于請(qǐng)求找到對(duì)應(yīng)的處理器(Handler),處理器對(duì)接收到的請(qǐng)求進(jìn)行對(duì)應(yīng)處理后,構(gòu)建響應(yīng)并返回給客戶端。

Go語言通過引入 net/http 包來實(shí)現(xiàn)HTTP網(wǎng)絡(luò)訪問,并提供HTTP客戶端和服務(wù)端的實(shí)現(xiàn)。

創(chuàng)建HTTP服務(wù)需經(jīng)過2個(gè)階段

例如:創(chuàng)建HTTP服務(wù)

理解HTTP服務(wù)關(guān)鍵點(diǎn)在于路由器和處理器

服務(wù)復(fù)用器

處理器

http.ServeMux 內(nèi)部使用一個(gè) map 映射來保存所有處理器, http.muxEntry 是一個(gè)多路復(fù)用器入口實(shí)體。

可以發(fā)現(xiàn)在 http.muxEntry 字段中存在著 http.Handler 接口類型的 h

雖然 http.ServeMux 也實(shí)現(xiàn)了 http.ServerHTTP() 算得上是一個(gè) http.Handler ,但 http.ServeMux 的 http.ServeHTTP() 并非用來處理請(qǐng)求和響應(yīng),而是用來查找注冊(cè)路由對(duì)應(yīng)的處理器。

當(dāng) http.ServeMux 路由器設(shè)置路由規(guī)則后,會(huì)通過它實(shí)現(xiàn)的 ServeHTTP() 完成請(qǐng)求的分發(fā)。當(dāng)路由器接收到請(qǐng)求后若請(qǐng)求的URI為 * 則會(huì)關(guān)閉連接,否則會(huì)調(diào)用自身的 Handler() 來獲取對(duì)應(yīng)路由的處理器,最終通過調(diào)用 h.ServeHTTP(w,r) 實(shí)現(xiàn)對(duì)應(yīng)路由的實(shí)現(xiàn)邏輯。

路由器會(huì)根據(jù)用戶請(qǐng)求的URL路徑去匹配自身存儲(chǔ)的在 map 中的 handler ,最終調(diào)用匹配到的 handler 的 ServeHTTP() 以實(shí)現(xiàn)執(zhí)行對(duì)應(yīng)路由的處理函數(shù)。

創(chuàng)建 http.ServeMux 實(shí)例的方式有兩種

http.DefaultServeMux 是默認(rèn)的 http.ServeMux ,會(huì)隨著 net/http 包初始化而被自動(dòng)初始化。

當(dāng) http.ListenAndServe() 在沒有提供其他處理器的情況下,即它的入?yún)?handler 為 nil 時(shí)內(nèi)部會(huì)使用 http.DefaultServeMux 。

net/http 包提供了一組快捷的注冊(cè)路由的函數(shù) http.Handle() 、 http.HandleFunc() 來配置 http.DefaultServeMux ,快捷函數(shù)會(huì)將處理器注冊(cè)到 http.DefaultServeMux 。

二者之間的區(qū)別在于 handler 參數(shù)上

http.Handle() 的 handler 是一個(gè) http.Handler 接口實(shí)例,也就是說傳入的 handler 必須要自己提前實(shí)現(xiàn) http.Handler 接口的 ServerHTTP(ResponseWriter, *Request) 方法。

例如:將處理器放入閉包中,將參數(shù)傳入處理器。

http.HandleFunc() 的 handler 直接是一個(gè)原型為 func(ResponseWriter, *Request) 的函數(shù),深入追蹤會(huì) HandleFunc() 會(huì)發(fā)現(xiàn)一個(gè)自定義的函數(shù)類型。

因此任何具有 func(ResponseWriter, *Request) 簽名的函數(shù)都能轉(zhuǎn)換成為一個(gè) http.HandlerFunc 類型的對(duì)象。同時(shí)自定義的函數(shù)類型中已經(jīng)實(shí)現(xiàn)了 ServeHTTP() 方法,因此它也是一個(gè) http.Handler 。

例如:返回時(shí)使用一個(gè)到 http.HandlerFunc 類型的隱式轉(zhuǎn)換

net/http 包提供了 http.NewServeMux() 來創(chuàng)建一個(gè)自定義的 http.ServeMux 實(shí)例

例如:調(diào)用 http.NewServeMux() 會(huì)創(chuàng)建服務(wù)復(fù)用器

例如:創(chuàng)建靜態(tài)服務(wù)

Go中沒有繼承、多態(tài),可通過接口來實(shí)現(xiàn)。而接口則是定義聲明的函數(shù)簽名,任何結(jié)構(gòu)體只要實(shí)現(xiàn)與接口函數(shù)簽名相同的方法,即等同于實(shí)現(xiàn)了對(duì)應(yīng)的接口。

例如: http.HandleFunc() 處理函數(shù)實(shí)現(xiàn)實(shí)際上調(diào)用默認(rèn) http.DefaultServeMux 的 HandleFunc() 方法

例如:調(diào)用 http.Handle() 方法則第二個(gè)參數(shù) handle 必須實(shí)現(xiàn) http.Handler 接口的 ServeHTTP() 方法,也就是說只要具有 ServeHTTP() 簽名方法即可作為處理器。

例如:自定義處理器

http.HandlerFunc 自身已實(shí)現(xiàn) http.Handler 接口的 ServeHTTP() 方法,因此它也是一個(gè)處理器。

http.HandlerFunc 的作用是將自定義函數(shù)轉(zhuǎn)換為 http.Handler 處理器類型,當(dāng)調(diào)用 http.HandlerFunc(fn) 后會(huì)強(qiáng)制將 fn 函數(shù)類型轉(zhuǎn)換為 http.HandlerFunc 類型,這樣 fn 函數(shù)就具有了 ServeHTTP() 方法,同時(shí)也就轉(zhuǎn)換成為了一個(gè) http.Handler 處理器。因此 http.HandlerFunc 又稱為適配器。

GO語言學(xué)習(xí)系列八——GO函數(shù)(func)的聲明與使用

GO是編譯性語言,所以函數(shù)的順序是無關(guān)緊要的,為了方便閱讀,建議入口函數(shù) main 寫在最前面,其余函數(shù)按照功能需要進(jìn)行排列

GO的函數(shù) 不支持嵌套,重載和默認(rèn)參數(shù)

GO的函數(shù) 支持 無需聲明變量,可變長(zhǎng)度,多返回值,匿名,閉包等

GO的函數(shù)用 func 來聲明,且左大括號(hào) { 不能另起一行

一個(gè)簡(jiǎn)單的示例:

輸出為:

參數(shù):可以傳0個(gè)或多個(gè)值來供自己用

返回:通過用 return 來進(jìn)行返回

輸出為:

上面就是一個(gè)典型的多參數(shù)傳遞與多返回值

對(duì)例子的說明:

按值傳遞:是對(duì)某個(gè)變量進(jìn)行復(fù)制,不能更改原變量的值

引用傳遞:相當(dāng)于按指針傳遞,可以同時(shí)改變?cè)瓉淼闹?,并且消耗的?nèi)存會(huì)更少,只有4或8個(gè)字節(jié)的消耗

在上例中,返回值 (d int, e int, f int) { 是進(jìn)行了命名,如果不想命名可以寫成 (int,int,int){ ,返回的結(jié)果都是一樣的,但要注意:

當(dāng)返回了多個(gè)值,我們某些變量不想要,或?qū)嶋H用不到,我們可以使用 _ 來補(bǔ)位,例如上例的返回我們可以寫成 d,_,f := test(a,b,c) ,我們不想要中間的返回值,可以以這種形式來舍棄掉

在參數(shù)后面以 變量 ... type 這種形式的,我們就要以判斷出這是一個(gè)可變長(zhǎng)度的參數(shù)

輸出為:

在上例中, strs ...string 中, strs 的實(shí)際值是b,c,d,e,這就是一個(gè)最簡(jiǎn)單的傳遞可變長(zhǎng)度的參數(shù)的例子,更多一些演變的形式,都非常類似

在GO中 defer 關(guān)鍵字非常重要,相當(dāng)于面相對(duì)像中的析構(gòu)函數(shù),也就是在某個(gè)函數(shù)執(zhí)行完成后,GO會(huì)自動(dòng)這個(gè);

如果在多層循環(huán)中函數(shù)里,都定義了 defer ,那么它的執(zhí)行順序是先進(jìn)后出;

當(dāng)某個(gè)函數(shù)出現(xiàn)嚴(yán)重錯(cuò)誤時(shí), defer 也會(huì)被調(diào)用

輸出為

這是一個(gè)最簡(jiǎn)單的測(cè)試了,當(dāng)然還有更復(fù)雜的調(diào)用,比如調(diào)試程序時(shí),判斷是哪個(gè)函數(shù)出了問題,完全可以根據(jù) defer 打印出來的內(nèi)容來進(jìn)行判斷,非??焖?,這種留給你們?nèi)?shí)現(xiàn)

一個(gè)函數(shù)在函數(shù)體內(nèi)自己調(diào)用自己我們稱之為遞歸函數(shù),在做遞歸調(diào)用時(shí),經(jīng)常會(huì)將內(nèi)存給占滿,這是非常要注意的,常用的比如,快速排序就是用的遞歸調(diào)用

本篇重點(diǎn)介紹了GO函數(shù)(func)的聲明與使用,下一篇將介紹GO的結(jié)構(gòu) struct


當(dāng)前題目:go語言怎么入?yún)?go調(diào)用接口
文章出自:http://weahome.cn/article/hdojoi.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部