反射 允许在运行时动态地查询和操作对象的类型和值。你可以通过
reflect.TypeOf和reflect.ValueOf获取类型和值信息、能够在运行时动态获取类型和修改值,灵活性更高。类型断言 是一种静态的类型转换机制,用于将
interface{}转换为具体类型。它是编译时检查的。类型断言(Type Assertion) 是一种在编译时进行的操作,它用于将接口类型(
interface{})的变量转换为具体的类型、意味着你需要在代码中明确地知道类型。
反射
反射的基本操作
获取变量的类型和值:你可以通过反射来获取变量的实际类型和值。
修改变量的值:通过反射,你不仅可以读取变量的类型和值,还可以在某些情况下修改它们。
调用方法:反射还允许你在运行时动态地调用对象的方法。
反射的使用
1.获取类型和原始值
使用 reflect.TypeOf() 来获取类型信息,使用 reflect.ValueOf() 来获取值信息。
import (
"fmt"
"reflect"
)
func main() {
var x int = 42
// 获取类型信息
t := reflect.TypeOf(x)
fmt.Println("Type:", t) // Type: int
// 获取值信息
v := reflect.ValueOf(x)
fmt.Println("Value:", v) // Value: 42
}2.修改变量的值
通过反射,你可以在运行时修改变量的值,但需要注意的是,只有当变量是可寻址的(例如,指针或者可变的变量)时,你才能修改其值。
import (
"fmt"
"reflect"
)
func main() {
var x int = 42
// 获取可寻址的反射值
v := reflect.ValueOf(&x)
// 修改值
v.Elem().SetInt(100)
fmt.Println("Modified x:", x) // Modified x: 100
}类型断言
类型断言用于将空接口类型(interface{})的值转换为具体的类型。
goCopy Codevar x interface{} = 42
// 断言 x 是一个 int 类型
if v, ok := x.(int); ok {
fmt.Println("x is an int:", v)
} else {
fmt.Println("x is not an int")
}
// 配合switch使用
var t interface{}
t = functionOfSomeType()
switch t := t.(type) {
default:
fmt.Printf("unexpected type %T", t) // %T prints whatever type t has
case bool:
fmt.Printf("boolean %t\n", t) // t has type bool
case int:
fmt.Printf("integer %d\n", t) // t has type int
case *bool:
fmt.Printf("pointer to boolean %t\n", *t) // t has type *bool
case *int:
fmt.Printf("pointer to integer %d\n", *t) // t has type *int
}在上面的例子中,x 是一个空接口类型,通过类型断言将它转换成了具体的 int 类型。如果 x 实际上是 int 类型,ok 将为 true,否则为 false。
反射和类型断言的区别(示例)
假设我们有一个 interface{} 类型的值,我们想要通过反射和类型断言分别获取它的类型和值。
goCopy Codepackage main
import (
"fmt"
"reflect"
)
func main() {
var x interface{} = 42
// 类型断言
if v, ok := x.(int); ok {
fmt.Println("通过断言,x 是 int:", v)
} else {
fmt.Println("x 不是 int")
}
// 反射
v := reflect.ValueOf(x)
fmt.Println("通过反射,x 的类型:", v.Type()) // int
fmt.Println("通过反射,x 的值:", v.Int()) // 42
}