1. 前言

前面的随笔Golang 利用反射对结构体优雅排序的操作方法分享了如何通过反射获取变量的类型和值,

interface{}interface{}

这篇随笔主要分享通过反射修改各种类型变量值的方法。

2. 判断是否可修改

reflectfunc (v Value) CanSet() bool

一般情况下,通过反射修改变量值,需要满足以下两个条件。

2.1 该值是可寻址的

类似函数传参,如果需要在函数内修改入参数的内容,那么就需要传引用,而不是传值。

函数内修改入参指向的内容,才能将修改效果“带出”该函数的作用域。

同理,反射修改变量的值,应当是可以寻址的,修改的是反射对象指向的数据内容,

func ValueOf(i any) Value
iiValueValue.ElemiValueiValueValue.Elem

上述三种情况如下图所示,经过寻址的内容才有可能是可修改的。

2.2 该值是可导出的

“public”

3. 修改slice

slicesliceslice
panic

代码输出如下

$ go run main.go
valueS Kind:slice CanSet:false Index(0).CanSet:true
after edit:[10 20 3]

sliceslice

代码输出如下

$ go run main.go
valuePtrS kind:ptr CanSet:false
valueS kind:slice CanSet:true
replace edit:[4 5 6 7]

4. 修改array

arrayfunc ValueOf(i any) Valuearray

代码输出如下

$ go run main.go
valuePtrS kind:ptr CanSet:false
valueS kind:array CanSet:true
after edit:[10 2 3]
replace edit:[4 5 6]

5. 修改结构体

带修改的结构体的成员的字段名首字母需要大写。

代码输出如下,

$ go run main.go
Kind:ptr CanSet:false
Kind:struct CanSet:true Field(0).CanSet:true
after edit:{Num:10 Desc:desc}
after replace:{Num:100 Desc:new desc}

6. 修改map

func (v Value) SetMapIndex(key, elem Value)mapkeyvalue

代码输出如下

$ go run main.go
key:1 val:1
key:2 val:2
key:3 val:3
--- after edit ---
key:1 val:a
key:2 val:a
key:3 val:a