From fba0aaffa656062eecefb11c3cfb3614389fdf77 Mon Sep 17 00:00:00 2001 From: ccpwcn Date: Thu, 17 Oct 2024 17:03:50 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 8ca8c0c..dec9d79 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,7 @@ - Intersection 两个切片的交集。 - Union 两个切片的合集,如果遇到重复元素,只保留1个。 - Diff 两个切片的差集,以第一个参数为基准。 + - SplitCounter 根据给定总数和页大小,生成一个二维切片。许多时候我们需要这样快速完成分页,直接往其中填写内容,这就非常方便。 - [x] 结构体相关操作 - JoinStructsField 将任意结构体切片中的指定字段的值使用英文逗号拼接成一个字符串,例如:用户列表中,所有用户ID拼成一个字符串。 - PickStructsField 将任意结构体切片中的指定字段的值提取出来形成一个保持原类型的数组,例如:用户列表中,所有用户ID提取成一个用户ID数组。 From 73a1e94cd5cd89b033771d8d1b78d9abccad1738 Mon Sep 17 00:00:00 2001 From: ccpwcn Date: Sat, 21 Dec 2024 23:59:13 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E7=BB=93=E6=9E=84=E6=A0=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 7 +++++- snowflake.go | 4 ++-- stack.go | 43 +++++++++++++++++++++++++++++++++++ stack_test.go | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 113 insertions(+), 3 deletions(-) create mode 100644 stack.go create mode 100644 stack_test.go diff --git a/README.md b/README.md index dec9d79..006dc65 100644 --- a/README.md +++ b/README.md @@ -55,13 +55,18 @@ - [x] Map相关操作 - HasKey 是否拥有某个Key。 - MapKeys 将一个Map的所有Key转换成数组返回。 -- [x] 自定义Set(拥有的元素不可重复,类似于Java中的HashSet),添加的元素必须是可比较的,即实现了标准接口中的comparable,这也可以理解,如果元素不可比较,怎么知道是否重复是否已经存在了呢? +- [x] 数据结构:Set(拥有的元素不可重复,类似于Java中的HashSet),添加的元素必须是可比较的,即实现了标准接口中的comparable,这也可以理解,如果元素不可比较,怎么知道是否重复是否已经存在了呢? - Add 添加元素。 - Remove 删除元素。 - Clear 清空所有元素。 - Contains 是否在已经存在的元素中。 - Len 获得Set集合中元素的数量。 - Empty 判断Set元素是否是空的。 +- [x] 数据结构:Stack(栈),先进后出,后进先出。 + - Push 入栈。 + - Pop 出栈。 + - Peek 查看栈顶元素。 + - Size 获得栈中元素的数量。 - [x] Slice切片相关 - SlicePagination 切片分页,返回一个分好页的二维数组,可指定页大小。 - Contains 包含某个元素。 diff --git a/snowflake.go b/snowflake.go index 9dbb8de..737baed 100644 --- a/snowflake.go +++ b/snowflake.go @@ -10,11 +10,11 @@ import ( const ( epoch = int64(1577808000000) // 设置起始时间(时间戳/毫秒):2020-01-01 00:00:00,有效期69年 - timestampBits = uint(41) // 时间戳占用位数 + timestampBits41 = uint(41) // 时间戳占用位数 datacenterIdBits = uint(2) // 数据中心id所占位数 workerIdBits = uint(7) // 机器id所占位数 sequenceBits = uint(12) // 序列所占的位数 - timestampMax = int64(-1 ^ (-1 << timestampBits)) // 时间戳最大值 + timestampMax = int64(-1 ^ (-1 << timestampBits41)) // 时间戳最大值 datacenterIdMax = int64(-1 ^ (-1 << datacenterIdBits)) // 支持的最大数据中心id数量 workerIdMax = int64(-1 ^ (-1 << workerIdBits)) // 支持的最大机器id数量 sequenceMask = int64(-1 ^ (-1 << sequenceBits)) // 支持的最大序列id数量 diff --git a/stack.go b/stack.go new file mode 100644 index 0000000..556c4c8 --- /dev/null +++ b/stack.go @@ -0,0 +1,43 @@ +package kgo + +import ( + "errors" + "reflect" +) + +type Stack[T any] struct { + elements []any +} + +// NewStack 创建一个新的栈 +func NewStack[T any]() *Stack[T] { + return &Stack[T]{} +} + +// Push 向栈中添加元素 +func (s *Stack[T]) Push(element T) { + s.elements = append(s.elements, element) +} + +// Pop 从栈中移除并返回栈顶元素 +func (s *Stack[T]) Pop() (T, error) { + if len(s.elements) == 0 { + return reflect.Zero(reflect.TypeOf(new(T))).Interface().(T), errors.New("stack is empty") + } + element := s.elements[len(s.elements)-1] + s.elements = s.elements[:len(s.elements)-1] + return element.(T), nil +} + +// Peek 返回栈顶元素但不移除它 +func (s *Stack[T]) Peek() (T, error) { + if len(s.elements) == 0 { + return reflect.Zero(reflect.TypeOf(new(T))).Interface().(T), errors.New("stack is empty") + } + return s.elements[len(s.elements)-1].(T), nil +} + +// Size 返回栈中元素的数量 +func (s *Stack[T]) Size() int { + return len(s.elements) +} diff --git a/stack_test.go b/stack_test.go new file mode 100644 index 0000000..602818d --- /dev/null +++ b/stack_test.go @@ -0,0 +1,62 @@ +package kgo + +import "testing" + +func TestNewStack(t *testing.T) { + stack := NewStack[int]() + if stack != nil { + t.Log("stack is not nil") + } else { + t.Errorf("stack is nil") + } +} + +func TestStack_Push(t *testing.T) { + stack := NewStack[int]() + stack.Push(1) + stack.Push(2) + stack.Push(3) + if stack.Size() != 3 { + t.Errorf("stack size is not 3") + } else { + t.Log("stack size is 3") + } +} + +func TestStack_Pop(t *testing.T) { + stack := NewStack[int]() + stack.Push(1) + stack.Push(2) + stack.Push(3) + element, err := stack.Pop() + if err != nil { + t.Errorf("pop error: %s", err) + } else if element != 3 { + t.Errorf("pop element is not 3") + } +} + +func TestStack_Peek(t *testing.T) { + stack := NewStack[int]() + stack.Push(1) + stack.Push(2) + stack.Push(3) + element, err := stack.Peek() + if err != nil { + t.Errorf("peek error: %s", err) + } else if element != 3 { + t.Errorf("peek element is not 3") + } +} + +func TestStack_Size(t *testing.T) { + stack := NewStack[int]() + stack.Push(1) + stack.Push(2) + stack.Push(3) + if stack.Size() != 3 { + t.Errorf("stack size is not 3") + } else { + t.Log("stack size is 3") + } +}