返回介绍

上卷 程序设计

中卷 标准库

下卷 运行时

源码剖析

附录

5.3.1 应用

发布于 2024-10-12 19:15:47 字数 2789 浏览 0 评论 0 收藏 0

切片除作为非正式 “数组指针” 外,还充当 动态数组向量 (vector)角色。
当然,更可实现一些常用数据结构。

// FILO: 先进后出,栈。

type Stack []int

func NewStack() *Stack {
	s := make(Stack, 0, 10)
	return &s
}

func (s *Stack) Push(v int) {
	*s = append(*s, v)
}

func (s *Stack) Pop() (int, bool) {
	if len(*s) == 0 {
		return 0, false
	}

	x, n := *s, len(*s)
	
	v := x[n - 1]
	*s = x[:n - 1]

	return v, true
}

// ---------------------------

func main() {
	s := NewStack()
    
	// push
	for i := 0; i < 5; i++ {
		s.Push(i + 10)
	}
    
	// pop
	for i := 0; i < 7; i++ {
		fmt.Println(s.Pop())
	}
}

/*

14 true
13 true
12 true
11 true
10 true
0 false
0 false

*/
// FIFO:先进先出,队列。

type Queue []int

func NewQueue() *Queue {
	q := make(Queue, 0, 10)
	return &q
}

func (q *Queue) Put(v int) {
	*q = append(*q, v)
}

func (q *Queue) Get() (int, bool) {
	if len(*q) == 0 {
		return 0, false
	}

	x := *q
	v := x[0]

	// copy(x, x[1:])
	// *q = x[:len(x) - 1]
    
    *q = append(x[:0], x[1:]...)  // 等同上两行。

	return v, true
}

// ---------------------------

func main() {
	q := NewQueue()
    
	// put
	for i := 0; i < 5; i++ {
		q.Put(i + 10)
	}
    
	// get
	for i := 0; i < 7; i++ {
		fmt.Println(q.Get())
	}
}

/*

10 true
11 true
12 true
13 true
14 true
0 false
0 false

*/

容量固定,且无需移动数据的环状队列。

import (
	"log"
	"sync"
	"math/rand"
	"time"
)

type Queue struct {
	sync.Mutex
	data []int
	head int
	tail int
}

func NewQueue(cap int) *Queue {
	return &Queue{ data: make([]int, cap) }
}

func (q *Queue) Put(v int) bool {
	q.Lock()
	defer q.Unlock()

	if q.tail - q.head == len(q.data) {
		return false
	}

	q.data[q.tail % len(q.data)] = v
	q.tail++

	return true
}

func (q *Queue) Get() (int, bool) {
	q.Lock()
	defer q.Unlock()

	if q.tail - q.head == 0 {
		return 0, false
	}

	v := q.data[q.head % len(q.data)]
	q.head++

	return v, true
}

// ---------------------------

func main() {
	rand.Seed(time.Now().UnixNano())

	const max = 100000
	src := rand.Perm(max)        // 随机测试数据。
	dst := make([]int, 0, max)

	q := NewQueue(6)

	// ------------------------

	var wg sync.WaitGroup
	wg.Add(2)

	// put
	go func() {
		defer wg.Done()
		for _, v := range src {
			for {
				if ok := q.Put(v); !ok {
					continue
				}
				break
			}
		}
	}()

	// get
	go func() {
		defer wg.Done()
		for len(dst) < max {
			if v, ok := q.Get(); ok {
				dst = append(dst, v)
				continue
			}
		}
	}()

	wg.Wait()

	// 转换成数组进行比较。
	if *(*[max]int)(src) != *(*[max]int)(dst) {
		log.Fatalln("fail !!!")
	}

	log.Printf("%+v\n", *q)
}

// {data:[99011 52214 53425 10572 82360 78821] head:100000 tail:100000}

SliceTricks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文