如何让RemoveDead
函数接受实现Liver
的其他接口切片(甚至可能是结构指针切片),而对性能几乎没有影响?
在我看来,该函数必须以interface{}
作为参数并进行运行时转换,但我不确定如何进行转换。我还猜测,x.(Liver)
比Liver(x)
慢很多,因为后者是编译时转换。
复制粘贴函数并更改每个副本中的参数和返回类型是最佳解决方案吗?只需要三到四份副本,但它仍然会感觉像是一个非常笨拙的解决方案。
type Updater interface {
Liver
Update() bool
}
type Liver interface {
Alive() bool
}
func RemoveDead(all []Updater) []Updater {
for i := len(all) - 1; i >= 0; i-- {
if Liver(all[i]).Alive() == false {
all[i] = all[len(all)-1]
all = all[:len(all)-1]
}
}
return all
}
答案 0 :(得分:1)
正如您所提到的,[]Updater
类型的切片无法通过简单的类型断言转换为[]Liver
;它们的类型不是接口,而是接口片。出于同样的原因,无法将[]Updater
传递给想要[]interface{}
作为参数的函数。
但是,您可以使用reflect
包执行所需操作。反思很有用,但会以性能为代价。如果您认为成本较高,那么您可能必须使用复制粘贴解决方案。
下面的代码肯定可以改进,但它显示了如何用反射来解决问题,并且在制作基准时它可能很有用。目前它认为任何甚至U值都是Alive:
package main
import (
"fmt"
"reflect"
)
type Updater interface {
Alive() bool
Update() bool
}
type Liver interface {
Alive() bool
}
type U int
func (u U) Alive() bool { return u % 2 == 0 }
func RemoveDead(all interface{}) interface{} {
v := reflect.ValueOf(all)
if v.Kind() != reflect.Slice {
panic("RemoveDead requires a slice")
}
for i := v.Len() - 1; i >= 0; i-- {
l := v.Index(i)
if l.Interface().(Liver).Alive() == false {
l.Set(v.Index(v.Len()-1))
v = v.Slice(0, v.Len()-1)
}
}
return v.Interface()
}
func main() {
u := []U{1,4,7,2,12}
fmt.Println("Before: ", u)
u = RemoveDead(u).([]U)
fmt.Println("After: ", u)
}
输出:
Before: [1 4 7 2 12]
After: [2 4 12]
答案 1 :(得分:0)
您可以定义第三个界面:
type UpdaterLiver interface {
Updater
Liver
}
然后将RemoveDead
的定义更改为
func RemoveDead(all []UpdaterLiver) []UpdaterLiver