[英]How to convert a string value to the correct reflect.Kind in go?
[英]In Go, which value’s kind is reflect.Interface?
j:=1
j
Kind
是reflect.Int
。如預期的那樣。
var j interface{} = 1
j
Kind
也是reflect.Int
。
哪種價值reflect.Interface
。 reflect.Interface
?
如果您正在尋找一個實用的解決方案,答案很簡單,也很煩人。 reflect.TypeOf
采用一個空接口類型,您可以將任何數據放入其中。 這個問題是接口類型不能容納另一種接口類型,這意味着你實際上無法將接口傳遞給reflect.TypeOf
。 有一個解決方法,但它有點痛苦。 您需要做的是創建一個復合類型(如結構或切片或映射),其中一個元素類型是接口類型,並提取它。 例如:
var sliceOfEmptyInterface []interface{}
var emptyInterfaceType = reflect.TypeOf(sliceOfEmptyInterface).Elem()
首先創建[]interface{}
一個reflect.Type
表示(一個interface{}
類型的片段),然后提取元素類型,即interface{}
。
感謝這篇文章 。
到目前為止,答案似乎令人驚訝地復雜,當問題及其響應實際上是直截了當時:reflect.Interface是一種接口值。
您可以通過以下方式輕松查看:
var v interface{}
var t = reflect.ValueOf(&v).Type().Elem()
fmt.Println(t.Kind() == reflect.Interface)
請注意, ValueOf(v)
不起作用,因為您需要v本身的類型,而不是其內容。
好問題。 我花了將近一個小時才找到自己!
讓我們從這段代碼開始:
package main
import (
"fmt"
"reflect"
)
// define an interface
type Doer interface {
Do()
}
// define a type that implements the interface
type T struct{}
func (T) Do() {}
func main() {
var v Doer = T{}
fmt.Println(reflect.TypeOf(v).Kind())
}
輸出是struct
,而不是interface
。 ( 你可以在這里運行它。 )
這是因為即使我們將v
定義為接口變量 ,此變量保存的實際值也是T
類型。 它被稱為變量的“動態類型”。 包reflect
一個要點是幫助確定接口變量的動態類型,因此它為您提供動態類型,而不是接口。 (即使它想要,包reflect
也無法獲得傳遞給TypeOf
和ValueOf
的變量接口,因為變量作為值傳遞給函數。)
所以,你可以看到你的問題“這價值的一種是Interface
?”,在技術上可以用“沒有價值 ”來回答。
但那Interface
有什么用呢? 看到這段代碼:
// assuming the above code, just with this main function
func main() {
a := make([]Doer, 0)
fmt.Println(reflect.TypeOf(a).Elem().Kind())
}
這打印interface
。 ( 這個就在這里。 )要點是函數Elem
,它返回地圖元素的類型,這里是一個接口類型。 Elem
還可以處理指針,數組,切片和通道。 獲取地圖鍵( Key
)的類型,struct的字段( Field
和friends)以及函數的參數和返回參數( In
和Out
)有類似的功能。 您可以期望從所有這些獲得類型的接口。
Rob Pike寫了一篇很棒的文章, 反思的法則,很好地解釋了界面和反思。
我認為您的問題等同於:接口是否可以包含其他接口?
在反思的法則中,我們發現了這一點
接口變量可以存儲任何具體(非接口)值
或者更詳細
接口類型的變量存儲一對:賦給變量的具體值,以及該值的類型描述符。 更確切地說,值是實現接口的基礎具體數據項,類型描述該項的完整類型。
所以接口不能包含另一個接口。 這意味着沒有值v
使得reflect.TypeOf(v).Kind()
是reflect.Interface
。 我想你可能會創建一個不安全但我不認為你會正常看到一個。
這取決於你的意思是“價值”和“價值的種類”。
在Go中,“type”可能意味着不同的東西: - 表達式的靜態類型(編譯時類型)。 語言中的每個表達式都有一個在編譯時已知的靜態類型。 - 接口值的動態類型(運行時類型)。 接口類型的變量或表達式是特殊的,因為它可以保存不同類型的值,並且在編譯時不知道該基礎值的類型。 可以在運行時檢查此運行時值及其類型。
反射在運行時發生,因此詢問接口值的動態類型是很有趣的。 因此,您必須討論接口值的基礎值的類型。
阿非nil
接口值基本上是一個“包裝”周圍的潛在值和類型。 請注意,此基礎類型不能是接口類型。 即包裝器不能“包裝”另一個包裝器。 這就是joshlf13的答案所說的。 這是因為從一種接口類型分配到另一種接口類型時,只傳輸基礎值。 它來自的接口類型不會被記住。 因此,不可能創建其底層類型是接口類型的接口值。
反射函數如reflect.ValueOf()
和reflect.TypeOf()
允許您傳入接口值並獲取基礎值的表示。 參數類型是interface{}
因為這是允許您傳入任何內容的類型。 但是,他們假設您實際上對該接口值的基礎值感興趣,您可以通過首先傳遞它來轉換為interface{}
,或者從其他地方獲取它並想要檢查它。 因此,反射函數基本上用於檢查接口的基礎值(如上所述,必須是非接口類型),而不是實際的接口類型參數。
因此,如果您的問題是:什么v
可以使reflect.ValueOf(v).Kind()
評估為Interface
; 答案一無所獲。 這是因為,如果v
不是nil
,則ValueOf()
獲取其基礎值的表示,該值必須是非接口類型。 如果v
為nil
,那么通過reflect.ValueOf()
的文檔,它返回Value
類型的零值,而Value.Kind()
類型的文檔則表示調用Kind()
值的Kind()
返回Invalid
。
您無法直接獲取interface{}
值的類型,但您可以通過指向間接:
reflect.TypeOf(new(interface{})).Elem()
t := reflect.TypeOf(new(interface{})).Elem()
fmt.Printf("Type: %s\n", t)
fmt.Printf("Kind: %v\n", t.Kind())
fmt.Printf("IsInterface: %v\n", t.Kind() == reflect.Interface)
輸出:
Type: interface {}
Kind: interface
IsInterface: true
我會為此做出明確答案。
首先,你必須現在接口可以容納除了另一個接口之外的任何東西。 所以讓我們說清楚。 看看這個程序。
type i interface {
hello()
}
type s struct{
name string
}
func (a s)hello(){}
func main(){
var f i //here we create an empty interface i
f=s{} //now f hold a structure of type s
fmt.Print(reflect.ValueOf(f).Kind()) // here we got a structure type so what really happen now i will explained
}
ValueOf方法的簽名是:
reflect.ValueOf(i interface{})
所以ValueOf總是得到一個ampty接口,我告訴你接口永遠不會持有另一個接口。 valueOf不會占用f接口,但它會采用一個保持s結構的空接口。 就像我們刪除f的底層值並分配給一個空接口並傳遞給ValueOf方法
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.