使用接口为任意类型创建队列 [英] Using Interfaces to Create a Queue for Arbitrary Types
问题描述
Queue
,它可以接受任何实现此接口的类型: 类型Queueable接口{
Next()* Queuable //这可能不正确
}
基本上我想要的是可以将任何具有 Next()
方法的类型添加到我的队列
。所以我试过的是:
类型Node结构{
value interface {}
next * Queuable
}
//下一个获取下一个对象
func(n * Node)Next()* Queuable {
return n.next
}
//作业 - 作业队列
类型作业结构{
指令字符串
下一个*可排队
}
/ / Next获取下一个对象
func(j * Job)Next()* Queuable {
return j.next
}
// Queue ...
类型Queue struct {
头*可排队
大小int
}
我的方法看起来像:
func(q * Queue)Enqueue(node * Queuable){
...
}
// Dequeue - 从队列中删除Queueable
func(q * Queue)Dequeue()* Queuable {
result:= q.head
q.head = q.head.Next()
q.size--
返回结果
}
我遇到了很多这样的错误(basicall y:
current.Next未定义(类型* Queuable是指向接口的指针,而不是接口)
因此,最终我想要做的是:
func main(){
queue:= NewQueue()//助手函数未显示
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
。例如:
$ $ p $ 类型Queueable接口{
下一个()Queueable
}
类型Node结构{
value interface {}
下一个可排序的
}
//下一个获取下一个对象
func(n * Node) Next()Queuable {
return n.next
}
...
在Go中,接口类型的值存储一对:分配给该变量的具体值,以及该值的类型描述符。
更多信息界面的内部: 所以你几乎不需要指向接口的指针。一个接口包含一个键值对,其中键可以是一个指针。如果你想修改传递给另一个函数的接口类型变量的值,那么这种情况很少见。 在你的例子中,类型 您的 成为 queuable 我也会添加另一个方法: 例如 试试 Go Playground 。 另请注意, 现在您可以将 这是完整的实现 请在 Go Playground 。 As an exercise for learning Go I am writing a basic Queue data structure. I started learning about interfaces yesterday I thought it would be cool to try and use them for this exercise. What I am trying to accomplish is to have a Basically what I want is to be able to add any type that has a And my methods looking like: I'm getting a ton of these errors (basically on any line with an assignment): So ultimately what I would like to do would be:
Don't use pointer to an interface type, just the interface type. In Go a value of interface type stores a pair: the concrete value assigned to the variable, and that value's type descriptor. More about interface's internals: The Laws of Reflection #The representation of an interface So you almost never need a pointer to interface. An interface contains a key-value pair where the key may be a pointer. The rare case when a pointer to interface makes sense is if you want to modify the value of a variable of interface type passed to another function. In your example the type Getting back to your example: Your To be queuable I would also add another method: Its implementation on Try it on the Go Playground. Also note that there is some code duplication in And now you can embed this This is the full implementation of Try this on the Go Playground. 这篇关于使用接口为任意类型创建队列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
* Job
实现 Queuable
,因为它有一个接收方类型为 * Job Queuable
值的地方,都可以使用 * Job
值将创建并使用 Queuable
只定义了一个获取队列中下一个元素的方法,但不能一个排队它会使这个解决方案失去灵活性。一个 Next()
方法只描述它是<排队> ,但它不是(必然)queuable。
SetNext(Queuable)
类型Queueable接口{
Next()Queuable
SetNext(Queuable)
}
Node
:
$ b
func(n * Node)SetNext(q Queuable){n.next = q}
Node $ c中有一些代码重复$ c>和
作业
下一个
字段和下一个()
和 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()
和 SetNext()
方法,所以您不必在 Node
和 Job 类型。
节点
和作业
,其他都不需要:
类型Node结构{
* Base
接口{}
}
类型作业结构{
* Base
指令字符串
}
Queue
that can accept any type that implements this interface:type Queuable interface {
Next() *Queuable // This is probably not right
}
Next()
method to my Queue
. So what I tried was: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
is an interface type, so everywhere in your code where you used *Queuable
, change it to Queuable
. For example: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
}
...
*Job
implements Queuable
because it has a method with receiver type *Job
, and so everywhere where a value of Queuable
is required, a value of *Job
can be used (and an implicit interface value of type Queuable
will be created and used).Queuable
only defines a method to get the next element in the queue, but not one to enqueue it which will make this solution lose flexibility. A single Next()
method only describes that it is "queued" but it is not (necessarily) "queuable".SetNext(Queuable)
type Queuable interface {
Next() Queuable
SetNext(Queuable)
}
Node
can be for example:func (n *Node) SetNext(q Queuable) { n.next = q }
Node
and Job
, being the next
field and Next()
and SetNext()
methods. We could create a base node implementation, e.g.:type Base struct {
next Queuable
}
func (b *Base) Next() Queuable { return b.next }
func (b *Base) SetNext(q Queuable) { b.next = q }
Base
type in your concrete Node
and Job
implementations which will "inherit" the next
field and Next()
and SetNext()
methods, so you don't have to define any of these on the Node
and Job
types.Node
and Job
, nothing else is required:type Node struct {
*Base
value interface{}
}
type Job struct {
*Base
instruction string
}