当前位置: 首页 > 知识库问答 >
问题:

结构的切片!=它实现的接口的一部分?

郎恺
2023-03-14

我有一个接口模型,它是由structPerson实现的。

要获取模型实例,我有以下助手函数

func newModel(c string) Model {
    switch c {
    case "person":
        return newPerson()
    }
    return nil
}

func newPerson() *Person {
    return &Person{}
}

上述方法允许我返回一个正确类型的Person实例(以后可以使用相同的方法轻松添加新模型)。

当我尝试执行类似的操作以返回模型片段时,我得到了一个错误。代码:

func newModels(c string) []Model {
    switch c {
    case "person":
        return newPersons()
    }
    return nil
}

func newPersons() *[]Person {
    var models []Person
    return &models
}

Go抱怨:不能在返回参数中使用newPeople()(type[]Person)作为type[]Model

我的目标是返回所请求的任何模型类型的切片(无论是[]Person[]FutureModel[]Terminator2000,w/e)。我遗漏了什么?我如何才能正确实施这样的解决方案?

共有3个答案

訾俊名
2023-03-14

因为斯蒂芬已经回答了这个问题,你是初学者,所以我强调给出建议。

使用go接口的更好方法不是让构造函数返回接口,就像您在其他语言(如java)中使用的那样,而是让每个对象都有一个独立的构造函数,因为它们隐式地实现接口。

而不是

newModel(type string) Model { ... }

你应该这样做

newPerson() *Person { ... }
newPolitician() *Politician { ... }

Personpolitical一起实现Model的方法。您仍然可以在接受模型的任何地方使用Personpolitical,但也可以实现其他接口。

在手动转换到另一种接口类型之前,使用您的方法只能使用Model

假设我有一个Person实现了方法Walker()和一个Model实现了Showoff(),以下内容将无法直接执行:

newModel("person").ShowOff()
newModel("person").Walk() // Does not compile, Model has no method Walk

然而,这将:

newPerson().ShowOff()
newPerson().Walk()

丁阳炎
2023-03-14

也许这是您的返回类型*[]Person的问题,它实际上应该是[]*Person,以便引用切片的每个索引都是对Person的引用,并且切片[]本身是对数组的引用。

请查看以下示例:

package main

import (
    "fmt"
)

type Model interface {
    Name() string
}

type Person struct {}

func (p *Person) Name() string {
    return "Me"
}

func NewPersons() (models []*Person) {
    return models
}

func main() {
    var p Model
    p = new(Person)
    fmt.Println(p.Name())

    arr := NewPersons()
    arr = append(arr, new(Person))
    fmt.Println(arr[0].Name())
}
许俊风
2023-03-14

这很像我刚才回答的一个问题:https://stackoverflow.com/a/12990540/727643

简而言之,你是对的。结构的切片不等于结构实现的接口的切片。

[]个人[]型号具有不同的内存布局。这是因为它们所属的类型具有不同的内存布局。一个模型是一个接口值,这意味着在内存中它的大小是两个字。一个字表示类型信息,另一个字表示数据。Person是一个结构,其大小取决于它包含的字段。为了将[]个人转换为[]模型,您需要在数组上循环并对每个元素进行类型转换。

由于此转换是一个O(n)操作,并且会导致创建一个新的切片,所以Go拒绝隐式地进行转换。您可以使用以下代码显式地执行此操作。

models := make([]Model, len(persons))
for i, v := range persons {
    models[i] = Model(v)
}
return models

正如dskner所指出的,您很可能想要一个指针片段,而不是一个指向片段的指针。通常不需要指向切片的指针。

*[]Person        // pointer to slice
[]*Person        // slice of pointers
 类似资料:
  • 问题内容: 我有一个接口,该接口由struct实现。 要获取模型实例,我具有以下辅助函数: 上面的方法允许我返回正确类型的Person实例(以后可以使用相同的方法轻松添加新模型)。 当我尝试执行类似的操作以返回模型切片时,出现错误。码: 去抱怨: 我的目标是回到请求任何机型的切片(是否,,,W / E)。我缺少什么,如何正确实施这样的解决方案? 问题答案: 简短的答案是您是正确的。结构的片段不等于

  • 问题内容: 给定您具有接受功能的场景。如果确定是切片,我如何在该切片上? 前往游乐场示例:http://play.golang.org/p/DNldAlNShB 问题答案: 好吧,我曾经使用过,然后如果它是一个切片,则可以调用,并在该值上调用以在索引处获取切片和元素的。我认为您将无法使用范围操作来做到这一点。 前往游乐场示例:http : //play.golang.org/p/gQhCTiwPA

  • 本文向大家介绍C#结构实现接口,包括了C#结构实现接口的使用技巧和注意事项,需要的朋友参考一下 示例            

  • 问题内容: 我不理解以下代码的行为。在创建作为结构指针切片的匹配结构列表时,代码始终会打印原始数组的最后一个元素(实际上不是匹配项),它会打印12和12。但是,如果将匹配项更改为[]窗口小部件代替[] * Widget,然后将输出10和11。 为什么是这样? 问题答案: 那是因为当您使用指针时,您将添加到数组。 请注意,实际上这是循环中使用的局部变量,因此,这不是您要添加到数组中的地址。 (即使变

  • 问题内容: 我将如何为正在实现接口的内部类编写构造函数?我知道我可以上一门全新的课,但是我认为必须有一种方法可以做到这一点: 当我输入此内容时,它不会将AbstractAction方法识别为构造函数(编译器要求返回类型)。有人有主意吗? 问题答案: 只需在扩展类的名称后面插入参数即可: 另外,您可以使用初始化块:

  • 我也试过: 它可以在其他Kotlin文件中工作(我可以编写),但我必须用Java编写。这个解决方案似乎最接近我想要的。 有什么解决办法吗?我希望能够用Kotlin和Java编写,并让它们引用一个实现接口的对象。 我相信我也可以将我的接口转换成一个抽象类,但这是最后的手段。