![](/img/trans.png)
[英]Using reflect, how do you initialize value of a struct pointer field?
[英]Using reflect, how do you set the value of a struct field?
使用reflect
包處理結構字段時遇到了困難。 特別是,還沒想好如何設置字段值。
type t struct { fi int; fs string } var r t = t{ 123, "jblow" } var i64 int64 = 456
獲取字段 i 的名稱 - 這似乎有效
var field = reflect.TypeOf(r).Field(i).Name
將字段 i 的值作為 a) interface{}, b) int - 這似乎有效
var iface interface{} = reflect.ValueOf(r).Field(i).Interface()
var i int = int(reflect.ValueOf(r).Field(i).Int())
設置字段 i 的值 - 嘗試一個 - 恐慌
reflect.ValueOf(r).Field(i).SetInt( i64 )
panic : reflect.Value·SetInt 使用使用未導出字段獲得的值
假設它不喜歡字段名稱“id”和“name”,所以重命名為“Id”和“Name”
a) 這個假設正確嗎?
b) 如果正確,認為沒有必要,因為在同一個文件/包中
設置字段 i 的值 - 嘗試兩個(字段名稱大寫) - 恐慌
reflect.ValueOf(r).Field(i).SetInt( 465 )
reflect.ValueOf(r).Field(i).SetInt( i64 )
恐慌:reflect.Value·SetInt 使用不可尋址的值
@peterSO 下面的說明是全面和高質量的
四。 這有效:
reflect.ValueOf(&r).Elem().Field(i).SetInt( i64 )
他還記錄了字段名稱必須是可導出的(以大寫字母開頭)
Go json 包對 Go 結構中的 JSON 進行編組和解組。
這是一個分步示例,它設置struct
字段的值,同時小心地避免錯誤。
func (v Value) CanAddr() bool
如果可以使用 Addr 獲取值的地址,則 CanAddr 返回 true。 這樣的值稱為可尋址的。 如果值是切片的元素、可尋址數組的元素、可尋址結構的字段或取消引用指針的結果,則該值是可尋址的。 如果 CanAddr 返回 false,則調用 Addr 將導致恐慌。
Go reflect
包有一個CanSet
函數,如果為true
,則意味着CanAddr
也是true
。
func (v Value) CanSet() bool
如果 v 的值可以更改,則 CanSet 返回 true。 只有當值可尋址且不是通過使用未導出的結構字段獲得時,才可以更改值。 如果 CanSet 返回 false,則調用 Set 或任何特定於類型的 setter(例如 SetBool、SetInt64)將發生恐慌。
我們需要確保我們可以Set
struct
字段。 例如,
package main
import (
"fmt"
"reflect"
)
func main() {
type t struct {
N int
}
var n = t{42}
// N at start
fmt.Println(n.N)
// pointer to struct - addressable
ps := reflect.ValueOf(&n)
// struct
s := ps.Elem()
if s.Kind() == reflect.Struct {
// exported field
f := s.FieldByName("N")
if f.IsValid() {
// A Value can be changed only if it is
// addressable and was not obtained by
// the use of unexported struct fields.
if f.CanSet() {
// change value of N
if f.Kind() == reflect.Int {
x := int64(7)
if !f.OverflowInt(x) {
f.SetInt(x)
}
}
}
}
}
// N at end
fmt.Println(n.N)
}
Output:
42
7
如果我們可以確定所有錯誤檢查都是不必要的,則示例簡化為,
package main
import (
"fmt"
"reflect"
)
func main() {
type t struct {
N int
}
var n = t{42}
fmt.Println(n.N)
reflect.ValueOf(&n).Elem().FieldByName("N").SetInt(7)
fmt.Println(n.N)
}
順便說一句,Go 可以作為開源代碼使用。 了解反射的一個好方法是了解核心 Go 開發人員如何使用它。 例如,Go fmt和json包。 包文檔在包文件標題下提供了指向源代碼文件的鏈接。
這似乎有效:
package main
import (
"fmt"
"reflect"
)
type Foo struct {
Number int
Text string
}
func main() {
foo := Foo{123, "Hello"}
fmt.Println(int(reflect.ValueOf(foo).Field(0).Int()))
reflect.ValueOf(&foo).Elem().Field(0).SetInt(321)
fmt.Println(int(reflect.ValueOf(foo).Field(0).Int()))
}
印刷:
123
321
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.