Как создать переменную с нужным типом вместо утверждения типа - PullRequest
0 голосов
/ 11 сентября 2018

У меня есть функция, которая принимает интерфейс, например:

func method(data interface{})

.. потому что мне нужно обрабатывать различные структуры, которые имеют общие поля / методы. В этой функции я использую data десятки или сотни раз, в разных местах. Это действительно неприятно добавлять switch a.(type) { case .. case .. все время.

Есть ли способ создать переменную только с одним switch с нужным типом, а затем просто использовать эту переменную везде позже? Что-то вроде:

var a .... // something here

switch data.(type) {
case *Struct1:
    a = data.(*Struct1)
case *Struct2:
    a = data.(*Struct2)
}

// Continue with 'a' only
a.Param = 15
fmt.Println(a.String())

Ответы [ 3 ]

0 голосов
/ 11 сентября 2018

Вы не можете делать то, что просили в своем вопросе напрямую, go имеет статическую типизацию, поэтому вы не можете иметь одну переменную, которая может содержать разные типы, и при этом обращаться к этой переменной, как если бы она была набрана.

Если вы работаете только с общими полями структуры в вашем методе, возможно, вам лучше собрать все общие переменные в его собственную структуру, показанную ниже как структуру commons, и ваш method принимает этот типв качестве аргумента

package main

import (
    "fmt"
)

type commons struct {
    name string
    age int
}
type structA struct {
    commons
    other_stuff int
}

type structB struct {
    commons
    foo string
}

func method(c* commons) {
    fmt.Println(c)
    c.age +=1

}
func main() {
    a := structA{commons{"foo", 44}, 1} 
    b := structB{commons{"bar", 33}, "test"} 
    method(&a.commons)
    method(&b.commons)
    fmt.Println(a)
}

Перейти на игровую площадку

0 голосов
/ 12 сентября 2018

Я не могу понять, какова ваша реальная цель, но если «метод», который вы хотите написать, обрабатывает общие поля из аналогичных структур, и вы не можете исправить исходные структуры, используя Type Embedding , как @nosсказанное выше, тогда вы можете попытаться создать другую структуру для внутреннего использования метода:

var v Vehicle // with common fields

switch data.(type) {
case *Car:
    v.Handle = data.(*Car).Handle // or CircleHandle
case *Motorcycle:
    v.Handle = data.(*Motorcycle).Handle // or BarHandle
}

v.Degree = 15
v.Speed = 50
v.Direction = "left"
v.Style = "rough"
/// so many things on `v`...

steering(v)

Я думаю, что это не очень хороший подход, но иногда ...: -)

0 голосов
/ 11 сентября 2018

Go - статически типизированный язык, тип a должен быть известен во время компиляции.А поскольку Go пока не поддерживает генерики, вы не можете делать то, что хотите.

Попробуйте найти какое-то другое решение, например, абстрагировать то, что вы хотите сделать с a, в интерфейс,и конкретные типы реализуют этот интерфейс.Тогда a может быть переменной этого типа интерфейса, и вы можете вызывать методы этого типа.

Если вы можете достичь этого, на самом деле вы даже можете изменить параметр типа data на этот интерфейс,и не требуется утверждение типа или переключение типа.

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

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