最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Golang反射修改變量值的操作代碼

 更新時間:2022年12月06日 08:36:10   作者:Amos01  
這篇文章主要介紹了Golang反射修改變量值,也就是Golang反射三大定律中的前兩個,即從interface{}到反射對象和從反射對象到interface{},需要的朋友可以參考下

1. 前言

前面的隨筆Golang 利用反射對結(jié)構(gòu)體優(yōu)雅排序的操作方法分享了如何通過反射獲取變量的類型和值,

也就是Golang反射三大定律中的前兩個,即從interface{}到反射對象和從反射對象到interface{}。

這篇隨筆主要分享通過反射修改各種類型變量值的方法。

2. 判斷是否可修改

reflect提供func (v Value) CanSet() bool判斷對象值是否修改。

一般情況下,通過反射修改變量值,需要滿足以下兩個條件。

2.1 該值是可尋址的

類似函數(shù)傳參,如果需要在函數(shù)內(nèi)修改入?yún)?shù)的內(nèi)容,那么就需要傳引用,而不是傳值。

函數(shù)內(nèi)修改入?yún)⒅赶虻膬?nèi)容,才能將修改效果“帶出”該函數(shù)的作用域。

同理,反射修改變量的值,應(yīng)當(dāng)是可以尋址的,修改的是反射對象指向的數(shù)據(jù)內(nèi)容,

因此,通過反射函數(shù)func ValueOf(i any) Value

  • 入?yún)?code>i是引用時,i指向的內(nèi)容可尋址,因此返回參數(shù)Value不可修改,Value.Elem可修改。
  • 入?yún)?code>i是地址時,返回參數(shù)Value可修改。
  • 入?yún)?code>i是引用地址時,返回參數(shù)ValueValue.Elem均可修改。

上述三種情況如下圖所示,經(jīng)過尋址的內(nèi)容才有可能是可修改的。

2.2 該值是可導(dǎo)出的

這個主要是針對結(jié)構(gòu)體的成員,該成員的字段名的首字母需要是大寫,即是“public”的。

3. 修改slice

slice是引用類型,slice的數(shù)據(jù)結(jié)構(gòu)如下圖所示,通過反射可以修改slice指向的內(nèi)容。

修改指定下標(biāo)的數(shù)據(jù)內(nèi)容,并且數(shù)據(jù)類型需要和修改前一只,否則會panic。

func main() {
	s := []int{1, 2, 3}
	valueS := reflect.ValueOf(s)
	// slice 是否可修改 不可整體修改
	fmt.Printf("valueS Kind:%v CanSet:%v Index(0).CanSet:%v\n", valueS.Kind(), valueS.CanSet(), valueS.Index(0).CanSet())
	// 修改指定下標(biāo)的元素值
	valueS.Index(0).Set(reflect.ValueOf(10))
	valueS.Index(1).SetInt(20)
	fmt.Printf("after edit:%v\n", s)
 
	// panic: reflect: call of reflect.Value.SetFloat on int Value
	//valueS.Index(1).SetFloat(100)
}

代碼輸出如下

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

如果需要整體修改修改slice,那么需要傳入slice的地址

func main() {
	s := []int{1, 2, 3}
	// slice的指針
	valuePtrS := reflect.ValueOf(&s)
	fmt.Printf("valuePtrS kind:%v CanSet:%v\n", valuePtrS.Kind(), valuePtrS.CanSet())
	// 獲取指針指向的內(nèi)容
	valueS := valuePtrS.Elem()
	fmt.Printf("valueS kind:%v CanSet:%v\n", valueS.Kind(), valueS.CanSet())
	// 整體修改slice
	valueS.Set(reflect.ValueOf([]int{4, 5, 6, 7}))
	fmt.Printf("replace edit:%v\n", s)
}

代碼輸出如下

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

4. 修改array

array不是引用類型,因此func ValueOf(i any) Value需要傳入array的地址。

func main() {
	s := [3]int{1, 2, 3}
	// array的指針
	valuePtrS := reflect.ValueOf(&s)
	fmt.Printf("valuePtrS kind:%v CanSet:%v\n", valuePtrS.Kind(), valuePtrS.CanSet())
	// 獲取指針指向的內(nèi)容
	valueS := valuePtrS.Elem()
	fmt.Printf("valueS kind:%v CanSet:%v\n", valueS.Kind(), valueS.CanSet())
	// 修改指定下標(biāo)數(shù)據(jù)
	valueS.Index(0).SetInt(10)
	fmt.Printf("after edit:%v\n", s)
	// 整體修改slice
	valueS.Set(reflect.ValueOf([3]int{4, 5, 6}))
	fmt.Printf("replace edit:%v\n", s)
 
	//panic: reflect.Set: value of type [4]int is not assignable to type [3]int
	//valueS.Set(reflect.ValueOf([4]int{4, 5, 6}))
}

代碼輸出如下

$ 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. 修改結(jié)構(gòu)體

帶修改的結(jié)構(gòu)體的成員的字段名首字母需要大寫。

