在 Golang 中,通过 反射 的方法 reflect.ValueOf 传入的不管是 变量 的值还是地址,通过反射都不可以直接修改变量的值。
在使用反射的 reflect.ValueOf 的 Elem 方法时,不可以使用 Elem 获取一个值类型或者是引用类型的变量的指针信息,如果使用 Elem 获取值类型或者引用类型的指针信息,程序会 panic。
在使用反射的 reflect.ValueOf 的 Elem 方法时,如果 ValueOf 传入的是变量的地址,那么可以通过反射可以修改变量的值。
reflect.ValueOf(x).CanSet()
使用 reflect.ValueOf
传入我们要获取的变量,不管我们传入的是变量还是传入的是变量的地址,都返回 False。
reflect.ValueOf(x).Elem()
使用 reflect.ValueOf
传入我们要获取的变量,如果我们传入的是变量,那么程序会 panic。
reflect.ValueOf(&x).CanSet()
使用 reflect.ValueOf
传入我们要获取的变量的地址,再次使用 CanSet 获取是否可以修改变量的值,返回 true。
ValueOf 传入的不管是变量的值还是地址,通过反射都不可以修改变量的值
package main
import (
"fmt"
"reflect"
)
func main() {
fmt.Println("嗨客网(www.haicoder.net)")
var x = 1024
var str = "HaiCoder"
var intSlice = []uint64{128, 256, 512, 1024}
valueX := reflect.ValueOf(x)
valueStr := reflect.ValueOf(str)
valueSlice := reflect.ValueOf(intSlice)
fmt.Println("valueX can set =", valueX.CanSet())
fmt.Println("valueStr can set =", valueStr.CanSet())
fmt.Println("valueSlice can set =", valueSlice.CanSet())
pValueX := reflect.ValueOf(&x)
pValueStr := reflect.ValueOf(&str)
pValueSlice := reflect.ValueOf(&valueSlice)
fmt.Println("pValueX can set =", pValueX.CanSet())
fmt.Println("pValueStr can set =", pValueStr.CanSet())
fmt.Println("pValueSlice can set =", pValueSlice.CanSet())
}
程序运行后,控制台输出如下:
首先,我们定义了一个 int 类型 的变量 x ,一个 字符串 类型的变量 str 和一个 切片 类型的变量 intSlice,接着,我们使用 reflect.ValueOf
获取这三个变量的值信息。
接着,我们使用值信息的 CanSet 方法来判断变量的值是否可以通过反射来修改,结果,我们发现,不管我们传入的是值类型的变量、值类型的变量的地址、引用类型的变量还是引用类型的变量的地址,结果 CanSet 返回的都是 False 。
即,我们不可以通过 reflect.ValueOf 返回的 Value 信息来实现对变量的修改。
不可以使用 Elem 获取一个值类型变量的指针信息
package main
import (
"fmt"
"reflect"
)
func main() {
fmt.Println("嗨客网(www.haicoder.net)")
var x = 1024
valueElemX := reflect.ValueOf(x).Elem()
fmt.Println("valueElemX can set =", valueElemX.CanSet())
}
程序运行后,控制台输出如下:
首先,我们定义了一个 int 类型的变量 x ,接着,我们使用 reflect.ValueOf 获取该变量的值信息,并且使用其 Elem 获取其指向的对象的信息。
结果,我们的程序报错,即,我们不可以使用 Elem 获取一个值类型变量的指针信息。
不可以使用 Elem 获取一个引用类型变量的指针信息
package main
import (
"fmt"
"reflect"
)
func main() {
fmt.Println("嗨客网(www.haicoder.net)")
var intSlice = []uint64{256, 512, 1024}
valueElemSlice := reflect.ValueOf(intSlice).Elem()
fmt.Println("valueElemSlice can set =", valueElemSlice.CanSet())
}
程序运行后,控制台输出如下:
首先,我们定义了一个切片类型的变量 intSlice ,接着,我们使用 reflect.ValueOf 获取该变量的值信息,并且使用其 Elem 获取其指向的对象的信息。
结果,我们的程序报错,即,我们不可以使用 Elem 获取一个引用类型变量的指针信息。
ValueOf 传入的如果是地址,通过反射可以修改变量的值
package main
import (
"fmt"
"reflect"
)
func main() {
fmt.Println("嗨客网(www.haicoder.net)")
var x = 1024
var intSlice = []uint64{256, 512, 1024}
valueElemInt := reflect.ValueOf(&x).Elem()
valueElemSlice := reflect.ValueOf(&intSlice).Elem()
fmt.Println("valueElemInt can set =", valueElemInt.CanSet())
fmt.Println("valueElemSlice can set =", valueElemSlice.CanSet())
}
程序运行后,控制台输出如下:
首先,我们定义了一个 int 类型的变量 x 和一个切片类型的变量 intSlice,接着,我们使用 reflect.ValueOf 获取变量的指针的信息。
同时,我们使用变量的指针的 Elem 获取地址所指向的指针变量,此时,再次使用 CanSet 获取变量是否可以修改值,发现,都返回了 true,即,我们可以通过在 reflect.ValueOf 传入地址,修改变量的值。
Go 语言反射是否可以修改变量语法:
reflect.ValueOf(x).CanSet()
使用 reflect.ValueOf
传入我们要获取的变量,不管我们传入的是变量还是传入的是变量的地址,都返回 False。Go 语言反射获取指向的对象信息语法:
reflect.ValueOf(x).Elem()
使用 reflect.ValueOf
传入我们要获取的变量,如果我们传入的是变量,那么程序会 panic。Go 语言反射是否可以修改变量语法:
reflect.ValueOf(&x).CanSet()
使用 reflect.ValueOf
传入我们要获取的变量的地址,再次使用 CanSet 获取是否可以修改变量的值,返回 true。