登录
首页 >  Golang >  Go问答

奇异的接口指针行为

来源:stackoverflow

时间:2024-03-22 12:18:35 190浏览 收藏

本文探讨了 Go 指针反射中出现的奇怪行为。通过编写三个函数来调查此问题,作者发现只有 main3 函数成功运行,而其他两个函数会导致恐慌。造成差异的关键在于 main3 创建了一个新值,而其他函数则尝试使用指向结构体的接口。

问题内容

我编写了 3 个类似的函数来找出 go 指针反射的奇怪行为。

package main

import (
    "reflect"
    "fmt"
)

var i interface{} = struct {}{}     // i is an interface which points to a struct
var ptr *interface{} = &i           // ptr is i's pointer

func f(x interface{}) {             // print x's underlying value
    fmt.Println(reflect.ValueOf(x).Elem())
}

func main1() {  // f is asking for interface? OK, I'll use the struct's interface
    structValue := reflect.ValueOf(ptr).Elem().Elem().Interface()
    f(structValue)
}

func main2() {  // Error? Let me try the struct's pointer
    structPtr := reflect.ValueOf(ptr).Elem().Interface()
    f(structPtr)
}

func main3() {  // Why this one could succeed after New() ?
    typ := reflect.ValueOf(ptr).Elem().Elem().Type()
    newPtr := reflect.New(typ).Elem().Addr().Interface()
    f(newPtr)
}

func main() {
    //main1()   // panic: reflect: call of reflect.Value.Elem on struct Value
    //main2()   // panic: reflect: call of reflect.Value.Elem on struct Value
    main3()     // OK. WHY???
}

只有 main3 正在工作,其他 2 个会出现恐慌。为什么? 3 的主要区别在于它创造了新价值。

对于main2,我认为valueof().elem().interface()已经重建了一个指向struct{}{}的接口,只是不明白为什么会失败。


解决方案


从reflect.valueof返回的值保存了参数中存储的具体值。如果参数为零,则返回零 reflect.value。

换句话说,reflect.value 和传递给reflect.value 的接口具有相同的底层值。

如果您将 f 更改为:,则函数 main1main2 将按我认为您期望的方式工作:

func f(x interface{}) {             // print x's underlying value
    fmt.Println(reflect.ValueOf(x))
}

main3f 的参数是 *struct{}。函数 f 取消引用指针(通过调用 elem())并打印 struct{} 的反射值。

可能令人困惑的一点是 reflect.valueof(ptr).elem().elem().interface()reflect.valueof(ptr).elem().interface() 返回一个接口相同的具体值。

表达式reflect.valueof(ptr).elem()i对应的反射值。对该值调用 interface() 将返回一个接口,该接口具有 i 中的具体值。

表达式reflect.valueof(ptr).elem().elem()i具体值对应的反射值。对此值调用 interface() 将返回包含该具体值的接口。

以上就是本文的全部内容了,是否有顺利帮助你解决问题?若是能给你带来学习上的帮助,请大家多多支持golang学习网!更多关于Golang的相关知识,也可关注golang学习网公众号。

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>