接受界面中的一片与结构B的切片呼叫转到功能(B实现A)

我有以下几种类型:接受界面中的一片与结构B的切片呼叫转到功能(B实现A)

type Statement interface { 

Say() string

}

type Quote struct {

quote string

}

func (p Quote) Say() string {

return p.quote

}

func Replay(conversation []Statement) {

for _, statement := range conversation {

fmt.Println(statement.Say())

}

}

我想我为什么功能的一个相当不错的把握接受[]Statement类型的参数,不能用[]Quote调用;即使Quote实施了Statement,[]Quote也没有实施[]Statement[]Statement甚至不是一个接口。它有slice of Statement。虽然Go隐式地从类型转换为接口类型,但它不会从A类型的片段到片段接口B的隐式转换。

我们可以将报价转换为明确声明:

conversation := []Quote{ 

Quote{"Nice Guy Eddie: C'mon, throw in a buck!"},

Quote{"Mr. Pink: Uh-uh, I don't tip."},

Quote{"Nice Guy Eddie: You don't tip?"},

Quote{"Mr. Pink: Nah, I don't believe in it."},

Quote{"Nice Guy Eddie: You don't believe in tipping?"},

}

// This doesn't work

// Replay(conversation)

// Create statements from quotes

statements := make([]Statement, len(conversation))

for i, quote := range conversation {

statements[i] = quote

}

Replay(statements)

现在说,重播是要出门其方式是多么容易使用重播库的一部分。只要这些对象实现了Statement接口,它就允许您使用任何切片对象调用Replay。要做到这一点,有以下转换方法:

func ConvertToStatements(its interface{}) ([]Statement, error) { 

itsValue := reflect.ValueOf(its)

itsKind := itsValue.Kind()

if itsKind != reflect.Array && itsKind != reflect.Slice {

return nil, fmt.Errorf("Expected items to be an Array or a Slice, got %s", itsKind)

}

itsLength := itsValue.Len()

items := make([]Statement, itsLength)

for i := 0; i < itsLength; i++ {

itsItem := itsValue.Index(i)

if item, ok := itsItem.Interface().(Statement); ok {

items[i] = item

} else {

return nil, fmt.Errorf("item #%d does not implement the Statement interface: %s", i, itsItem)

}

}

return items, nil

}

重播看起来是这样的:

func Replay(its interface{}) { 

conversation := ConvertToStatements(its)

for _, statement := range conversation {

fmt.Println(statement.Say())

}

}

现在,我们可以直接调用重播时报价:

Replay(conversation) 

最后,我的问题:只要A实现Statement接口,是否有更简单的方法允许Replay接受任何类型A的切片?

回答:

非常简短的回答你(长)的问题是:第

我不认为你的ConvertToStatment和重播服用空接口解决方案是一个“好”的解决方案:我宁愿func Replay([]Statement)并且来电者必须提供一部分声明。这更清晰,呼叫者可以将他们的东西转换为[]语句或直接构造一个[]语句。

一个

[]Quote切片的

回答:

在内存中的布局是一个[]Statement切片不同,所以这是不可能的。

[]Quote切片的后备阵列将由顺序Quote结构组成,而[]Statement切片的后备阵列由接口变量组成。除了持有Quote结构(或任何其他类型实现接口)之外,接口变量还存储指向包含值的类型信息的指针。这需要确定如何分派Say方法调用。

不同的数据布局意味着你不能交换两个片类型,甚至通过不安全的强制转换不:如果你有一个类型,需要其他的你就需要在它们之间进行手动转换。

回答:

以下代码有两种不同的结构类型,它们都实现Say()函数。您可以创建包含两种类型的数组,并调用Replay(),并让它做你想要什么:

package main 

import "fmt"

type Statement interface {

Say() string

}

type Statements []Statement

type Quote struct {

quote string

}

type Quotes []Quote

func (p Quote) Say() string {

return p.quote

}

type Attributed struct {

who string

quote string

}

func (p Attributed) Say() string {

return p.who + ": " + p.quote

}

func Replay(conversation []Statement) {

for _, s := range conversation {

fmt.Println(s.Say())

}

}

func (q Quotes) toStatements() Statements {

conv := make(Statements, len(q))

for i, v := range q {

conv[i] = Statement(v)

}

return conv

}

func main() {

conversation := Statements{

Quote{"Nice Guy Eddie: C'mon, throw in a buck!"},

Quote{"Mr. Pink: Uh-uh, I don't tip."},

Attributed{"Nice Guy Eddie", "You don't tip?"}, // <= another type

Quote{"Mr. Pink: Nah, I don't believe in it."},

Quote{"Nice Guy Eddie: You don't believe in tipping?"},

}

myquotes := Quotes{

Quote{"Nice Guy Eddie: C'mon, throw in a buck!"},

Quote{"Mr. Pink: Uh-uh, I don't tip."},

Quote{"Nice Guy Eddie: You don't tip?"},

Quote{"Mr. Pink: Nah, I don't believe in it."},

Quote{"Nice Guy Eddie: You don't believe in tipping?"},

}

Replay(conversation)

Replay(myquotes.toStatements())

}

Replay()不改变或了解Attributed{}什么。 你必须引入切片类型Quotes & Statements

以上是 接受界面中的一片与结构B的切片呼叫转到功能(B实现A) 的全部内容, 来源链接: utcz.com/qa/265134.html

回到顶部