Go语言反射修改变量

Go语言反射修改变量教程

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

案例

Go语言反射Value不可以修改变量

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()) }

程序运行后,控制台输出如下:

13_golang反射Value修改变量.png

首先,我们定义了一个 int 类型 的变量 x ,一个 字符串 类型的变量 str 和一个 切片 类型的变量 intSlice,接着,我们使用 reflect.ValueOf 获取这三个变量的值信息。

接着,我们使用值信息的 CanSet 方法来判断变量的值是否可以通过反射来修改,结果,我们发现,不管我们传入的是值类型的变量、值类型的变量的地址、引用类型的变量还是引用类型的变量的地址,结果 CanSet 返回的都是 False 。

即,我们不可以通过 reflect.ValueOf 返回的 Value 信息来实现对变量的修改。

Go语言反射不可以获取值类型的指针

不可以使用 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()) }

程序运行后,控制台输出如下:

14_golang反射Value修改变量.png

首先,我们定义了一个 int 类型的变量 x ,接着,我们使用 reflect.ValueOf 获取该变量的值信息,并且使用其 Elem 获取其指向的对象的信息。

结果,我们的程序报错,即,我们不可以使用 Elem 获取一个值类型变量的指针信息。

Go语言反射不可以获取引用类型的指针

不可以使用 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()) }

程序运行后,控制台输出如下:

15_golang反射Value修改变量.png

首先,我们定义了一个切片类型的变量 intSlice ,接着,我们使用 reflect.ValueOf 获取该变量的值信息,并且使用其 Elem 获取其指向的对象的信息。

结果,我们的程序报错,即,我们不可以使用 Elem 获取一个引用类型变量的指针信息。

Go语言反射Value可以根据指针修改变量

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()) }

程序运行后,控制台输出如下:

16_golang反射Value修改变量.png

首先,我们定义了一个 int 类型的变量 x 和一个切片类型的变量 intSlice,接着,我们使用 reflect.ValueOf 获取变量的指针的信息。

同时,我们使用变量的指针的 Elem 获取地址所指向的指针变量,此时,再次使用 CanSet 获取变量是否可以修改值,发现,都返回了 true,即,我们可以通过在 reflect.ValueOf 传入地址,修改变量的值。

Go语言反射修改变量总结

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。