[Golang nâng cao] Queue trong Golang

Post on: 2023-04-12 00:09:19 | in: Golang
Trong Golang, một queue (hàng đợi) có thể được triển khai bằng cách sử dụng slice hoặc package container/list.

Giới thiệu

Một queue đơn giản có thể được triển khai trong GO bằng cách sử dụng:

  • package container/list
  • slice

Một queue sẽ có các hoạt động sau:

  • Enqueue (đưa phần tử vào queue)
  • Dequeue (lấy phần tử ra khỏi queue)
  • Front (trả về phần tử đầu tiên trong queue)
  • Size (trả về số lượng phần tử trong queue)
  • Empty (kiểm tra xem queue có rỗng không)

Triển khai sử dụng list

Đối với cách triển khai sử dụng package container/list, bạn có thể sử dụng phương thức PushBack để thêm phần tử vào cuối queue và sử dụng phương thức Front để lấy phần tử đầu tiên. Dưới đây là một ví dụ về cách triển khai một queue sử dụng package container/list trong Golang:

package main

import (
    "container/list"
    "fmt"
)

type customQueue struct {
    queue *list.List
}

func (c *customQueue) Enqueue(value string) {
    c.queue.PushBack(value)
}

func (c *customQueue) Dequeue() error {
    if c.queue.Len() > 0 {
        ele := c.queue.Front()
        c.queue.Remove(ele)
    }
    return fmt.Errorf("Pop Error: Queue is empty")
}

func (c *customQueue) Front() (string, error) {
    if c.queue.Len() > 0 {
        if val, ok := c.queue.Front().Value.(string); ok {
            return val, nil
        }
        return "", fmt.Errorf("Peep Error: Queue Datatype is incorrect")
    }
    return "", fmt.Errorf("Peep Error: Queue is empty")
}

func (c *customQueue) Size() int {
    return c.queue.Len()
}

func (c *customQueue) Empty() bool {
    return c.queue.Len() == 0
}

func main() {
    customQueue := &customQueue{
        queue: list.New(),
    }
    fmt.Printf("Enqueue: A\n")
    customQueue.Enqueue("A")
    fmt.Printf("Enqueue: B\n")
    customQueue.Enqueue("B")
    fmt.Printf("Size: %d\n", customQueue.Size())
    for customQueue.Size() > 0 {
        frontVal, _ := customQueue.Front()
        fmt.Printf("Front: %s\n", frontVal)
        fmt.Printf("Dequeue: %s\n", frontVal)
        customQueue.Dequeue()
    }
    fmt.Printf("Size: %d\n", customQueue.Size())
}

Output:

Enqueue: A
Enqueue: B
Size: 2
Front: A
Dequeue: A
Front: B
Dequeue: B
Size: 0

Triển khai sử dụng slice

Đối với cách triển khai sử dụng slice, bạn có thể sử dụng hàm append để thêm phần tử vào cuối slice và sử dụng hàm copy để xóa phần tử đầu tiên. Dưới đây là một ví dụ về cách triển khai một queue sử dụng slice trong Golang:

package main

import (
"fmt"
"sync"
)

type customQueue struct {
queue []string
lock  sync.RWMutex
}

func (c *customQueue) Enqueue(name string) {
c.lock.Lock()
defer c.lock.Unlock()
c.queue = append(c.queue, name)
}

func (c *customQueue) Dequeue() error {
if len(c.queue) > 0 {
  c.lock.Lock()
  defer c.lock.Unlock()
  c.queue = c.queue[1:]
  return nil
}
return fmt.Errorf("Pop Error: Queue is empty")
}

func (c *customQueue) Front() (string, error) {
if len(c.queue) > 0 {
  c.lock.Lock()
  defer c.lock.Unlock()
  return c.queue[0], nil
}
return "", fmt.Errorf("Peep Error: Queue is empty")
}

func (c *customQueue) Size() int {
return len(c.queue)
}

func (c *customQueue) Empty() bool {
return len(c.queue) == 0
}

func main() {
customQueue := &customQueue{
  queue: make([]string, 0),
}

fmt.Printf("Enqueue: A\n")
customQueue.Enqueue("A")
fmt.Printf("Enqueue: B\n")
customQueue.Enqueue("B")
fmt.Printf("Len: %d\n", customQueue.Size())

for customQueue.Size() > 0 {
  frontVal, _ := customQueue.Front()
  fmt.Printf("Front: %s\n", frontVal)
  fmt.Printf("Dequeue: %s\n", frontVal)
  customQueue.Dequeue()
}
fmt.Printf("Len: %d\n", customQueue.Size())
}

Output:

Enqueue: A
Enqueue: B
Size: 2
Front: A
Dequeue: A
Front: B
Dequeue: B
Size: 0

Tổng kết

Đó là tất cả những gì cần biết về queue trong Go. Mong rằng bạn sẽ thích bài viết này. Vui lòng chia sẻ phản hồi/cải tiến/sai sót trong  phần bình luận.

Tag: go Golang nâng cao