Как сделать пустой интерфейс обратно частью моего пользовательского типа? - PullRequest
0 голосов
/ 13 сентября 2018

У меня есть 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 голосов
/ 13 сентября 2018

Я бы предложил сделать так, чтобы все эти пользовательские типы реализовывали интерфейс, который говорит, что они «обрабатываются». Затем в ProcessSlice() вы можете перебирать элементы слайса и обрабатывать те, которые реализуют интерфейс 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() при добавлении новых пользовательских типов.

Возвращаясь к актуальному вопросу, вы можете использовать переключатель типа на значении среза, как это (хотя я предпочитаю интерфейс гораздо больше)

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...