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

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

go語言函數(shù)式庫 go語言cobra

Go語言實踐模式 - 函數(shù)選項模式(Functional Options Pattern)

大家好,我是小白,有點黑的那個白。

成都創(chuàng)新互聯(lián)自2013年創(chuàng)立以來,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項目網(wǎng)站設(shè)計、成都網(wǎng)站設(shè)計網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元港閘做網(wǎng)站,已為上家服務(wù),為港閘各地企業(yè)和個人服務(wù),聯(lián)系電話:028-86922220

最近遇到一個問題,因為業(yè)務(wù)需求,需要對接第三方平臺.

而三方平臺提供的一些HTTP(S)接口都有統(tǒng)一的密鑰生成規(guī)則要求.

為此我們封裝了一個獨立的包 xxx-go-sdk 以便維護和對接使用.

其中核心的部分是自定義HTTP Client,如下:

一些平臺會要求appKey/appSecret等信息,所以Client結(jié)構(gòu)體就變成了這樣,這時參數(shù)還比較少, 而且是必填的參數(shù),我們可以提供構(gòu)造函數(shù)來明確指定。

看起來很滿足,但是當(dāng)我們需要增加一個 Timeout 參數(shù)來控制超時呢?

或許你會說這還不簡單,像下面一樣再加一個參數(shù)唄

那再加些其他的參數(shù)呢?那構(gòu)造函數(shù)的參數(shù)是不是又長又串,而且每個參數(shù)不一定是必須的,有些參數(shù)我們又會考慮默認值的問題。

為此,勤勞但尚未致富的 gophers 們使用了總結(jié)一種實踐模式

首先提取所有需要的參數(shù)到一個獨立的結(jié)構(gòu)體 Options,當(dāng)然你也可以用 Configs 啥的.

然后為每個參數(shù)提供設(shè)置函數(shù)

這樣我們就為每個參數(shù)設(shè)置了獨立的設(shè)置函數(shù)。返回值 func(*Options) 看著有點不友好,我們提取下定義為單個 Option 調(diào)整一下代碼

當(dāng)我們需要添加更多的參數(shù)時,只需要在 Options 添加新的參數(shù)并添加新參數(shù)的設(shè)置函數(shù)即可。

比如現(xiàn)在要添加新的參數(shù) Timeout

這樣后續(xù)不管新增多少參數(shù),只需要新增配置項并添加獨立的設(shè)置函數(shù)即可輕松擴展,并且不會影響原有函數(shù)的參數(shù)順序和個數(shù)位置等。

至此,每個選項是區(qū)分開來了,那么怎么作用到我們的 Client 結(jié)構(gòu)體上呢?

首先,配置選項都被提取到了 Options 結(jié)構(gòu)體重,所以我們需要調(diào)整一下 Client 結(jié)構(gòu)體的參數(shù)

其次,每一個選項函數(shù)返回 Option,那么任意多個就是 ...Option,我們調(diào)整一下構(gòu)造函數(shù) NewClient 的參數(shù)形式,改為可變參數(shù),不再局限于固定順序的幾個參數(shù)。

然后循環(huán)遍歷每個選項函數(shù),來生成Client結(jié)構(gòu)體的完整配置選項。

那么怎么調(diào)用呢?對于調(diào)用方而已,直接在調(diào)用構(gòu)造函數(shù)NewClient()的參數(shù)內(nèi)添加自己需要的設(shè)置函數(shù)(WithXXX)即可

當(dāng)需要設(shè)置超時參數(shù),直接添加 WithTimeout即可,比如設(shè)置3秒的超時

配置選項的位置可以任意設(shè)置,不需要受常規(guī)的固定參數(shù)順序約束。

可以看到,這種實踐模式主要作用于配置選項,利用函數(shù)支持的特性來實現(xiàn)的,為此得名 Functional Options Pattern,優(yōu)美的中國話叫做「函數(shù)選項模式」。

最后, 我們總結(jié)回顧一下在Go語言中函數(shù)選項模式的優(yōu)缺點

如何看待go語言泛型的最新設(shè)計?

Go 由于不支持泛型而臭名昭著,但最近,泛型已接近成為現(xiàn)實。Go 團隊實施了一個看起來比較穩(wěn)定的設(shè)計草案,并且正以源到源翻譯器原型的形式獲得關(guān)注。本文講述的是泛型的最新設(shè)計,以及如何自己嘗試泛型。

例子

FIFO Stack

假設(shè)你要創(chuàng)建一個先進先出堆棧。沒有泛型,你可能會這樣實現(xiàn):

type?Stack?[]interface{}func?(s?Stack)?Peek()?interface{}?{

return?s[len(s)-1]

}

func?(s?*Stack)?Pop()?{

*s?=?(*s)[:

len(*s)-1]

}