func main() {
	type myStruct struct {
		Num  int    `json:"num_json" orm:"column:num_orm"`
		Desc string `json:"desc_json" orm:"column:desc_orm"`
	}
	s := myStruct{
		Num:  1,
		Desc: "desc",
	}
	valueS := reflect.ValueOf(&s)
	// 指針本身不可修改 可指向的內(nèi)容
	fmt.Printf("Kind:%v CanSet:%v\n", valueS.Kind(), valueS.CanSet())
	// 獲取指針指向的內(nèi)容
	valueS = valueS.Elem()
	fmt.Printf("Kind:%v CanSet:%v Field(0).CanSet:%v\n", valueS.Kind(), valueS.CanSet(), valueS.Field(0).CanSet())
	// 修改指定成員的值
	valueS.Field(0).SetInt(10)
	fmt.Printf("after edit:%+v\n", s)
	// 替換整體內(nèi)容
	valueS.Set(reflect.ValueOf(myStruct{Num: 100, Desc: "new desc"}))
	fmt.Printf("after replace:%+v\n", s)
}

代碼輸出如下,

$ 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)修改map指定keyvalue

func main() {
	m := map[int]string{
		1: "1",
		2: "2",
		3: "3",
	}
	valueM := reflect.ValueOf(m)
	// 迭代器訪問
	iter := valueM.MapRange()
	for iter.Next() {
		fmt.Printf("key:%v val:%v\n", iter.Key(), iter.Value())
		// 將所有value修改為"a"
		valueM.SetMapIndex(iter.Key(), reflect.ValueOf("a"))
	}
	fmt.Println("--- after edit ---")
	// 通過key訪問
	keys := valueM.MapKeys()
	for i := 0; i < len(keys); i++ {
		fmt.Printf("key:%v val:%v\n", keys[i], valueM.MapIndex(keys[i]))
	}
}

代碼輸出如下

$ 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

到此這篇關(guān)于Golang反射修改變量值的文章就介紹到這了,更多相關(guān)Golang反射修改變量值內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go語言之自定義集合Set

    Go語言之自定義集合Set

    本文主要介紹的是Go語言的自定義集合Set,文中介紹的很詳細(xì),有需要的可以參考學(xué)習(xí)。
    2016-08-08
  • 解決golang處理http response碰到的問題和需要注意的點

    解決golang處理http response碰到的問題和需要注意的點

    這篇文章主要介紹了解決golang處理http response碰到的問題和需要注意的點,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • golang結(jié)構(gòu)化日志slog的用法簡介

    golang結(jié)構(gòu)化日志slog的用法簡介

    日志是任何軟件的重要組成部分,Go?提供了一個內(nèi)置日志包(slog),在本文中,小編將簡單介紹一下slog包的功能以及如何在?Go?應(yīng)用程序中使用它,感興趣的可以了解下
    2023-09-09
  • golang中select語句的簡單實例

    golang中select語句的簡單實例

    Go的select語句是一種僅能用于channl發(fā)送和接收消息的專用語句,此語句運行期間是阻塞的,下面這篇文章主要給大家介紹了關(guān)于golang中select語句的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • golang中使用匿名結(jié)構(gòu)體的方法

    golang中使用匿名結(jié)構(gòu)體的方法

    這篇文章主要介紹了golang中使用匿名結(jié)構(gòu)體,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-08-08
  • Go 中閉包的底層原理

    Go 中閉包的底層原理

    這篇文章主要介紹了Go 中閉包的底層原理,閉包的基本原理是一種現(xiàn)象,一個函數(shù)內(nèi)引用了外部的局部變量的現(xiàn)象,帶著些許的了解和小編一起進入文章正題學(xué)習(xí)
    2021-10-10
  • Go語言io?pipe源碼分析詳情

    Go語言io?pipe源碼分析詳情

    這篇文章主要介紹了Go語言io?pipe源碼分析詳情,pipe是一個適配器,用于連接Reader和Writer,pipe的方法不多,新的寫法卻不少,并且結(jié)構(gòu)體分兩塊,讀寫信道和結(jié)束標(biāo)識,下面進入文章了解具體的內(nèi)容吧
    2022-02-02
  • 深入理解golang中io.Writer接口的使用

    深入理解golang中io.Writer接口的使用

    io 是一個 Golang 標(biāo)準(zhǔn)庫包,它為圍繞輸入和輸出的許多操作和用例定義了靈活的接口,這篇文章主要為大家介紹了Go中Writer接口的使用,需要的可以參考下
    2023-10-10
  • go json數(shù)據(jù)轉(zhuǎn)發(fā)的實現(xiàn)代碼

    go json數(shù)據(jù)轉(zhuǎn)發(fā)的實現(xiàn)代碼

    這篇文章主要介紹了go json數(shù)據(jù)轉(zhuǎn)發(fā)的實現(xiàn)代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • golang爬蟲colly?發(fā)送post請求

    golang爬蟲colly?發(fā)送post請求

    本文主要介紹了golang爬蟲colly?發(fā)送post請求實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07

最新評論

黔南| 湄潭县| 铁岭县| 安丘市| 西平县| 永州市| 南陵县| 丽江市| 安龙县| 宁陕县| 会昌县| 苏尼特右旗| 乐平市| 临夏县| 铜鼓县| 九江市| 邳州市| 芮城县| 寿阳县| 嘉义市| 若羌县| 汝阳县| 礼泉县| 太仓市| 黄大仙区| 华容县| 中江县| 晋中市| 周至县| 玉屏| 松阳县| 军事| 准格尔旗| 马尔康县| 铁力市| 玉田县| 若尔盖县| 鄢陵县| 永善县| 息烽县| 五常市|