Отражение, показывающее другой тип, отличный от ошибки - PullRequest
0 голосов
/ 11 октября 2018

Справочная информация: Я использую govmomi для сбора конфигурации для VMware.Сейчас я нахожусь в процессе получения информации о хранилище данных, которая мне нужна.Одно из полей, которое мне нужно, это диск Naa.Это можно найти в структуре VmfsDatastoreInfo в поле Vmfs.

Проблема: Я перебираю диапазон и считаю, что Ds.Info относится к типу VmfsDatastoreInfo, поэтому теоретически я мог быполучить необходимую информацию, пройдя через Ds.Info.Vmfs.Когда я ссылаюсь на это, я получаю ошибку:

ds.Info.Vmfs undefined (type types.BaseDatastoreInfo has no field or method Vmfs)

Из любопытства я исследовал с помощью отражения и сделал следующее:

fmt.Println(reflect.TypeOf(ds.Info))

вывод был

*types.VmfsDatastoreInfo

Я пытаюсь понять, почему один и тот же объект отображается как два разных типа?

Редактировать: Как добраться до ds:

c, err := govmomi.NewClient(ctx, u, true)

//Check if the connection was successful
if err != nil {
    fmt.Println(err)
}

// Create view of Datastore objects
m := view.NewManager(c.Client)

d, _ := m.CreateContainerView(ctx, c.ServiceContent.RootFolder, []string{"Datastore"}, true)



if err != nil {
    log.Fatal(err)
}

defer d.Destroy(ctx)

//Retrieve a list of all Virtual Machines including their summary and runtime
var dss []mo.Datastore
err = d.Retrieve(ctx, []string{"Datastore"}, []string{"info", "host"}, &dss)
if err != nil {
    log.Fatal(err)
}


for _, ds := range dss {
    fmt.Println(reflect.TypeOf(ds.Info))
    s := reflect.ValueOf(ds.Info).Elem()

    typeOfT := s.Type()

    for i := 0; i < s.NumField(); i++ {

    f := s.Field(i)

    fmt.Println(i, typeOfT.Field(i).Name, f.Type(), f.Interface())

    }

}

ds является типом хранилища данных:

type Datastore struct {
    ManagedEntity

    Info              types.BaseDatastoreInfo        `mo:"info"`
    Summary           types.DatastoreSummary         `mo:"summary"`
    Host              []types.DatastoreHostMount     `mo:"host"`
    Vm                []types.ManagedObjectReference `mo:"vm"`
    Browser           types.ManagedObjectReference   `mo:"browser"`
    Capability        types.DatastoreCapability      `mo:"capability"`
    IormConfiguration *types.StorageIORMInfo         `mo:"iormConfiguration"`
}

Просматривая информацию о пакете Govmomi, я обнаружил следующее

type BaseDatastoreInfo interface {
    GetDatastoreInfo() *DatastoreInfo
}

func (b *DatastoreInfo) GetDatastoreInfo() *DatastoreInfo

type DatastoreInfo struct {
    DynamicData

    Name                   string     `xml:"name"`
    Url                    string     `xml:"url"`
    FreeSpace              int64      `xml:"freeSpace"`
    MaxFileSize            int64      `xml:"maxFileSize"`
    MaxVirtualDiskCapacity int64      `xml:"maxVirtualDiskCapacity,omitempty"`
    MaxMemoryFileSize      int64      `xml:"maxMemoryFileSize,omitempty"`
    Timestamp              *time.Time `xml:"timestamp"`
    ContainerId            string     `xml:"containerId,omitempty"`
}

Информация о структуре Govmomi

1 Ответ

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

Я пытаюсь понять, почему один и тот же объект отображается как два разных типа?

Это не так.

Я полагал, что Ds.Infoтипа VmfsDatastoreInfo

Нет.если ds является Datastore, то ds.Info имеет тип BaseDatastoreInfo, который является интерфейсом и поэтому имеет только один метод GetDatastoreInfo().Вот почему вы видите ошибку

ds.Info.Vmfs undefined (type types.BaseDatastoreInfo has no field or method Vmfs)

Теперь прочитайте всю документацию по пакету отражений пакета и документацию по отражению. TypoOf.Теперь прочитайте https://blog.golang.org/laws-of-reflection.

Ваш reflect.TypeOf(ds.Info) разрешает динамический тип ds.Info (его статический тип - BaseDatastoreInfo).Для простого примера смотрите: https://play.golang.org/p/kgDYXv4i63T. reflect.TypeOf смотрит внутри своего аргумента (который interface {});если он не будет сообщать всегда о статическом типе, рефлексирует.TypeOf будет всегда сообщать interface{}).

Возможно, вам просто следует использовать интерфейс без отражения:

ds.Info.GetDatastoreInfo()

и использовать этоИнформация.Не нужно здесь задумываться.

...