如何将一个空接口断言为我的自定义类型的一部分?

时间:2018-09-13 19:21:17

标签: go

在此应用程序中,我有15种自定义类型,而我希望对它们进行的处理实际上对它们都非常通用。

在每种情况下,我都需要遍历我正在使用的任何类型的切片。

接口是当前通过的接口,但不必一定要保持这种状态

我有以下代码:

func ProcessSlice(in interface{}){
    switch reflect.TypeOf(p.in).Kind() {
    case reflect.Slice:
        s := reflect.ValueOf(p.in)

        for i := 0; i < s.Len(); i++ {
            fmt.Println(reflect.ValueOf(p.in))
        }
    }
}

fmt.Println用于调试,我得到以下输出:

[map[_Id:4K7qx_mUSbV-----------== name:<name ommited> _class:basic_organization] map[_Id:4K7qx_mUnvB-----------== name:<name omitted> _class:basic_organization]]

我在这里真正的问题是,我有以下类型:

MyCustomStructA,
MyCustomeStructB

并且我用其中的任意一个来保全该功能,我如何才能在该循环中使用实际的结构项呢?因为在此刻,我会看到一张地图,而那不是我想要的。

1 个答案:

答案 0 :(得分:0)

我建议使所有这些自定义类型都实现一个表示它们“可处理”的接口。然后,在ProcessSlice()中,您可以遍历slice元素并处理实现Processable接口的元素。像这样:

// Processable is a type that can be 'processed'
type Processable interface {
    Process()
}

// ProcessSlice processes a slice of types that can be processed
func ProcessSlice(in interface{}) {
    switch reflect.TypeOf(in).Kind() {
    case reflect.Slice:
        s := reflect.ValueOf(in)

        for i := 0; i < s.Len(); i++ {
            v := s.Index(i).Interface()

            if p, ok := v.(Processable); ok {
                p.Process()
            }
        }
    }
}

通过这种方式,类型的所有处理逻辑都可以附加到类型本身,并且在添加新的自定义类型时也不需要修改ProcessSlice()

谈到实际问题,您可以像这样在slice值上使用类型开关(尽管我更喜欢使用接口方式)

// ProcessSliceConcreteTypes processes a slice of types based on the type of the slice
func ProcessSliceConcreteTypes(in interface{}) {
    switch reflect.TypeOf(in).Kind() {
    case reflect.Slice:
        s := reflect.ValueOf(in)

        switch sv := s.Interface().(type) {
        case []S1:
            for _, s1 := range sv {
                s1.Process()
            }
        case []S2:
            for _, s2 := range sv {
                s2.Process()
            }
        default:
            // error here
        }
    }
}

(在Go Playground上查看)