在使用Go語(yǔ)言和viper庫(kù)時(shí),為什么傳遞指針的指針是必要的?

go指針語(yǔ)法及viper庫(kù)使用中的尋址問題

在使用go語(yǔ)言進(jìn)行編程時(shí),理解指針的語(yǔ)法和使用方法至關(guān)重要,尤其是在與第三方庫(kù)如viper結(jié)合使用時(shí),可能會(huì)遇到一些需要深入理解的問題。今天我們要探討的問題是關(guān)于在viper庫(kù)的使用中,如何正確地傳遞參數(shù),以及為什么傳遞一個(gè)指針的指針是必要的。

在我們的項(xiàng)目中有幾個(gè)模塊:setting、section、global和main。具體代碼如下:

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模塊:

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模塊:

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

var serversetting *setting.serversettings

main模塊:

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

現(xiàn)在,如果在main模塊中將第二行修改為setting.readsection(“server”, global.serversetting),會(huì)報(bào)錯(cuò)result must be addressable (a pointer)。這是為什么呢?

問題在于,global.serversetting已經(jīng)是一個(gè)指針,為什么在調(diào)用readsection方法時(shí),還需要傳遞它的地址呢?

在viper庫(kù)的源碼中有這樣的說(shuō)明:

// 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)")     } }

從這段代碼可以看出,傳遞的參數(shù)不僅需要是一個(gè)指針,還需要是可以尋址的(can be addressable)。當(dāng)你傳遞一個(gè)結(jié)構(gòu)體的指針時(shí),它本身并不能被尋址,因此會(huì)導(dǎo)致錯(cuò)誤。

為了驗(yàn)證這一點(diǎn),我們可以看一下下面的例子:

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()) }

運(yùn)行這段代碼會(huì)得到如下輸出:

false true

這表明傳遞a本身(即一個(gè)指針)時(shí),其元素?zé)o法被尋址,而傳遞&a(即指針的指針)時(shí),其元素是可以被尋址的。

因此,在使用readsection方法時(shí),我們需要傳遞&global.serversetting,因?yàn)檫@樣傳遞的是一個(gè)指針的地址,它是可以被尋址的,從而滿足viper庫(kù)的要求。

以上就是在使用go語(yǔ)言和viper庫(kù)時(shí),

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