簡體   English   中英

Golang反射:無法設置包裝結構的接口字段

[英]Golang reflection: Can't set fields of interface wrapping a struct

我正在嘗試實現一個方法,該方法可以更改可以具有任意結構的對象中的字段值。 當我有一個指向結構的指針時,字段的轉換沒有問題。 但是,當我的接口沒有包裝指向結構的指針但結構本身時,我無法改變字段,簡而言之:

// The following doesn't work
var x interface{} = A{Str: "Hello"}
// This panics: reflect: call of reflect.Value.Field on ptr Value
reflect.ValueOf(&x).Field(0).SetString("Bye")
// This panics: reflect: call of reflect.Value.Field on interface Value
reflect.ValueOf(&x).Elem().Field(0).SetString("Bye")
// This panics: reflect: reflect.Value.SetString using unaddressable value
reflect.ValueOf(&x).Elem().Elem().Field(0).SetString("Bye")
// This prints `false`. But I want this to be settable
fmt.Println(reflect.ValueOf(&x).Elem().Elem().Field(0).CanSet())

// This works
var z interface{} = &A{Str: "Hello"}
// This prints `true`
fmt.Println(reflect.ValueOf(z).Elem().Field(0).CanSet())

長: http//play.golang.org/p/OsnCPvOx8F

我已經閱讀了反射法則,所以我知道當我有一個指向結構的指針時,我可能只修改字段。 所以現在我的問題是: 如何獲得指向結構數據的指針?

更新:

我基本上使用y := reflect.New(reflect.TypeOf(x))使它工作,所以y的值現在可以設置。 有關廣泛的示例,請參閱: https//gist.github.com/hvoecking/10772475

您似乎正在嘗試修改存儲在接口變量中的動態值。 您可以對接口變量執行的唯一操作是獲取或設置動態值(進行復制的操作),以及檢查存儲值的類型。

要理解為什么會這樣,想象有這樣的操作,我們有以下代碼:

var ptr *A = pointer_to_dynamic_value(x)
x = B{...}

ptr現在代表什么? 在為接口變量分配新值時,該語言可以自由地重用存儲,因此ptr現在可能指向B值的內存,這會破壞語言的類型安全性(當前編譯器存儲僅保證是重用小值,但重點仍然是)。

改變存儲在接口中的值的唯一安全方法是復制值,然后返回修改后的版本。 例如:

a := x.(A)
a.Str = "Bye"
x = a

reflect包反映了這些限制,因此表示動態值字段的reflect.Value被認為是只讀的。

您可以在第一個示例中設置字段,因為z的動態值是*A指針而不是結構本身:這意味着可以修改引用的結構。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM