Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release v0.0.9 #251

Merged
merged 26 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
046debe
删除 changelog action
flycash Sep 25, 2023
c5bfbd4
queue, tree 暴露了红黑树和优先级队列(#218)
KelipuTe Sep 25, 2023
856d32a
sqlx: 解决 RawBytes 共享内存的问题 (#223)
flycash Oct 1, 2023
7c4e022
新增sqlx.NewNullXXX系列方法 (#227)
wureny Oct 9, 2023
afcc565
ekit: 修复 AnyValue 中当 Val 为 nil 的时候,生成错误信息引发 panic 的 BUG (#229)
flycash Oct 13, 2023
e2bf6f7
syncx: SegmentKeysLock 支持分key加锁 (#225)
WeiJiadong Oct 13, 2023
5f9ae28
SegmentKeysLock 引入 TryLock 和 TryRLock (#230)
flycash Oct 13, 2023
8216bf6
list: 增加 SkipList 实现 (#231)
AIJoe1995 Nov 6, 2023
45c4365
queue: 暴露超出容量错误 (#232)
flycash Nov 7, 2023
985e68e
syncx(feat): 添加具有最大申请次数限制的Pool (#233)
longyue0521 Dec 25, 2023
14dba09
添加 iox.JSONReader{ (#235)
flycash Dec 29, 2023
5a23504
httpx: Request 和 Response 初步设计 (#236)
flycash Jan 1, 2024
5056d18
增加Pair类型 (#237)
dxyinme Jan 8, 2024
eba89e1
新增mapi.Len()方法 (#239)
wureny Jan 9, 2024
4628cd1
重构: randx.RandCode 代码 (#241)
dxyinme Jan 14, 2024
194ef90
slice.Reverse, slice.Add, arrayList.Add 修改 (#242)
dxyinme Jan 22, 2024
8c729df
AnyValue: 增加 JSONScan 方法 (#243)
flycash Feb 7, 2024
43c0955
重命名枚举值
flycash Feb 7, 2024
ab2ac5b
httptestx: 支持 JSONRecorder
flycash Feb 11, 2024
d8a351a
httptestx: 支持 JSONRecorder (#244)
flycash Feb 11, 2024
b681071
Merge branch 'main' of github.com:ecodeclub/ekit into dev
flycash Feb 11, 2024
6e35f58
Merge branch 'dev' of github.com:ecodeclub/ekit into dev
flycash Feb 11, 2024
ea42c17
Merge pull request #245 from flycash/dev
flycash Feb 11, 2024
20b3765
httpx: 添加 AddHeader 方法 (#246)
flycash Mar 4, 2024
e1ba7d0
fix: 修复文档URL链接 (#247)
longyue0521 Mar 5, 2024
871f651
slice: 增加函数ToMap, ToMapV (#249)
dxyinme Mar 31, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
# 开发中
- [syncx: 支持分key加锁](https://github.com/ecodeclub/ekit/pull/224)
- [syncx: 添加具有最大申请次数限制的LimitPool](https://github.com/ecodeclub/ekit/pull/233)
- [tuple: 增加Pair的实现](https://github.com/ecodeclub/ekit/pull/237)
- [randx: 重构randx.RandCode的代码,增加对特殊字符的支持](https://github.com/ecodeclub/ekit/pull/241)

# v0.0.8
- [atomicx: 泛型封装 atomic.Value](https://github.com/gotomicro/ekit/pull/101)
Expand Down Expand Up @@ -35,7 +39,9 @@
- [sqlx: Scanner 添加 NextResultSet 方法](https://github.com/ecodeclub/ekit/pull/212)
- [ekit: AnyValue 支持As[Type]类型 String 转换](https://github.com/ecodeclub/ekit/pull/213)
- [stringx: unsafe 转换 string 和 []byte](https://github.com/ecodeclub/ekit/pull/215)
- [stringx: 添加 Benchmark](https://github.com/ecodeclub/ekit/pull/216)
- [stringx: 添加 Benchmark](https://github.com/ecodeclub/ekit/pull/216)
- [tree: 把 internal 里的红黑树做一个简单封装](https://github.com/ecodeclub/ekit/pull/218)
- [queue: 把 internal 里的优先级队列做一个简单封装](https://github.com/ecodeclub/ekit/pull/218)

# v0.0.7
- [slice: FilterDelete](https://github.com/ecodeclub/ekit/pull/152)
Expand Down
46 changes: 0 additions & 46 deletions .github/workflows/changelog.yml

This file was deleted.

File renamed without changes.
File renamed without changes.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ ut:

.PHONY: setup
setup:
@sh ./script/setup.sh
@sh ./.script/setup.sh

.PHONY: fmt
fmt:
@sh ./script/goimports.sh
@sh ./.script/goimports.sh

.PHONY: lint
lint:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# ekit
泛型工具库。

- [文档](https://ekit.gocn.vip/ekit/develop/guide/)
- [文档](https://doc.meoying.com/)

## 交流

Expand Down
15 changes: 8 additions & 7 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@ go 1.20
require (
github.com/DATA-DOG/go-sqlmock v1.5.0
github.com/mattn/go-sqlite3 v1.14.15
github.com/stretchr/testify v1.8.1
golang.org/x/sync v0.1.0
github.com/stretchr/testify v1.8.4
golang.org/x/exp v0.0.0-20231006140011-7918f672742d
golang.org/x/sync v0.4.0
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
38 changes: 19 additions & 19 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
4 changes: 2 additions & 2 deletions internal/errs/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ func NewErrIndexOutOfRange(length int, index int) error {
}

// NewErrInvalidType 创建一个代表类型转换失败的错误
func NewErrInvalidType(want, got string) error {
return fmt.Errorf("ekit: 类型转换失败,want:%s, got:%s", want, got)
func NewErrInvalidType(want string, got any) error {
return fmt.Errorf("ekit: 类型转换失败,预期类型:%s, 实际值:%#v", want, got)
}

func NewErrInvalidIntervalValue(interval time.Duration) error {
Expand Down
174 changes: 174 additions & 0 deletions internal/list/skip_list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
// Copyright 2021 ecodeclub
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package list

import (
"errors"

"github.com/ecodeclub/ekit"
"github.com/ecodeclub/ekit/internal/errs"
"golang.org/x/exp/rand"
)

// 跳表 skip list

const (
FactorP = float32(0.25) // level i 上的结点 有FactorP的比例出现在level i + 1上
MaxLevel = 32
)

// FactorP = 0.25, MaxLevel = 32 列表可包含 2^64 个元素

type skipListNode[T any] struct {
Val T
Forward []*skipListNode[T]
}

type SkipList[T any] struct {
header *skipListNode[T]
level int // SkipList为空时, level为1
compare ekit.Comparator[T]
size int
}

func newSkipListNode[T any](Val T, level int) *skipListNode[T] {
return &skipListNode[T]{Val, make([]*skipListNode[T], level)}
}

func (sl *SkipList[T]) AsSlice() []T {
curr := sl.header
slice := make([]T, 0, sl.size)
for curr.Forward[0] != nil {
slice = append(slice, curr.Forward[0].Val)
curr = curr.Forward[0]
}
return slice
}

func NewSkipListFromSlice[T any](slice []T, compare ekit.Comparator[T]) *SkipList[T] {
sl := NewSkipList[T](compare)
for _, n := range slice {
sl.Insert(n)
}
return sl
}

func NewSkipList[T any](compare ekit.Comparator[T]) *SkipList[T] {
return &SkipList[T]{
header: &skipListNode[T]{
Forward: make([]*skipListNode[T], MaxLevel),
},
level: 1,
compare: compare,
}
}

// levels的生成和跳表中元素个数无关
func (sl *SkipList[T]) randomLevel() int {
level := 1
p := FactorP
for (rand.Int31() & 0xFFFF) < int32(p*0xFFFF) {
level++
}
if level < MaxLevel {
return level
}
return MaxLevel

}

func (sl *SkipList[T]) Search(target T) bool {
curr, _ := sl.traverse(target, sl.level)
curr = curr.Forward[0] // 第1层 包含所有元素
return curr != nil && sl.compare(curr.Val, target) == 0
}

func (sl *SkipList[T]) traverse(Val T, level int) (*skipListNode[T], []*skipListNode[T]) {
update := make([]*skipListNode[T], MaxLevel) // update[i] 包含位于level i 的插入/删除位置左侧的指针
curr := sl.header
for i := level - 1; i >= 0; i-- {
for curr.Forward[i] != nil && sl.compare(curr.Forward[i].Val, Val) < 0 {
curr = curr.Forward[i]
}
update[i] = curr
}
return curr, update
}

func (sl *SkipList[T]) Insert(Val T) {
_, update := sl.traverse(Val, sl.level)
level := sl.randomLevel()
if level > sl.level {
for i := sl.level; i < level; i++ {
update[i] = sl.header
}
sl.level = level
}

// 插入新节点
newNode := newSkipListNode[T](Val, level)
for i := 0; i < level; i++ {
newNode.Forward[i] = update[i].Forward[i]
update[i].Forward[i] = newNode
}

sl.size += 1

}

func (sl *SkipList[T]) Len() int {
return sl.size
}

func (sl *SkipList[T]) DeleteElement(target T) bool {
curr, update := sl.traverse(target, sl.level)
node := curr.Forward[0]
if node == nil || sl.compare(node.Val, target) != 0 {
return true
}
// 删除target结点
for i := 0; i < sl.level && update[i].Forward[i] == node; i++ {
update[i].Forward[i] = node.Forward[i]
}

// 更新层级
for sl.level > 1 && sl.header.Forward[sl.level-1] == nil {
sl.level--
}
sl.size -= 1
return true
}

func (sl *SkipList[T]) Peek() (T, error) {
curr := sl.header
curr = curr.Forward[0]
var zero T
if curr == nil {
return zero, errors.New("跳表为空")
}
return curr.Val, nil
}

func (sl *SkipList[T]) Get(index int) (T, error) {
var zero T
if index < 0 || index >= sl.size {
return zero, errs.NewErrIndexOutOfRange(sl.size, index)
}
curr := sl.header
for i := 0; i <= index; i++ {
curr = curr.Forward[0]
}
return curr.Val, nil
}
Loading
Loading