在Go語言中使用viper庫時(shí),為什么需要傳遞指針的地址而不是指針本身?

問題探討:在go語言中使用viper庫時(shí)的指針傳參問題

在編寫go程序時(shí),經(jīng)常會(huì)遇到關(guān)于指針和內(nèi)存地址的問題。尤其是在使用第三方庫如viper時(shí),指針的使用更加復(fù)雜。本文將通過一個(gè)具體的例子,詳細(xì)解釋在go語言中使用viper庫時(shí)的指針傳參問題。

首先,我們來看一下代碼示例:

setting模塊:

type setting struct {     vp *viper.viper }  func newsetting() (*setting, error) {     vp := viper.new()     vp.setconfigname("config")     vp.addconfigpath("configs/")     vp.setconfigtype("yaml")     err := vp.readinconfig()     if err != nil {         return nil, err     }      return &setting{vp: vp}, nil }

section模塊:

立即學(xué)習(xí)go語言免費(fèi)學(xué)習(xí)筆記(深入)”;

type serversettings struct {     runmode      string     httpport     string     readtimeout  time.duration     writetimeout time.duration }  func (s *setting) readsection(k string, v interface{}) error {     err := s.vp.unmarshalkey(k, v)     if err != nil {         return err     }      return nil }

global模塊:

var serversetting *setting.serversettings

main模塊:

setting, err := setting.newsetting()  setting.readsection("server", &global.serversetting)

在上述代碼中,如果我們?cè)趍ain模塊中將第二行修改為setting.readsection(“server”, global.serversetting),程序會(huì)報(bào)錯(cuò)result must be addressable (a pointer)。為什么會(huì)出現(xiàn)這個(gè)問題呢?

首先需要明確的是,雖然global.serversetting是一個(gè)指針,但這并不意味著它可以被直接傳遞給readsection函數(shù)。我們需要傳遞的是指針的地址,而不是指針本身。

要理解這一點(diǎn),我們需要深入viper庫的源碼。在viper庫的newdecoder函數(shù)中,有這樣一段代碼:

// newdecoder returns a new decoder for the given configuration. once // a decoder has been returned, the same configuration must not be used // again. func newdecoder(config *decoderconfig) (*decoder, error) {     val := reflect.valueof(config.result)     if val.kind() != reflect.ptr {         return nil, errors.new("result must be a pointer")     }      val = val.elem()     if !val.canaddr() {         return nil, errors.new("result must be addressable (a pointer)")     } }

這段代碼說明了問題的關(guān)鍵:傳遞的參數(shù)不僅需要是一個(gè)指針,還必須是可以被尋址的(addressable)。當(dāng)我們傳遞一個(gè)結(jié)構(gòu)體的指針時(shí),它并不能被尋址,因此會(huì)報(bào)錯(cuò)。

為了進(jìn)一步理解這個(gè)問題,我們可以看一個(gè)簡單的例子:

package main  import (     "fmt"     "reflect" )  var a *db  type db struct { }  func main() {     val := reflect.valueof(a)     val = val.elem()     fmt.println(val.canaddr())      val = reflect.valueof(&a)     val = val.elem()     fmt.println(val.canaddr()) }

這段代碼的輸出結(jié)果是:

false true

這表明,當(dāng)我們直接傳遞a時(shí),它是不可尋址的;而當(dāng)我們傳遞&a時(shí),它是可以被尋址的。

因此,在使用viper庫時(shí),我們需要傳遞指針的地址,而不是指針本身。這就是為什么在main模塊中,我們需要使用&global.serversetting而不是global.serversetting。

通過這個(gè)例子,我們可以更好地理解go語言中指針的使用以及viper庫的具體要求。希望這能幫助你在編寫go程序時(shí)更好地處理指針和內(nèi)存地址的問題。

以上就是在Go語言中使用viper庫時(shí),

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點(diǎn)贊15 分享