亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

go中的reflect.ValueOf()和Value.Elem()有什么區別?

go中的reflect.ValueOf()和Value.Elem()有什么區別?

Go
慕斯王 2023-07-10 16:27:35
幾天前我開始學習golang,發現reflect.Valueof()和Value.Elem()相當混亂。這兩個函數/方法有什么區別以及如何正確使用它們?兩個函數/方法都返回一個值,并且根據 go 文檔ValueOf 返回一個新的 Value,初始化為接口 i 中存儲的具體值。ValueOf(nil) 返回零值。Elem 返回接口 v 包含的值或指針 v 指向的值。如果 v 的 Kind 不是 Interface 或 Ptr,它會發生恐慌。如果 v 為零,則返回零值。我從 stackoverflow 上的一篇文章中找到了這段代碼,但仍然不明白何時使用 .Elem()func SetField(obj interface{}, name string, value interface{}) error {? ??? ? // won't work if I remove .Elem()? ? structValue := reflect.ValueOf(obj).Elem()? ??? ? structFieldValue := structValue.FieldByName(name)? ? if !structFieldValue.IsValid() {? ? ? ? return fmt.Errorf("No such field: %s in obj", name)? ? }? ? if !structFieldValue.CanSet() {? ? ? ? return fmt.Errorf("Cannot set %s field value", name)? ? }? ? structFieldType := structFieldValue.Type()? ? // won't work either if I add .Elem() to the end? ? val := reflect.ValueOf(value)? ? if structFieldType != val.Type() {? ? ? ? return fmt.Errorf("Provided value %v type %v didn't match obj field type %v",val,val.Type(),structFieldType)? ? }? ? structFieldValue.Set(val)? ? return nil}
查看完整描述

1 回答

?
慕碼人2483693

TA貢獻1860條經驗 獲得超9個贊

reflect.ValueOf()是一個函數,將其視為反射的入口點。當您有“非反射”值(例如 或 )時string,int您可以使用reflect.ValueOf()來獲取reflect.Value它的描述符。

Value.Elem()是的一種方法reflect.Value。因此,只有當您已經擁有reflect.Value.?您可以使用來獲取由原始值包裝的值所指向的Value.Elem()value( )?。請注意,您也可以用于此目的。還有另一個“用例”?,但它更“高級”,我們在答案末尾返回它。reflect.Valuereflect.Valuereflect.Indirect()Value.Elem()

要“離開”反射,您可以使用通用Value.Interface()方法,該方法將包裝值作為interface{}.

例如:

var i int = 3

var p *int = &i

fmt.Println(p, i)


v := reflect.ValueOf(p)

fmt.Println(v.Interface()) // This is the p pointer


v2 := v.Elem()

fmt.Println(v2.Interface()) // This is i's value: 3

這將輸出(在Go Playground上嘗試):


0x414020 3

0x414020

3

另一個用例Value.Elem()

這是一個高級主題,所以如果您不理解也不要驚慌。你不需要。

我們看到了Value.Elem()當指針被包裹在reflect.Value.?文檔Value.Elem()說:

Elem 返回接口 v 包含的值或指針 v 指向的值。

因此,如果reflect.Value包裝接口值,Value.Elem()也可用于獲取包裝在該接口值中的具體值。

同樣,這不一定是 Go 初學者的主題。

基本上,無論您傳遞給 的值是什么reflect.ValueOf(),如果它還不是接口值,它將被interface{}隱式包裝在一個接口值中。如果傳遞的值已經是一個接口值,那么存儲在其中的具體值將作為interface{}.?如果您傳遞一個指向接口的指針(這在 Go 中很少見?。?,那么第二個“用例”就會出現。

因此,如果您將指針傳遞給接口,則該指針將被包裝在一個interface{}值中。您可以使用它Value.Elem()來獲取指向的值,該值將是一個接口值(不是具體值),Value.Elem()?再次使用它將為您提供具體值。

這個例子說明了這一點:

var r io.Reader = os.Stdin // os.Stdin is of type *os.File which implements io.Reader


v := reflect.ValueOf(r) // r is interface wrapping *os.File value

fmt.Println(v.Type())? ?// *os.File


v2 := reflect.ValueOf(&r)? ? ? ? ? ? // pointer passed, will be wrapped in interface{}

fmt.Println(v2.Type())? ? ? ? ? ? ? ?// *io.Reader

fmt.Println(v2.Elem().Type())? ? ? ? // navigate to pointed: io.Reader (interface type)

fmt.Println(v2.Elem().Elem().Type()) // 2nd Elem(): get concrete value in interface: *os.File

在Go Playground上嘗試一下。



查看完整回答
反對 回復 2023-07-10
  • 1 回答
  • 0 關注
  • 288 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號