golang 設計模式之選項模式

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

有時候一個函數會有很多參數,為了方便函數的使用,我們會給希望給一些參數設定預設值,調用時只需要傳與預設值不同的參數即可,類似於 python 裡面的預設參數和字典參數,雖然 golang 裡面既沒有預設參數也沒有字典參數,但是我們有選項模式

可變長參數列表

在這之前,首先需要介紹一下可變長參數列表,顧名思義,就是參數的個數不固定,可以是一個也可以是多個,最典型的用法就是標準庫裡面的 fmt.Printf,文法比較簡單,如下面例子實現任意多個參數的加法

func add(nums ...int) int {    sum := 0    for _, num := range nums {        sum += num    }    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) {    fmt.Println(requiredStr, str1, str2, int1, int2)}// 調用方法MyFunc1("requiredStr", "defaultStr1", "defaultStr2", 1, 2)

這種實現比較簡單,但是同時傳入參數較多,對調用方來說,使用的成本就會比較高,而且每個參數的具體含義這裡並不清晰,很容易出錯

那選項模式怎麼實現這個需求呢?先來看下最終的效果

MyFunc2("requiredStr")MyFunc2("requiredStr", WithOptionStr1("mystr1"))MyFunc2("requiredStr", WithOptionStr2AndInt2("mystr2", 22), WithOptionInt1(11))

如上面代碼所示,你可以根據自己的需求選擇你需要傳入的參數,大大簡化了函數調用的複雜度,並且每個參數都有了清晰明確的含義

那怎麼實現上面的功能呢

定義可選項和預設值

首先定義可選項和預設值,這裡有4個可選項,第一個參數為必填項

type MyFuncOptions struct {    optionStr1 string    optionStr2 string    optionInt1 int    optionInt2 int}var defaultMyFuncOptions = MyFuncOptions{    optionStr1: "defaultStr1",    optionStr2: "defaultStr2",    optionInt1: 1,    optionInt2: 2,}

實現 With 方法

這些 With 方法看起來有些古怪,接受一個選項參數,返回一個選項方法,而選項方法以選項作為參數負責修改選項的值,如果沒看明白沒關係,可以先看函數功能如何?

type MyFuncOption func(options *MyFuncOptions)func WithOptionStr1(str1 string) MyFuncOption {    return func(options *MyFuncOptions) {        options.optionStr1 = str1    }}func WithOptionInt1(int1 int) MyFuncOption {    return func(options *MyFuncOptions) {        options.optionInt1 = int1    }}func WithOptionStr2AndInt2(str2 string, int2 int) MyFuncOption {    return func(options *MyFuncOptions) {        options.optionStr2 = str2        options.optionInt2 = int2    }}

這裡我們讓 optionStr2 和 optionInt2 合并一起設定,實際應用情境中可以用這種方式將相關的參數放到一起設定

實現函數功能

func MyFunc2(requiredStr string, opts ...MyFuncOption) {    options := defaultMyFuncOptions    for _, o := range opts {        o(&options)    }    fmt.Println(requiredStr, options.optionStr1, options.optionStr2, options.optionInt1, options.optionInt2)}

使用 With 方法返回的選項方法作為參數列表,用這些方法去設定選項

選項模式的應用

從這裡可以看到,為了實現選項的功能,我們增加了很多的代碼,實現成本相對還是較高的,所以實踐中需要根據自己的業務情境去權衡是否需要使用。個人總結滿足下麵條件可以考慮使用選項模式

  1. 參數確實比較複雜,影響調用方使用
  2. 參數確實有比較清晰明確的預設值
  3. 為參數的後續拓展考慮

在 golang 的很多開源項目裡面也用到了選項模式,比如 grpc 中的 rpc 方法就是採用選項模式設計的,除了必填的 rpc 參數外,還可以一些選項參數,grpc_retry 就是通過這個機制實現的,可以實現自動重試功能

參考連結

  • Go 函數式選項模式:https://studygolang.com/artic...
  • Functional Options Pattern in Go:https://halls-of-valhalla.org...
轉載請註明出處
本文連結:http://hatlonely.github.io/20...

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.