作为学习Go的练习,我正在编写一个基本的Queue数据结构。我昨天开始学习有关接口的知识,我认为尝试将其用于本练习将很酷。我要完成的工作是拥有一个Queue
可以接受实现此接口的任何类型的对象:
type Queuable interface {
Next() *Queuable // This is probably not right
}
基本上,我想要的是能够将任何具有Next()
方法的类型添加到我的Queue
。所以我尝试的是:
type Node struct {
value interface{}
next *Queuable
}
// Next gets the next object
func (n *Node) Next() *Queuable {
return n.next
}
// Job - A job for the queue
type Job struct {
instruction string
next *Queuable
}
// Next gets the next object
func (j *Job) Next() *Queuable {
return j.next
}
// Queue ...
type Queue struct {
head *Queuable
size int
}
我的方法看起来像:
func (q *Queue) Enqueue(node *Queuable) {
...
}
// Dequeue - Remove a Queueable form the Queue
func (q *Queue) Dequeue() *Queuable {
result := q.head
q.head = q.head.Next()
q.size--
return result
}
我收到大量这些错误(基本上是在有作业的任何一行上):
current.Next undefined (type *Queuable is pointer to interface, not interface)
因此,最终我想做的是:
func main() {
queue := NewQueue() // Helper function not pictured
job := &Job{"some instructions", nil}
node := &Node{5, nil}
queue.Enqueue(node) // queue = [node]
queue.Enqueue(job) // queue = [node, job]
queue.Dequeue() // node
queue.Dequeue() // job
}
不要使用指向接口类型的指针,而只需使用接口类型。
Queuable
是接口类型,因此在您使用过的代码中的任何地方都*Queuable
将其更改为Queuable
。例如:
type Queuable interface {
Next() Queuable
}
type Node struct {
value interface{}
next Queuable
}
// Next gets the next object
func (n *Node) Next() Queuable {
return n.next
}
...
在Go中,接口类型的值存储一对:分配给变量的具体值以及该值的类型描述符。
有关界面内部的更多信息:反射定律#界面的表示形式
因此,您几乎永远不需要接口的指针。接口包含键/值对,其中键可以是指针。指向接口的指针有意义的罕见情况是,您想修改传递给另一个函数的接口类型变量的值。
在您的示例中,该类型之所以*Job
实现,Queuable
是因为该类型具有一个具有接收器类型的方法*Job
,因此在需要值的任何地方都可以使用Queuable
值*Job
(并且Queuable
将创建和使用类型的隐式接口值)。
回到您的示例:
您Queuable
只定义了一种方法来获取队列中的下一个元素,但没有一个方法将其排队,这会使该解决方案失去灵活性。单个Next()
方法仅描述它是
“排队的”, 但不是(必需) “排队的” 。
为了 排队, 我还要添加另一种方法:SetNext(Queuable)
type Queuable interface {
Next() Queuable
SetNext(Queuable)
}
其实现Node
例如可以是:
func (n *Node) SetNext(q Queuable) { n.next = q }
在上尝试一下[Go Playground](http://play.golang.org/p/2RCRpV_NBX)
。
还要注意的是有一些代码重复Node
和Job
,作为next
场Next()
和SetNext()
方法。我们可以创建一个基本节点实现,例如:
type Base struct {
next Queuable
}
func (b *Base) Next() Queuable { return b.next }
func (b *Base) SetNext(q Queuable) { b.next = q }
现在你可以嵌入这个Base
在您的具体类型Node
和Job
实现其将“继承”的next
领域,Next()
和SetNext()
方法,所以你不必定义对任何这些Node
和Job
类型。
这是全面落实Node
和Job
,没有别的要求:
type Node struct {
*Base
value interface{}
}
type Job struct {
*Base
instruction string
}
在上尝试一下[Go Playground](http://play.golang.org/p/Fv9HbYJyhQ)
。
我试图创建像@repository这样的系统。
我正在使用openapi生成器生成java类。 我希望模型类实现openapi生成器尚未生成的外部接口。 有什么东西可以在yaml模型中定义,或者有一个属性可以传递给openapi生成器maven插件,允许这种行为? 所需行为的示例:
我正在使用一个接口来定义一个新类型。这是正确的做法吗?我做如下: 然后,为了实例化它,我必须这样做: 它实际上创建了一个空对象,这不是我想要的;但是如果没有这个,它会引发一个错误,例如,“无法读取未定义的属性‘问题’”。我定义新类型的方法是错误的吗? ====EDIT====以下是我根据你的评论所做的: 然后我说: 然后我仍然得到这个错误:无法读取未定义的属性“push”。我不想在定义接口的地方启
这个问题直接类似于使用TypeScript进行类类型检查
7.2. 接口类型 接口类型具体描述了一系列方法的集合,一个实现了这些方法的具体类型是这个接口类型的实例。 io.Writer类型是用的最广泛的接口之一,因为它提供了所有的类型写入bytes的抽象,包括文件类型,内存缓冲区,网络链接,HTTP客户端,压缩工具,哈希等等。io包中定义了很多其它有用的接口类型。Reader可以代表任意可以读取bytes的类型,Closer可以是任意可以关闭的值,例如一
问题内容: 考虑以下代码: 当我们尝试调用新定义的方法时,这是不可能的。这样做的原因是,它被声明为类型的对象,而不是我们新的匿名子类的实例。 因此,我的问题是,是否有任何“不错”的方式来实现这种行为?除了显而易见的(正确地声明类)。 问题答案: 这是不可能的,因为您试图在超类引用上调用方法子类。而且该方法未在超类本身中定义。匿名类只是那里的一个子类。 但是,一种解决方法是进行反思: 该方法将返回的