golang知識點--reflect

相關知識學習

1.go語言的type和interface{}

類型
go語言是靜態類型的語言,這意味着每個變量都有它的靜態類型,那是確定且一直固定的一個類型。
例如:

type MyInt int

var i int
var j MyInt

雖然定義了MyInt是int的別名,但是i與j的類型並不是一個類型,除非經過轉換。
接口概述
interface:標識固定的方法集
接口變量可以存儲任何具體(非接口)值,只要該值實現接口的方法

// Reader is the interface that wraps the basic Read method.
type Reader interface {
    Read(p []byte) (n int, err error)
}

// Writer is the interface that wraps the basic Write method.
type Writer interface {
    Write(p []byte) (n int, err error)
}

任何使用此簽名實現了Read(Write)的類型,都可以說實現了io.Reader(io.Writer),舉一個例子說明io.Reader類型的變量可以保存期類型具有Read方法的任何值:

type test struct{
  a int
}
func (f *test) Read(p []byte) (n int, err error) {
	return 0,nil
}

func main() {
	var b *test
	var r io.Reader
	r = b
}

要記得無論r的具體值是多少r的類型都是io.Reader
一個及其重要的接口類型是空interface

interface{}

它表示方法的空集合,並且完全由任何值滿足,因爲任何值都有零個或多個方法。要明確接口都是靜態類型的,無論他們存儲的值如何他們的類型都不變。

var b *test
	var a int
	var r interface{}
	r = b
	fmt.Println(reflect.TypeOf(r))//*main.test
	r = a
	fmt.Println(reflect.TypeOf(r))//int

接口詳解
一個接口類型的變量存儲一對數據:
(1)指定給變量的具體值(實現接口的底層具體數據項)
(2)該值的類型描述符(描述該項的完整類型)

var r io.Reader
tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0)
if err != nil {
    return nil, err
}
r = tty

r表示如下:(value,type)對(tty,*os.File)

2.反射定律

1.反射從接口值到反射對象。

func TypeOf(i interface{}) Type {
	eface := *(*emptyInterface)(unsafe.Pointer(&i))
	return toType(eface.typ)
}

當我們調用typeof的時候實際上我們是先將x作爲一個空interface傳遞,
然後typeof解壓空interface來回復類型信息。

var x float64 = 3.4
v := reflect.ValueOf(x)
fmt.Println("type:", v.Type())
fmt.Println("kind is float64:", v.Kind() == reflect.Float64)
fmt.Println("value:", v.Float())

輸出

type: float64
kind is float64: true
value: 3.4

2.反射從反射對象到接口值。
與物理反射一樣,Go中的反射也會產生自身的逆反射

y := v.Interface().(float64) // y will have type float64.
fmt.Println(y)

3.若要修改反射對象,該值必須是可設置的
錯誤示範:

var x float64 = 3.4
v := reflect.ValueOf(x)
v.SetFloat(7.1) // Error: will panic.

會發現v的值是不可以被設置的。可設置性是反射值的一個屬性,並非所有反射值都具有它。
如何查看這個值是否可設置

var x float64 = 3.4
v := reflect.ValueOf(x)
fmt.Println("settability of v:", v.CanSet())

可設置性:可設置性有點像可尋址性,但更嚴格。反射對象可以修改用於創建反射對象的實際存儲的屬性。可設置性由反射對象是否保存原始項決定。
若要通過反射修改x,必須給反射庫一個指向要修改的值得指針。

	var x float64 = 3.4
	p := reflect.ValueOf(&x) // Note: take the address of x.
	fmt.Println("type of p:", p.Type())
	fmt.Println("settability of p:", p.CanSet())
	v := p.Elem()
	fmt.Println("settability of v:", v.CanSet())
	v.SetFloat(7.1)
	fmt.Println(v.Interface())
	fmt.Println(x)

輸出:

type of p: *float64
settability of p: false
settability of v: true
7.1
7.1

參考頁面:
https://blog.golang.org/laws-of-reflection

發佈了211 篇原創文章 · 獲贊 33 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章