在使用Go語言和viper庫時,為什么傳遞指針的指針是必要的?

go指針語法及viper庫使用中的尋址問題

在使用go語言進行編程時,理解指針的語法和使用方法至關重要,尤其是在與第三方庫如viper結合使用時,可能會遇到一些需要深入理解的問題。今天我們要探討的問題是關于在viper庫的使用中,如何正確地傳遞參數,以及為什么傳遞一個指針的指針是必要的。

在我們的項目中有幾個模塊: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模塊:

立即學習go語言免費學習筆記(深入)”;

var serversetting *setting.serversettings

main模塊:

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

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

問題在于,global.serversetting已經是一個指針,為什么在調用readsection方法時,還需要傳遞它的地址呢?

在viper庫的源碼中有這樣的說明:

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

從這段代碼可以看出,傳遞的參數不僅需要是一個指針,還需要是可以尋址的(can be addressable)。當你傳遞一個結構體的指針時,它本身并不能被尋址,因此會導致錯誤。

為了驗證這一點,我們可以看一下下面的例子:

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

運行這段代碼會得到如下輸出:

false true

這表明傳遞a本身(即一個指針)時,其元素無法被尋址,而傳遞&a(即指針的指針)時,其元素是可以被尋址的。

因此,在使用readsection方法時,我們需要傳遞&global.serversetting,因為這樣傳遞的是一個指針的地址,它是可以被尋址的,從而滿足viper庫的要求。

以上就是在使用go語言和viper庫時,

? 版權聲明
THE END
喜歡就支持一下吧
點贊6 分享