draxq02664 2018-09-13 19:21
浏览 47

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

I have 15 custom types in this application, and the processing I wish to do to them is actually very generic to them all.

In each case, I need to iterate over a slice of whatever type it is that I am working with.

an interface is what currently gets passed, but it certainly doesn't have to remain that way

I have the following code :

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))
        }
    }
}

the fmt.Println is there for debugging, and I get the following sort of output :

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

My real question here, is let's say I have the types :

MyCustomStructA,
MyCustomeStructB

and I bail into that function with a slice of either, how can I end up in that loop, working with actual struct items? Because at the minute, I wind up with a map, and that is not what I want here.

  • 写回答

1条回答 默认 最新

  • doudonglu3764 2018-09-13 20:06
    关注

    I'd suggest making all of those custom types implement an interface which says that they're 'processable'. Then in ProcessSlice(), you can iterate over the slice elements and process those that implement the Processable interface. Something like this:

    // 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()
                }
            }
        }
    }
    

    This way, all of the processing logic for a type can be attached to the type itself and you also wouldn't need to modify ProcessSlice() when adding new custom types.

    Coming to the actual question, you can use a type switch on the slice value like this (though I prefer the interface way more)

    // 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
            }
        }
    }
    

    (See it on the Go Playground)

    评论

报告相同问题?

悬赏问题

  • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计
  • ¥15 cmd cl 0x000007b
  • ¥20 BAPI_PR_CHANGE how to add account assignment information for service line
  • ¥500 火焰左右视图、视差(基于双目相机)
  • ¥100 set_link_state
  • ¥15 虚幻5 UE美术毛发渲染
  • ¥15 CVRP 图论 物流运输优化
  • ¥15 Tableau online 嵌入ppt失败
  • ¥100 支付宝网页转账系统不识别账号
  • ¥15 基于单片机的靶位控制系统