Deep into the Go
重新描述一下 Go 的 reflect 套件
基礎
透過
reflect.ValueOf
可以得到任意實體 (instance) 的 reflect.Value
物件,
透過這個可以取得物件的類型、值等屬各種屬性。
package main
import (
"fmt"
"reflect"
)
func main() {
object := "Hello, World!"
value := reflect.ValueOf(object)
t := value.Type()
fmt.Println(t)
}
類型
為了能夠可以更彈性的處裡不同類型的物件,我們可以透過 any type 來處理、並且在內部透過 reflect.Type 來做不同類型的處理。
package main
import (
"fmt"
"reflect"
)
func handler(object any) {
value := reflect.ValueOf(object)
switch value.Kind() {
case reflect.String:
fmt.Println("String:", value.String())
case reflect.Int:
fmt.Println("Int:", value.Int())
default:
fmt.Println("Unknown type")
}
}
func main() {
handler("Hello, World!")
handler(123)
handler(true)
}
修改內容
在某些情境我們可能需要修改物件的內容,這時候我們可以透過 reflect.Value
的 Elem()
方法來取得指標指向的物件。
接下來可以透過這個指標的操作來修改物件的內容。
package main
import (
"fmt"
"reflect"
)
func handler(object any) {
value := reflect.ValueOf(object)
if value.Kind() == reflect.Ptr {
elm := value.Elem()
switch elm.Kind() {
case reflect.String:
elm.SetString("In-place modification")
case reflect.Int:
elm.SetInt(9527)
}
}
}
func main() {
str := "Hello, World!"
handler(&str)
fmt.Println(str)
num := 123
handler(&num)
fmt.Println(num)
}
複製物件
透過 reflect.Value
的 Interface()
方法可以取得物件的值,這個方法會回傳一個 interface{}
的物件,
這個物件是一個複製的物件,所以在這個物件上的操作不會影響原本的物件。
package main
import (
"fmt"
"reflect"
)
func handler(object any) any {
value := reflect.ValueOf(object)
dup := reflect.New(value.Type()).Elem()
dup.Set(value)
return dup.Interface()
}
func main() {
str := "Hello, World!"
dup := handler(str)
fmt.Println(str, dup)
}