最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go?函數(shù)選項(xiàng)模式

 更新時(shí)間:2025年08月06日 09:25:17   作者:dreamw  
在?Go?語(yǔ)言中,函數(shù)選項(xiàng)模式(Functional?Options?Pattern)?是一種優(yōu)雅的設(shè)計(jì)模式,用于處理可選配置參數(shù),特別是當(dāng)配置項(xiàng)較多或可能變化時(shí),它避免了冗長(zhǎng)的構(gòu)造函數(shù)參數(shù)列表,提高了代碼的可讀性和可擴(kuò)展性,本文介紹Go函數(shù)選項(xiàng)模式,感興趣的朋友一起看看吧

熟悉 Python 開(kāi)發(fā)的同學(xué)都知道,Python 有默認(rèn)參數(shù)的存在,使得我們?cè)趯?shí)例化一個(gè)對(duì)象的時(shí)候,可以根據(jù)需要來(lái)選擇性的覆蓋某些默認(rèn)參數(shù),以此來(lái)決定如何實(shí)例化對(duì)象。當(dāng)一個(gè)對(duì)象有多個(gè)默認(rèn)參數(shù)時(shí),這個(gè)特性非常好用,能夠優(yōu)雅地簡(jiǎn)化代碼。

而 Go 語(yǔ)言從語(yǔ)法上是不支持默認(rèn)參數(shù)的,所以為了實(shí)現(xiàn)既能通過(guò)默認(rèn)參數(shù)創(chuàng)建對(duì)象,又能通過(guò)傳遞自定義參數(shù)創(chuàng)建對(duì)象,我們就需要通過(guò)一些編程技巧來(lái)實(shí)現(xiàn)。對(duì)于這些程序開(kāi)發(fā)中的常見(jiàn)問(wèn)題,軟件行業(yè)的先行者們總結(jié)了許多解決常見(jiàn)場(chǎng)景編碼問(wèn)題的最佳實(shí)踐,這些最佳實(shí)踐后來(lái)成為了我們所說(shuō)的設(shè)計(jì)模式。其中選項(xiàng)模式在 Go 語(yǔ)言開(kāi)發(fā)中會(huì)經(jīng)常用到。

核心思想

定義一個(gè) Option 函數(shù)類(lèi)型,接收目標(biāo)結(jié)構(gòu)體的指針
創(chuàng)建多個(gè)返回 Option 的配置函數(shù)(通常以 With 開(kāi)頭)
在構(gòu)造函數(shù)中使用可變參數(shù)接收這些選項(xiàng)函數(shù)

通常我們有以下三種方法來(lái)實(shí)現(xiàn)通過(guò)默認(rèn)參數(shù)創(chuàng)建對(duì)象,以及通過(guò)傳遞自定義參數(shù)創(chuàng)建對(duì)象:

  • 使用多個(gè)構(gòu)造函數(shù)
  • 默認(rèn)參數(shù)選項(xiàng)
  • 選項(xiàng)模式

通過(guò)多構(gòu)造函數(shù)實(shí)現(xiàn)

第一種方式是通過(guò)多構(gòu)造函數(shù)實(shí)現(xiàn),下面是一個(gè)簡(jiǎn)單例子:

package main
import "fmt"
const (
    defaultAddr = "127.0.0.1"
    defaultPort = 8000
)
type Server struct {
    Addr string
    Port int
}
func NewServer() *Server {
    return &Server{
        Addr: defaultAddr,
        Port: defaultPort,
    }
}
func NewServerWithOptions(addr string, port int) *Server {
    return &Server{
        Addr: addr,
        Port: port,
    }
}
func main() {
    s1 := NewServer()
    s2 := NewServerWithOptions("localhost", 8001)
    fmt.Println(s1)  // &{127.0.0.1 8000}
    fmt.Println(s2)  // &{localhost 8001}
}

這里我們?yōu)?Server 結(jié)構(gòu)體實(shí)現(xiàn)了兩個(gè)構(gòu)造函數(shù):

  • NewServer:無(wú)需傳遞參數(shù)即可直接返回 Server 對(duì)象
  • NewServerWithOptions :需要傳遞 addr 和 port 兩個(gè)參數(shù)來(lái)構(gòu)造 Server 對(duì)象

如果通過(guò)默認(rèn)參數(shù)創(chuàng)建的對(duì)象即可滿(mǎn)足需求,不需要對(duì) Server 進(jìn)行定制時(shí),我們可以使用 NewServer 來(lái)生成對(duì)象(s1)。而如果需要對(duì) Server 進(jìn)行定制時(shí),我們則可以使用 NewServerWithOptions 來(lái)生成對(duì)象(s2)。

