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

如何检查切片界面元素是否具有相同的动态类型?

如何检查切片界面元素是否具有相同的动态类型?

Go
翻过高山走不出你 2022-11-15 13:39:01
我有以下结构,它们遵循这个结构:A是接口,B, C,D都是带接口的类型A。我有一部分变量args都带有 interface 类型A,每个变量都可以是B, C,D特定类型。我想写一个for循环来判断切片中的所有变量是否都属于同一个动态类型。我写了以下代码:var existingTyp Afor i, d := range args { switch typ := d.(type) {   case *B, *C, *D:    if existingTyp == nil {        existingTyp = typ    } else {        if typ != existingTyp {            panic("error!")        }   }}如何修改代码来实现我想要的?
查看完整描述

2 回答

?
holdtom

TA贡献1805条经验 获得超10个赞

您不能==在接口值上使用相等运算符。即使动态类型相同,如果它们具有不同值的字段,比较也可能返回 false。或者它会恐慌 if B,C并且D与开始时不可比较。


相反,您可以使用反射并使用==on reflect.Type。如果您添加更多实现A.


func dynamicTypesEq(args []A) bool {

    var a reflect.Type

    for _, d := range args {

        t := reflect.TypeOf(d)

        if a == nil {

            a = t

            continue

        }

        if a != t {

            return false

        }


    }

    return true

}

使用一些示例切片调用函数:


func main() {

    a := []A{&B{}, &B{}, &B{}}

    fmt.Println(dynamicTypesEq(a)) // true


    b := []A{&C{}, &B{}, &B{}}

    fmt.Println(dynamicTypesEq(b)) // false



    c := []A{&D{}, &D{}, &B{}}

    fmt.Println(dynamicTypesEq(c)) // false

}

请注意,如果输入具有*B和,则此函数报告错误B。显然,指针类型与基类型不同。


游乐场:https ://go.dev/play/p/QOCvSyxGPRU


查看完整回答
反对 回复 2022-11-15
?
翻阅古今

TA贡献1780条经验 获得超5个赞

这是使用 reflect 包的方法。如果某个元素的类型与第一个元素的类型不同,则切片包含混合值类型。


func check(args []interface{}) bool {

    if len(args) == 0 {

        return true

    }

    t := reflect.TypeOf(args[0])

    for _, v := range args[1:] {

        if reflect.TypeOf(v) != t {

            return false

        }

    }

    return true

}

以下是如何在没有反射的情况下做到这一点。保留一个状态变量,记录最后看到的类型。如果当前类型不是最后一个类型,则切片包含混合值类型。


func check(args []interface{}) bool {

    const (

        initState = iota

        typeB

        typeC

        typeD

    )

    state := initState

    for _, d := range args {

        switch d.(type) {

        case *B:

            if state != initState && state != typeB {

                return false

            }

            state = typeB

        case *C:

            if state != initState && state != typeC {

                return false

            }

            state = typeC

        case *D:

            if state != initState && state != typeD {

                return false

            }

            state = typeD

        default:

            panic("unsupported type")

        }

    }

    return true

}


查看完整回答
反对 回复 2022-11-15
  • 2 回答
  • 0 关注
  • 161 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号