func?(s?*Stack)?Push(value?interface{})?{

*s?=?

append(*s,?value)

}

但是,這里存在一個問題:每當(dāng)你 Peek 項時,都必須使用類型斷言將其從 interface{} 轉(zhuǎn)換為你需要的類型。如果你的堆棧是 *MyObject 的堆棧,則意味著很多 s.Peek().(*MyObject)這樣的代碼。這不僅讓人眼花繚亂,而且還可能引發(fā)錯誤。比如忘記 * 怎么辦?或者如果您輸入錯誤的類型怎么辦?s.Push(MyObject{})` 可以順利編譯,而且你可能不會發(fā)現(xiàn)到自己的錯誤,直到它影響到你的整個服務(wù)為止。

通常,使用 interface{} 是相對危險的。使用更多受限制的類型總是更安全,因為可以在編譯時而不是運行時發(fā)現(xiàn)問題。

泛型通過允許類型具有類型參數(shù)來解決此問題:

type?Stack(type?T)?[]Tfunc?(s?Stack(T))?Peek()?T?{

return?s[len(s)-1]

}

func?(s?*Stack(T))?Pop()?{

*s?=?(*s)[:

len(*s)-1]

}

func?(s?*Stack(T))?Push(value?T)?{

*s?=?

append(*s,?value)

}

這會向 Stack 添加一個類型參數(shù),從而完全不需要 interface{}?,F(xiàn)在,當(dāng)你使用 Peek() 時,返回的值已經(jīng)是原始類型,并且沒有機會返回錯誤的值類型。這種方式更安全,更容易使用。(譯注:就是看起來更丑陋,^-^)

此外,泛型代碼通常更易于編譯器優(yōu)化,從而獲得更好的性能(以二進制大小為代價)。如果我們對上面的非泛型代碼和泛型代碼進行基準(zhǔn)測試,我們可以看到區(qū)別:

type?MyObject?struct?{

X?

int

}

var?sink?MyObjectfunc?BenchmarkGo1(b?*testing.B)?{

for?i?:=?0;?i??b.N;?i++?{

var?s?Stack

s.Push(MyObject{})

s.Push(MyObject{})

s.Pop()

sink?=?s.Peek().(MyObject)

}

}

func?BenchmarkGo2(b?*testing.B)?{

for?i?:=?0;?i??b.N;?i++?{

var?s?Stack(MyObject)

s.Push(MyObject{})

s.Push(MyObject{})

s.Pop()

sink?=?s.Peek()

}

}

結(jié)果:

BenchmarkGo1BenchmarkGo1-16?????12837528?????????87.0?ns/op???????48?B/op????????2?allocs/opBenchmarkGo2BenchmarkGo2-16?????28406479?????????41.9?ns/op???????24?B/op????????2?allocs/op

在這種情況下,我們分配更少的內(nèi)存,同時泛型的速度是非泛型的兩倍。

合約(Contracts)

上面的堆棧示例適用于任何類型。但是,在許多情況下,你需要編寫僅適用于具有某些特征的類型的代碼。例如,你可能希望堆棧要求類型實現(xiàn) String() 函數(shù)

Go語言os標(biāo)準(zhǔn)庫常用方法Getwd/Getenv/Chdir

1. os.Getwd()函數(shù)

原型:func Getwd()(pwd string, err error)

作用:獲取當(dāng)前文件路徑

返回:當(dāng)前文件路徑的字符串和一個err信息

示例:

輸出:

當(dāng)前路徑: D:ProjectsGomGoLab01

2. os.Getenv()函數(shù)

原型:func Getenv(key string) string

作用:獲取系統(tǒng)環(huán)境變量的值

參數(shù):key - 系統(tǒng)環(huán)境變量名

返回:系統(tǒng)環(huán)境變量的值

示例:

輸出:

環(huán)境變量GOPATH的值是: D:/Projects/Go

3. os.Chdir()函數(shù)

原型:func Chdir(dir string) error

作用:將當(dāng)前文件路徑改變?yōu)槟繕?biāo)路徑(非真實改變)

參數(shù):dir - 目標(biāo)路徑(即改變之后的路徑)

返回:修改成功,返回 nil;修改失?。ㄈ纾耗繕?biāo)路徑不存在的情況),返回錯誤信息。

示例一:

輸出:

起始路徑: D:ProjectsGomGoLab01

修改后的路徑: D:ProjectsGoDemo02

示例二:

輸出:

起始路徑: D:ProjectsGomGoLab01

error: chdir D:ProjectsGoDemo03: The system cannot find the file specified.

注:文件路徑,Window 系統(tǒng)下默認是“”,寫在代碼中時要用“”或“/”代替。


當(dāng)前名稱:go語言函數(shù)式庫 go語言cobra
轉(zhuǎn)載來于:http://weahome.cn/article/dohspii.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部