通過(guò)默認(rèn)參數(shù)選項(xiàng)實(shí)現(xiàn)

另外一種實(shí)現(xiàn)默認(rèn)參數(shù)的方案,是為要生成的結(jié)構(gòu)體對(duì)象定義一個(gè)選項(xiàng)結(jié)構(gòu)體,用來(lái)生成要?jiǎng)?chuàng)建對(duì)象的默認(rèn)參數(shù),代碼實(shí)現(xiàn)如下:

package main
import "fmt"
const (
    defaultAddr = "127.0.0.1"
    defaultPort = 8000
)
type Server struct {
    Addr string
    Port int
}
type ServerOptions struct {
    Addr string
    Port int
}
func NewServerOptions() *ServerOptions {
    return &ServerOptions{
        Addr: defaultAddr,
        Port: defaultPort,
    }
}
func NewServerWithOptions(opts *ServerOptions) *Server {
    return &Server{
        Addr: opts.Addr,
        Port: opts.Port,
    }
}
func main() {
    s1 := NewServerWithOptions(NewServerOptions())
    s2 := NewServerWithOptions(&ServerOptions{
        Addr: "localhost",
        Port: 8001,
    })
    fmt.Println(s1)  // &{127.0.0.1 8000}
    fmt.Println(s2)  // &{localhost 8001}
}

我們?yōu)?Server 結(jié)構(gòu)體專(zhuān)門(mén)實(shí)現(xiàn)了一個(gè) ServerOptions 用來(lái)生成默認(rèn)參數(shù),調(diào)用 NewServerOptions 函數(shù)即可獲得默認(rèn)參數(shù)配置,構(gòu)造函數(shù) NewServerWithOptions 接收一個(gè) *ServerOptions 類(lèi)型作為參數(shù)。所以我們可以通過(guò)以下兩種方式來(lái)完成功能:

  • 直接將調(diào)用 NewServerOptions 函數(shù)的返回值傳遞給 NewServerWithOptions 來(lái)實(shí)現(xiàn)通過(guò)默認(rèn)參數(shù)生成對(duì)象(s1)
  • 通過(guò)手動(dòng)構(gòu)造 ServerOptions 配置來(lái)生成定制對(duì)象(s2)

通過(guò)選項(xiàng)模式實(shí)現(xiàn)

以上兩種方式雖然都能夠完成功能,但卻有以下缺點(diǎn):

  • 通過(guò)多構(gòu)造函數(shù)實(shí)現(xiàn)的方案需要我們?cè)趯?shí)例化對(duì)象時(shí)分別調(diào)用不同的構(gòu)造函數(shù),代碼封裝性不強(qiáng),會(huì)給調(diào)用者增加使用負(fù)擔(dān)。
  • 通過(guò)默認(rèn)參數(shù)選項(xiàng)實(shí)現(xiàn)的方案需要我們預(yù)先構(gòu)造一個(gè)選項(xiàng)結(jié)構(gòu),當(dāng)使用默認(rèn)參數(shù)生成對(duì)象時(shí)代碼看起來(lái)比較冗余。

而選項(xiàng)模式可以讓我們更為優(yōu)雅地解決這個(gè)問(wèn)題。代碼實(shí)現(xiàn)如下:

package main
import "fmt"
const (
    defaultAddr = "127.0.0.1"
    defaultPort = 8000
)
type Server struct {
    Addr string
    Port int
}
type ServerOptions struct {
    Addr string
    Port int
}
type ServerOption interface {
    apply(*ServerOptions)
}
type FuncServerOption struct {
    f func(*ServerOptions)
}
func (fo FuncServerOption) apply(option *ServerOptions) {
    fo.f(option)
}
func WithAddr(addr string) ServerOption {
    return FuncServerOption{
        f: func(options *ServerOptions) {
            options.Addr = addr
        },
    }
}
func WithPort(port int) ServerOption {
    return FuncServerOption{
        f: func(options *ServerOptions) {
            options.Port = port
        },
    }
}
func NewServer(opts ...ServerOption) *Server {
    options := ServerOptions{
        Addr: defaultAddr,
        Port: defaultPort,
    }
    for _, opt := range opts {
        opt.apply(&options)
    }
    return &Server{
        Addr: options.Addr,
        Port: options.Port,
    }
}
func main() {
    s1 := NewServer()
    s2 := NewServer(WithAddr("localhost"), WithPort(8001))
    s3 := NewServer(WithPort(8001))
    fmt.Println(s1)  // &{127.0.0.1 8000}
    fmt.Println(s2)  // &{localhost 8001}
    fmt.Println(s3)  // &{127.0.0.1 8001}
}

