相關知識學習
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