簡體   English   中英

在Go中,哪種價值反映出來。接口?

[英]In Go, which value’s kind is reflect.Interface?

j:=1

j Kindreflect.Int 。如預期的那樣。

var j interface{} = 1

j Kind也是reflect.Int

哪種價值reflect.Interfacereflect.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也無法獲得傳遞給TypeOfValueOf的變量接口,因為變量作為值傳遞給函數。)

所以,你可以看到你的問題“這價值的一種是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)以及函數的參數和返回參數( InOut )有類似的功能。 您可以期望從所有這些獲得類型的接口。

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()獲取其基礎值的表示,該值必須是非接口類型。 如果vnil ,那么通過reflect.ValueOf()的文檔,它返回Value類型的零值,而Value.Kind()類型的文檔則表示調用Kind()值的Kind()返回Invalid

您無法直接獲取interface{}值的類型,但您可以通過指向間接:

reflect.TypeOf(new(interface{})).Elem()

在play.golang.org上運行

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.

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