乍一看我們的代碼復(fù)雜了很多,但其實(shí)調(diào)用構(gòu)造函數(shù)生成對(duì)象的代碼復(fù)雜度是沒(méi)有改變的,只是定義上的復(fù)雜。

我們定義了 ServerOptions 結(jié)構(gòu)體用來(lái)配置默認(rèn)參數(shù)。因?yàn)?Addr 和 Port 都有默認(rèn)參數(shù),所以 ServerOptions 的定義和 Server 定義是一樣的。但有一定復(fù)雜性的結(jié)構(gòu)體中可能會(huì)有些參數(shù)沒(méi)有默認(rèn)參數(shù),必須讓用戶(hù)來(lái)配置,這時(shí) ServerOptions 的字段就會(huì)少一些,大家可以按需定義。

同時(shí),我們還定義了一個(gè) ServerOption 接口和實(shí)現(xiàn)了此接口的 FuncServerOption 結(jié)構(gòu)體,它們的作用是讓我們能夠通過(guò) apply 方法為 ServerOptions 結(jié)構(gòu)體單獨(dú)配置某項(xiàng)參數(shù)。

我們可以分別為每個(gè)默認(rèn)參數(shù)都定義一個(gè) WithXXX 函數(shù)用來(lái)配置參數(shù),如這里定義的 WithAddr 和 WithPort ,這樣用戶(hù)就可以通過(guò)調(diào)用 WithXXX 函數(shù)來(lái)定制需要覆蓋的默認(rèn)參數(shù)。

此時(shí)默認(rèn)參數(shù)定義在構(gòu)造函數(shù) NewServer 中,構(gòu)造函數(shù)的接收一個(gè)不定長(zhǎng)參數(shù),類(lèi)型為 ServerOption,在構(gòu)造函數(shù)內(nèi)部通過(guò)一個(gè) for 循環(huán)調(diào)用每個(gè)傳進(jìn)來(lái)的 ServerOption 對(duì)象的 apply 方法,將用戶(hù)配置的參數(shù)依次賦值給構(gòu)造函數(shù)內(nèi)部的默認(rèn)參數(shù)對(duì)象 options 中,以此來(lái)替換默認(rèn)參數(shù),for 循環(huán)執(zhí)行完成后,得到的 options 對(duì)象將是最終配置,將其屬性依次賦值給 Server 即可生成新的對(duì)象。

總結(jié)

通過(guò) s2 和 s3 的打印結(jié)果可以發(fā)現(xiàn),使用選項(xiàng)模式實(shí)現(xiàn)的構(gòu)造函數(shù)更加靈活,相較于前兩種實(shí)現(xiàn),選項(xiàng)模式中我們可以自由的更改其中任意一項(xiàng)或多項(xiàng)默認(rèn)配置。

雖然選項(xiàng)模式確實(shí)會(huì)多寫(xiě)一些代碼,但多數(shù)情況下這都是值得的。比如 Google 的 gRPC 框架 Go 語(yǔ)言實(shí)現(xiàn)中創(chuàng)建 gRPC server 的構(gòu)造函數(shù) NewServer 就使用了選項(xiàng)模式,感興趣的同學(xué)可以看下其源碼的實(shí)現(xiàn)思想其實(shí)和這里的示例程序如出一轍。

以上就是我關(guān)于 Golang 選項(xiàng)模式的一點(diǎn)經(jīng)驗(yàn),希望今天的分享能夠給你帶來(lái)一些幫助。

推薦閱讀

服務(wù)端渲染基礎(chǔ)

云原生灰度更新實(shí)踐

