簡單了解指針和指針本身
當(dāng)我們有一個(gè)指針時(shí),我們通常需要獲取指針指向的值的反射對(duì)象。這時(shí),我們可以使用 `reflect.Value` 的 `Elem()` 方法來獲取指針指向的元素的反射值。`Elem()` 方法會(huì)對(duì)指針進(jìn)行解引用,返回指針指向的值的 `reflect.Value`。如果 `reflect.Value` 本身不是指針,調(diào)用 `Elem()` 會(huì)導(dǎo)致 panic。
1. 指針本身的反射值
var num int = 42
ptr := &num // ptr 是一個(gè)指向 num 的指針
// 獲取指針的反射值(指針本身)
valPtr := reflect.ValueOf(ptr)
fmt.Println(valPtr.Kind()) // 輸出: ptr
這里 valPtr 表示的是指針變量 ptr 的反射值,其類型為 reflect.Ptr(指針類型)。
2. 獲取指針指向的值
如果需要操作指針指向的實(shí)際數(shù)據(jù)(如 num),需通過 Elem() 方法解引用:
// 解引用指針,獲取其指向的值
valNum := valPtr.Elem()
fmt.Println(valNum.Kind()) // 輸出: int
fmt.Println(valNum.Int()) // 輸出: 42
valNum 現(xiàn)在表示指針指向的 int 值,可直接修改:
valNum.SetInt(100) // 修改原始數(shù)據(jù)
fmt.Println(num) // 輸出: 100
“獲取指針對(duì)應(yīng)的反射值”時(shí),可能有兩種含義:
獲取指針本身的反射值。
獲取指針指向的值的反射值。
在 Go 的反射中,通常通過 `reflect.ValueOf(ptr)` 得到指針的反射值,然后通過調(diào)用其 `Elem()` 來獲取指針指向的值的反射值。
3.市導(dǎo)航的比喻
想象你在一個(gè)城市里:
數(shù)據(jù) = 一棟實(shí)際存在的房子(例如:"陽光小區(qū)3棟")
指針 = 寫著房子地址的導(dǎo)航卡片(例如:卡片上寫著"陽光小區(qū)3棟")
指針本身 = 你手里拿著的這張導(dǎo)航卡片
4.關(guān)鍵區(qū)別
指針指向的值 實(shí)際的房子 *ptr 解引用后的值 直接修改房子屬性
指針本身 你手中的導(dǎo)航卡片 ptr 指針變量 修改卡片上的地址
指針的值 卡片上寫的地址文字 指針的內(nèi)存地址(如0xc0000...) 查看卡片內(nèi)容
Go代碼示例
package main
import (
"fmt"
"reflect"
)
func main() {
// 1. 創(chuàng)建一棟房子(實(shí)際數(shù)據(jù))
house := "陽光小區(qū)3棟"
// 2. 創(chuàng)建導(dǎo)航卡片(指針)
card := &house // card是指向房子的指針
// 3. 獲取卡片本身的反射對(duì)象(不是房子?。?span>
cardReflect := reflect.ValueOf(card)
fmt.Println("=== 導(dǎo)航卡片信息 ===")
fmt.Printf("卡片類型: %v\n", cardReflect.Type()) // *string
fmt.Printf("卡片種類: %v\n", cardReflect.Kind()) // ptr
fmt.Printf("卡片內(nèi)容: %p\n", card) // 內(nèi)存地址(0x...)
// 4. 通過卡片找到實(shí)際房子
houseReflect := cardReflect.Elem()
fmt.Println("\n=== 房子信息 ===")
fmt.Printf("房子類型: %v\n", houseReflect.Type()) // string
fmt.Printf("房子值: %v\n", houseReflect.String()) // 陽光小區(qū)3棟
// 5. 修改房子(通過卡片導(dǎo)航)
houseReflect.SetString("明月花園8單元")
fmt.Println("\n修改后的房子:", house) // 明月花園8單元
// 6. 修改卡片本身(不改變房子)
newHouse := "星河灣12座"
cardReflect.Set(reflect.ValueOf(&newHouse)) // 讓卡片指向新地址
fmt.Println("\n=== 卡片重定向后 ===")
fmt.Println("卡片指向:", *card) // 星河灣12座
fmt.Println("原房子:", house) // 明月花園8單元(未改變)
}