【问题标题】:How do I get the type of struct in Go? [closed]如何在 Go 中获取 struct 的类型? [关闭]
【发布时间】:2019-01-15 11:47:52
【问题描述】:

我正在做一个演示项目来理解 GO 语言。我定义了一个接口和两个结构类型。另外,我定义了一个接口数组。根据用户输入,我将数组中的每个元素定义为一种结构。在数据操作过程中,我想检查数组上定义的结构的类型。

我曾尝试使用反射,但不幸的是它没有奏效。互联网上的其他方法也不起作用。我收到了诸如 panic 或 json cannot Unmarshal 之类的消息。

type Main_interface interface {
}

type Struct1 struct {
    Index                         int
    ID                            int
    Name                          string
}

type Struct2 struct {
    Index                         int
    Timestamp                     string
    Temporary_ID                  int
}


var MyArray []Main_interface

//...
NewStruct1Block := generateStruct1Block(...)
MyArray = append(MyArray, NewStruct1Block)

//...
NewStruct2Block := generateStruct2Block(...)
MyArray = append(MyArray, NewStruct2Block)

更新:我希望能够检查在运行时实现接口的结构类型,具体取决于用户输入。

【问题讨论】:

  • 尚不清楚您遇到了什么错误或您正在尝试做什么。有关类型断言的基础知识,请参阅此答案 stackoverflow.com/questions/38816843/… 和此 go 部分之旅 tour.golang.org/methods/15 - 也许这就是您要寻找的东西?
  • 这里最好的建议可能是:不要尝试使用反射来理解发生了什么。反射是困难。即使您了解语言以及接口和类型系统如何工作,也很难。试图通过使用反射来增加对类型系统的理解注定要失败。
  • 如果您尝试了某项操作但没有成功,请在您的问题正文中包含该代码,并附上有关它不起作用的方式的详细信息。
  • 我尝试了以下两种解决方案。我通过硬编码在 main 中初始化数组的第一个元素。类型测试适用于该元素。其余元素根据用户输入进行初始化,返回的元素类型为接口类型。我不想要这个。我想要返回 Struct1 或 Struct2。
  • 好的,您的问题的答案是type assestion。在不了解您的特定要求的情况下,实际上不可能为您提供一个完全正常工作的应用程序(并且此资源不用于此目的),因为目前它们看起来有点混乱。

标签: go


【解决方案1】:

你的数组可以是异构的,也就是说,它可以包含不同类型的元素。您无法确保(在编译时)所有元素都属于同一类型。

也就是说,您可以使用类型转换语法检查单个元素。

您有三个选择:

选项 1:检查特定类型

var unknown Main_Interface = getSomethingSomewhere()
result, ok := unknown.(Struct1);
if ok {
    // result has type `Struct1` 
}

选项 2:使用 switch 语句覆盖多种类型(已在另一个答案中提出)

switch t := unknown.(type) {
case Struct1:
    // t has type `Struct1` within this block (at compile time)
case Struct2:
    // t has type `Struct2` within this block (at compile time)
default:
    // neither Struct1 no Struct2
}

选项 3:在运行时与另一种类型进行比较。

请注意,reflect.TypeOf 返回的类型可以使用 == 运算符进行比较,如下所述:

https://golang.org/pkg/reflect/#Type

类型值是可比较的,例如使用 == 运算符,因此它们可以用作映射键。如果两个 Type 值表示相同的类型,则它们是相等的。

所以我们可以这样做:

var s1 Struct1 // empty struct
var s2 Struct2 // empty struct
if reflect.TypeOf(unknown) == reflect.TypeOf(s1) {
    // unknown holds an s1 instance
}

但是当您可以只进行编译时检查时,这显然没有用。相反,您可以比较两个未知数来检查它们是否相同:

var unknown1 Main_Interface = getSomethingSomewhere()
var unknown2 Main_Interface = getSomethingSomewhereElse()

if reflect.TypeOf(unknown1) == reflect.TypeOf(unknown2) {
    // they are the same type
}

【讨论】:

  • 为了清楚起见,选项 1 是类型 assertion,而不是类型 castgolang.org/ref/spec#Type_assertions
  • 这些解决方案仅适用于我通过硬编码在 main 中初始化的数组的第一个元素。其余元素作为主界面返回。
  • @Liviu 如果这不能回答你的问题,那么我不明白你的问题。也许你可以更好地澄清它?
【解决方案2】:

你需要使用如下的类型评估:

var MyArray []Main_interface

NewStruct1Block := Struct1{}
NewStruct2Block := Struct2{}

MyArray = append(MyArray, NewStruct1Block)
MyArray = append(MyArray, NewStruct2Block)

fmt.Printf("%v", MyArray)

switch t := MyArray[0].(type) {
case Struct1:
    fmt.Printf("%v", t)
    t.ID = 1
case Struct2:
    fmt.Printf("%v", t)
    t.Timestamp = "A"
default:
    fmt.Print("unknown")
}

这里的工作代码: https://play.golang.org/p/OhpBDJu_q2x

【讨论】:

  • 不幸的是,此解决方案返回 Main_interface 类型。我想返回 Struct1 类型或 Struct2 类型,即使我只附加 Struct1 或 Struct1 类型
  • 你确定吗?此解决方案根本不返回类型,如果类型为Struct1Struct2,则打印,否则打印unknown
  • 不,它没有。请在操场上检查更新的代码:您可以将结构值分配给t
  • 此解决方案仅适用于我通过硬编码在 main 中初始化的数组的第一个元素。其余元素作为主界面返回。
猜你喜欢
  • 2013-09-01
  • 2015-03-05
  • 2017-12-20
  • 2014-08-27
  • 1970-01-01
  • 1970-01-01
  • 2018-08-21
  • 2012-11-30
  • 2018-02-03
相关资源
最近更新 更多