到此這篇關(guān)于Go 函數(shù)選項(xiàng)模式的文章就介紹到這了,更多相關(guān)go 函數(shù)選項(xiàng)模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • golang獲取當(dāng)前時(shí)間、時(shí)間戳和時(shí)間字符串及它們之間的相互轉(zhuǎn)換方法

    golang獲取當(dāng)前時(shí)間、時(shí)間戳和時(shí)間字符串及它們之間的相互轉(zhuǎn)換方法

    這篇文章主要介紹了golang獲取當(dāng)前時(shí)間、時(shí)間戳和時(shí)間字符串及它們之間的相互轉(zhuǎn)換,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧
    2025-04-04
  • Go語(yǔ)言開(kāi)發(fā)中有了net/http為什么還要有g(shù)in的原理及使用場(chǎng)景解析

    Go語(yǔ)言開(kāi)發(fā)中有了net/http為什么還要有g(shù)in的原理及使用場(chǎng)景解析

    這篇文章主要為大家介紹了Go語(yǔ)言有了net/http標(biāo)準(zhǔn)庫(kù)為什么還要有g(shù)in第三方庫(kù)的原理及使用場(chǎng)景詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • 淺析Golang中類(lèi)型嵌入的簡(jiǎn)介與使用

    淺析Golang中類(lèi)型嵌入的簡(jiǎn)介與使用

    類(lèi)型嵌入指的就是在一個(gè)類(lèi)型的定義中嵌入了其他類(lèi)型,Go?語(yǔ)言支持兩種類(lèi)型嵌入,分別是接口類(lèi)型的類(lèi)型嵌入和結(jié)構(gòu)體類(lèi)型的類(lèi)型嵌入,下面我們就來(lái)詳細(xì)一下類(lèi)型嵌入的使用吧
    2023-11-11
  • golang利用不到20行代碼實(shí)現(xiàn)路由調(diào)度詳解

    golang利用不到20行代碼實(shí)現(xiàn)路由調(diào)度詳解

    這篇文章主要給大家介紹了關(guān)于golang利用不到20行代碼實(shí)現(xiàn)路由調(diào)度的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-08-08
  • Go標(biāo)準(zhǔn)庫(kù)Flag庫(kù)和Log庫(kù)的使用

    Go標(biāo)準(zhǔn)庫(kù)Flag庫(kù)和Log庫(kù)的使用

    本文主要介紹了Go標(biāo)準(zhǔn)庫(kù)Flag庫(kù)和Log庫(kù)的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-05-05
  • 基于Go語(yǔ)言實(shí)現(xiàn)高性能文件上傳下載系統(tǒng)

    基于Go語(yǔ)言實(shí)現(xiàn)高性能文件上傳下載系統(tǒng)

    在Web應(yīng)用開(kāi)發(fā)中,文件上傳下載是一個(gè)非常常見(jiàn)的需求,本文將介紹如何使用Go語(yǔ)言實(shí)現(xiàn)一個(gè)安全、高效的本地文件存儲(chǔ)系統(tǒng),感興趣的小伙伴可以了解下
    2025-03-03
  • Go語(yǔ)言數(shù)據(jù)結(jié)構(gòu)之單鏈表的實(shí)例詳解

    Go語(yǔ)言數(shù)據(jù)結(jié)構(gòu)之單鏈表的實(shí)例詳解

    鏈表由一系列結(jié)點(diǎn)(鏈表中每一個(gè)元素稱(chēng)為結(jié)點(diǎn))組成,結(jié)點(diǎn)可以在運(yùn)行時(shí)動(dòng)態(tài)生成。本文將通過(guò)五個(gè)例題帶大家深入了解Go語(yǔ)言中單鏈表的用法,感興趣的可以了解一下
    2022-08-08
  • Go語(yǔ)言實(shí)現(xiàn)配置熱加載的方法分享

    Go語(yǔ)言實(shí)現(xiàn)配置熱加載的方法分享

    web項(xiàng)目,經(jīng)常需要熱啟動(dòng)各種各樣的配置信息,一旦這些服務(wù)發(fā)生變更,我們需要重新啟動(dòng)web server,以使配置生效,實(shí)現(xiàn)配置熱加載,本文為大家整理了幾個(gè)方法實(shí)現(xiàn)這個(gè)需求,需要的可以參考下
    2023-05-05
  • go mod 安裝依賴(lài) unkown revision問(wèn)題的解決方案

    go mod 安裝依賴(lài) unkown revision問(wèn)題的解決方案

    這篇文章主要介紹了go mod 安裝依賴(lài) unkown revision問(wèn)題的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-05-05
  • golang log4go的日志輸出優(yōu)化詳解

    golang log4go的日志輸出優(yōu)化詳解

    log4go源于google的一項(xiàng)log工程,但官方已經(jīng)停止維護(hù)更新,下面這篇文章主要給大家介紹了關(guān)于golang log4go的日志輸出優(yōu)化的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。
    2017-12-12

最新評(píng)論

沾化县| 吴忠市| 达尔| 海丰县| 峡江县| 永寿县| 马鞍山市| 三亚市| 夏河县| 仁化县| 卓尼县| 津市市| 临桂县| 泗水县| 龙海市| 沙河市| 南丹县| 多伦县| 黄陵县| 安吉县| 曲麻莱县| 宾川县| 静安区| 肃北| 洞口县| 任丘市| 忻城县| 建宁县| 郁南县| 尼勒克县| 荔浦县| 扎赉特旗| 姚安县| 资阳市| 晴隆县| 合作市| 石家庄市| 湘乡市| 县级市| 盘山县| 宁波市|