golang給函數(shù)參數(shù)設(shè)置默認(rèn)值的幾種方式小結(jié)(函數(shù)參數(shù)默認(rèn)值
前言
這個(gè)問題相當(dāng)麻煩,根據(jù)golang-nuts/google groups中的這篇文章,golang現(xiàn)在與將來都不會支持參數(shù)默認(rèn)值。Go始終在使得自己變得盡可能的簡單,而增加這種額外的支持會使parser變得更復(fù)雜。
設(shè)置參數(shù)值的好處:
- 可以缺省部分參數(shù)。
- 可以提供一種默認(rèn)的,行之有效的配置。
但是參考資料中提到了幾種實(shí)現(xiàn)默認(rèn)值的方法:
強(qiáng)制改變
// Both parameters are optional, use empty string for default value func Concat1(a string, b int) string { if a == "" { a = "default-a" } if b == 0 { b = 5 } return fmt.Sprintf("%s%d", a, b) }
go的一大特點(diǎn)就是所有的變量都必須經(jīng)過初始化。那如果在函數(shù)內(nèi)部讀取到參數(shù)值為初始化值,即可進(jìn)行對應(yīng)的操作。 但是這種方法無法解決設(shè)置參數(shù)默認(rèn)值時(shí)所經(jīng)常應(yīng)對的場景,即參數(shù)缺省問題。
使用可變參數(shù)語法糖
// a is required, b is optional. // Only the first value in b_optional will be used. func Concat2(a string, b_optional ...int) string { b := 5 if len(b_optional) > 0 { b = b_optional[0] } return fmt.Sprintf("%s%d", a, b) }
上述方法中,a是必須的,而b是可選的。 此時(shí)b的默認(rèn)值時(shí)5,如果b_optional中存在數(shù)據(jù),則將其讀取。
利用結(jié)構(gòu)體的config
// A declarative default value syntax // Empty values will be replaced with defaults type Parameters struct { A string `default:"default-a"` // this only works with strings B string // default is 5 } func Concat3(prm Parameters) string { typ := reflect.TypeOf(prm) if prm.A == "" { f, _ := typ.FieldByName("A") prm.A = f.Tag.Get("default") } if prm.B == 0 { prm.B = 5 } return fmt.Sprintf("%s%d", prm.A, prm.B) }
雖然也能做到缺省參數(shù)(如果不設(shè)置A屬性,則該屬性將被默認(rèn)初始化),但是這種方式只對字符串管用。
轉(zhuǎn)換函數(shù)的全部參數(shù)
func Concat4(args ...interface{}) string { a := "default-a" b := 5 for _, arg := range args { switch t := arg.(type) { case string: a = t case int: b = t default: panic("Unknown argument") } } return fmt.Sprintf("%s%d", a, b) }
相當(dāng)泛用的方法,但是對于不同的類型就不可行了。
補(bǔ)充知識:Golang中設(shè)置函數(shù)默認(rèn)參數(shù)的優(yōu)雅實(shí)現(xiàn)
在Golang中,我們經(jīng)常碰到要設(shè)置一個(gè)函數(shù)的默認(rèn)值,或者說我定義了參數(shù)值,但是又不想傳遞值,這個(gè)在python或php一類的語言中很好實(shí)現(xiàn),但Golang中好像這種方法又不行。今天在看Grpc源碼時(shí),發(fā)現(xiàn)了一個(gè)方法可以很優(yōu)雅的實(shí)現(xiàn),叫做 Functional Options Patter.通過定義函數(shù)的方式來實(shí)現(xiàn)
比如我們以如下的構(gòu)造函數(shù)為例說明下,用這個(gè)的好處
func NewClient(address string,timeout,trynums int){}
如果我們要實(shí)例化這個(gè)函數(shù),timeout,trynums這個(gè)是必須要傳的,那如果我不想傳呢,一般可能是通過傳對象(struct,map)或定義多個(gè)func,感覺都不太方便。
func NewClient(address string){} func NewClientNoTimeout(address string,trynums int){}
另一種傳一個(gè)對象
type Options struct{ timeout int, trynums int } func NewClient(address string,opts Options){}
用對象的形式,還得檢查參數(shù)的合法性。比如傳遞了不存在的參數(shù)等。
那么,我們看下用Functional Options Patter的方式,我寫了一個(gè)簡單的例子。
package main import "fmt" //如何向func傳遞默認(rèn)值 type dialOption struct { Username string Password string Service string } type DialOption interface { apply(*dialOption) } type funcOption struct { f func(*dialOption) } func(fdo *funcOption) apply(do *dialOption){ fdo.f(do) } func newFuncOption(f func(*dialOption))*funcOption{ return &funcOption{ f:f, } } func withUserName(s string) DialOption{ return newFuncOption(func(o *dialOption){ o.Username = s }) } func withPasswordd(s string) DialOption{ return newFuncOption(func(o *dialOption){ o.Password = s }) } func withService(s string) DialOption{ return newFuncOption(func(o *dialOption){ o.Service = s }) } //默認(rèn)參數(shù) func defaultOptions() dialOption{ return dialOption{ Service:"test", } } type clientConn struct { timeout int dopts dialOption } func NewClient(address string, opts ...DialOption){ cc :=&clientConn{ timeout:30, dopts:defaultOptions(), } //循環(huán)調(diào)用opts for _,opt := range opts { opt.apply(&cc.dopts) } fmt.Printf("%+v",cc.dopts) } func main(){ NewClient("127.0.0.1",withPasswordd("654321"),withService("habox")) NewClient("127.0.0.1",withService("habox")) }
實(shí)例化時(shí),通過func的方式來傳遞參數(shù),也可以定義一些默認(rèn)參數(shù)。如果以后要加,只需要更改很少的代碼。
而且,這種方式也不會傳遞不相關(guān)的參數(shù),因?yàn)閰?shù)都在通過func的方式來修改的。
唯一不好的地方可能是代碼量相應(yīng)的增加了。但是為了更優(yōu)雅,這種做法還是值得的。
總結(jié)
到此這篇關(guān)于golang給函數(shù)參數(shù)設(shè)置默認(rèn)值的文章就介紹到這了,更多相關(guān)golang函數(shù)參數(shù)設(shè)置默認(rèn)值內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go語言實(shí)現(xiàn)websocket推送程序
這篇文章主要介紹了Go語言實(shí)現(xiàn)websocket推送程序,WebSocket是基于TCP的一個(gè)雙向傳輸數(shù)據(jù)的協(xié)議,和HTTP協(xié)議一樣,是在應(yīng)用層的,他的出現(xiàn),是為了解決網(wǎng)頁進(jìn)行持久雙向傳輸數(shù)據(jù)的問題2023-01-01Go打印結(jié)構(gòu)體提升代碼調(diào)試效率實(shí)例詳解
這篇文章主要介紹了Go打印結(jié)構(gòu)體提升代碼調(diào)試效率實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-02-02