Video:

Implementing a Queue in Go

April 2, 2021

Course Instructor: Elliot Forbes

Hey Gophers! My name is Elliot and I'm the creator of TutorialEdge and I've been working with Go systems for roughly 5 years now.

👋 Welcome Gophers! In this video, we are going to be looking at how you can set about implementing the Queue data structure in Go. We’ll cover implementing all of the methods that a basic queue implementation needs.

We’ll be building this ourselves, without the help of additional packages or libraries. The focus on this tutorial is how can we effectively implement the Queue data structure and the concepts behind that as opposed to working with Queues for production applications.

Implementing a Queue in Go

With this in mind, let’s look at how we can implement this in Go.

We’ll start off by implementing a Queue struct which will contain a slice of type int:

package main

// Queue - our queue of ints!
type Queue struct {
  Elements []int
}

With this in place, let’s try and define a method that will allow us to add an item to our Queue.

// Enqueue - adds an element to the front of the queue
func (q Queue) Enqueue(elem int) {
    q.Elements = append(q.Elements, elem)
}

Perfect, we now have a function that will allow us to effectively enqueue an item onto the end of our queue.

Dequeue

So, we have an element within our queue, how do we retrieve the first element from the start of a queue? To do that, we need to implement a dequeue method which will return the first element and then update the Elements int slice so that the second element in the queue is now the first.

// Dequeue - removes the first element from a queue
func (q Queue) Dequeue() int {
      
}

Awesome, we now have the ability to add something to our queue and also to remove the first element from our queue.

Peek

We now have the basic functionality in place, however there are a few other helper methods that we should implement for a more complete Queue implementation. The first of these methods is going to be the Peek method which will allow us to retrieve the first element but doesn’t remove it from the queue.

// Peek - returns the first element from our queue without updating queue
func (q *Queue) Peek() (int, error) {
	if q.IsEmpty() {
		return 0, errors.New("empty queue")
	}
	return q.Elements[0], nil
}

The next method we’ll want to implement is the GetLength method which will return the number of elemenet we currently have in our Queue.

// GetLength - returns the length of the queue
func (q Queue) GetLength() int {
  return len(q.Elements)
}

And the final helper method we want to implement is the IsEmpty which will return true if the queue does not have anything else in it.

// LastElem - returns the last element of the queue
func (q Queue) IsEmpty() bool {
  return len(q.Elements) == 0
}

A Simple Queue Program

Now that we have a working implementation of a Queue in place, let’s actually put it to use and see how things work:

package main

type Queue struct {
  Elements []int
}

func main() {
	fmt.Println("Queues Section")

	queue := Queue{}
	fmt.Println(queue)
	queue.Enqueue(1)
	fmt.Println(queue)
	queue.Enqueue(2)
	fmt.Println(queue)
	elem, _ := queue.Dequeue()
	fmt.Println(elem)
	fmt.Println(queue)

}

Awesome, let’s try and run this within the terminal:

$ go run main.go
Consuming Elements From Queue

As you can see, our application has been able to instantiate a new Queue and then subsequently iterate through this queue using the Pop method that we defined on top of this Queue.

Quiz

Test your knowledge with these questions:

Conclusion

Awesome, so in this tutorial, we covered the Queue data structure and how we can effectively build our own implementation of this using Go. We’ve covered building the key methods that a Queue data structure needs to expose and how the underlying element slice should be updated when performing actions such as dequeueing and enqueueing objects onto the Queue.

In the next video, we’ll be looking at taking this a step further and implementing a Priority Queue.