有時候乙個函式會有很多引數,為了方便函式的使用,我們會給希望給一些引數設定預設值,呼叫時只需要傳與預設值不同的引數即可,類似於 python 裡面的預設引數和字典引數,雖然 golang 裡面既沒有預設引數也沒有字典引數,但是我們有選項模式
在這之前,首先需要介紹一下可變長引數列表,顧名思義,就是引數的個數不固定,可以是乙個也可以是多個,最典型的用法就是標準庫裡面的fmt.printf
,語法比較簡單,如下面例子實現任意多個引數的加法
func add(nums ...int) int
return sum
}so(add(1,2), shouldequal,3)
so(add(1,2,3), shouldequal,6)
在型別前面加...
來表示這個型別的變長引數列表,使用上把引數當成slice
來用即可
假設我們要實現這樣乙個函式,這個函式接受5個引數,三個string
(其中第乙個引數是必填引數),兩個int
,這裡功能只是簡單輸出這個引數,於是我們可以簡單用如下**實現
func myfunc1(requiredstr string, str1 string, str2 string, int1 int, int2 int)
// 呼叫方法
myfunc1("requiredstr", "defaultstr1", "defaultstr2",1,2)
這種實現比較簡單,但是同時傳入引數較多,對呼叫方來說,使用的成本就會比較高,而且每個引數的具體含義這裡並不清晰,很容易出錯
那選項模式怎麼實現這個需求呢?先來看下最終的效果
myfunc2("requiredstr")
myfunc2("requiredstr", withoptionstr1("mystr1"))
myfunc2("requiredstr", withoptionstr2andint2("mystr2",22), withoptionint1(11))
如上面**所示,你可以根據自己的需求選擇你需要傳入的引數,大大簡化了函式呼叫的複雜度,並且每個引數都有了清晰明確的含義
那怎麼實現上面的功能呢
定義可選項和預設值
首先定義可選項和預設值,這裡有4個可選項,第乙個引數為必填項
type myfuncoptions struct
var defaultmyfuncoptions = myfuncoptions
實現 with 方法
這些 with 方法看起來有些古怪,接受乙個選項引數,返回乙個選項方法,而選項方法以選項作為引數負責修改選項的值,如果沒看明白沒關係,可以先看函式功能如何實現
type myfuncoption func(options *myfuncoptions)
func withoptionstr1(str1 string) myfuncoption
}func withoptionint1(int1 int) myfuncoption
}func withoptionstr2andint2(str2 string, int2 int) myfuncoption
}
這裡我們讓 optionstr2 和 optionint2 合併一起設定,實際應用場景中可以用這種方式將相關的引數放到一起設定
實現函式功能
func myfunc2(requiredstr string, opts ...myfuncoption)
fmt.println(requiredstr, options.optionstr1, options.optionstr2, options.optionint1, options.optionint2)
}
使用 with 方法返回的選項方法作為引數列表,用這些方法去設定選項
從這裡可以看到,為了實現選項的功能,我們增加了很多的**,實現成本相對還是較高的,所以實踐中需要根據自己的業務場景去權衡是否需要使用。個人總結滿足下面條件可以考慮使用選項模式
引數確實比較複雜,影響呼叫方使用
引數確實有比較清晰明確的預設值
為引數的後續拓展考慮
在 golang 的很多開源專案裡面也用到了選項模式,比如 grpc 中的 rpc 方法就是採用選項模式設計的,除了必填的 rpc 引數外,還可以一些選項引數,grpc_retry 就是通過這個機制實現的,可以實現自動重試功能
Golang 選項模式(Option模式)
option模式的專業術語為 functional options pattern 函式式選項模式 option模式為golang的開發者提供了將乙個函式的引數設定為可選的功能,也就是說我們可以選擇引數中的某幾個,並且可以按任意順序傳入引數。比如針對特殊場景需要不同引數的情況,c 可以直接用過載來寫...
golang設計模式之建造者模式
最近一直在寫框架,這個系列也好久沒更新了,抽時間更新一篇 wiki 建造者模式 builder pattern 將乙個複雜物件的構建與它的表示分離,使得同樣的構建過程可以建立不同的表示。直白一點的說,就是將我們在開發過程中遇到的大型物件,拆分成多個小物件,然後將多個小物件組裝成大物件,並且對外部隱藏...
golang設計模式之單例模式
保證乙個類只有乙個例項,並且提供乙個訪問該例項的全域性訪問點 由於單例模式只生成乙個例項,減少系統效能開銷,當乙個物件的生產需要比較多資源時,就可以通過在應用啟動的時候直接產生乙個單例物件,然後永久駐留記憶體,例如日誌模組 單例模式可以在系統設定全域性訪問點,優化資源共享問題,比如資料庫裡連線池 餓...