为了账号安全,请及时绑定邮箱和手机立即绑定

Go中如何获取指针类型的底层值?

Go中如何获取指针类型的底层值?

Go
暮色呼如 2023-01-03 14:14:54
我发现了这个问题How to get a pointer to the underlying value of an Interface{} in Go,但它对我来说看起来太不安全了。当然我可以*用来解压它,但我每次都必须在调用方添加 nil 检查。x := &some_type fmt.Println(*x)如果指针为 nil,我期待函数返回基类型的默认值。x := Unpacker(some_type)
查看完整描述

2 回答

?
小怪兽爱吃肉

TA贡献1852条经验 获得超1个赞

我只是nil用 if 语句检查。这是合理的做法。不过,如果您想探索替代方案,请继续阅读。


在 Go 1.18 中,您可以使用一个简单的通用函数来完成此操作:


func val[T any](v *T) T {

    if v != nil {

        return *v

    }

    return *new(T) // zero value of T

}

但是,这仅适用于 form 中的指针类型*T。Go 中还有其他类型具有nil零值并且不是指针。或者,nil如果您将指针传递给此类类型(例如*[]int. 不幸的是,没有一种方便的方法来为所有可能的可空类型1声明约束。


在 Go 1.17 及以下版本中,如果已知可能的类型集,则可以使用类型开关,但必须断言结果。这具有允许对可空类型进行临时初始化的次要优势:


func val(v interface{}) interface{} {

    switch t := v.(type) {

    case *string:

        if t != nil {

            return *t

        }

        return ""


    case *[]string:

        if t != nil {

            return *t

        }

        return []string{}


    default:

        panic("unexpected type")

    }

}

或者只是使用反射,具有必须断言返回或冒着nil再次返回的风险的相同限制:


func val(v interface{}) interface{} {

    t := reflect.TypeOf(v)

    if t == nil || t.Kind() != reflect.Ptr {

        panic("invalid input")

    }

    rv := reflect.ValueOf(v)

    if rv.IsNil() {

        return reflect.Zero(rv.Type().Elem()).Interface()

    }

    return v

}

游乐场:https ://go.dev/play/p/9dk0hWay90j


1:主要是因为这样的约束必须捕获映射类型的键和/或值类型,并决定在这些情况下(任意)返回什么。


查看完整回答
反对 回复 2023-01-03
?
临摹微笑

TA贡献1982条经验 获得超2个赞

我正在接受另一个答案,但这是我尝试过的,显然也适用于原语。


func Unwrap[T any](x *T) (r T) {

    if x != nil {

        r = *x

    }

    return

}


查看完整回答
反对 回复 2023-01-03
  • 2 回答
  • 0 关注
  • 120 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信