English | 简体中文
本库包含 Go 语言实现的范型容器和算法库,就像 C++ 中的 STL。
import "github.com/chen3feng/stl4go"
本库是在 Go 1.18 开始支持范型后,尝试借鉴 C++ STL 实现的一个通用容器和算法库。(我个人完全无法接受没有范型的语言,因此直到 go 1.18 才开始尝试用它)
本库代码质量高,遵循了业界最新的最佳实践。测试覆盖率接近 💯%,✅,设置了 CI、 gosec 检查,
评分。
众所周知,C++ 的 STL 包括容器、算法,并以迭代器关联两者。
受语言限制,在 Go 中无法也没有必要完全模仿 C++的接口,因此 C++ 用户可能会感觉似曾相识相识,有时候也会感觉更方便。
目前实现的容器有:
BuiltinSetVector。提供了中间插入删除、区间删除等功能,依然与 slice 兼容。map 只支持无序的的空白。这是目前全 GitHub 最快的跳表,参见 skiplist-survey的性能比较不同的容器支持的方法不同,下面是所有容器都支持的方法:
DList 和 SkipList 支持简单的迭代器。
l := stl4go.NewDListOf(Range(1, 10000)...)
sum := 0
for i := 0; i < b.N; i++ {
for it := l.Iterate(); it.IsNotEnd(); it.MoveToNext() {
sum += it.Value()
}
}
SkipList 还支持区间迭代:
l := stl4go.NewDListOf(Range(1, 1000)...)
it := sl.FindRange(120, 350)
对 it 迭代可以得到 120~349 之间的数。
更多时候,使用容器提供的 ForEach 和 ForEachIf 更方便,往往性能也更好一些:
func TestSkipList_ForEach(t *testing.T) {
sl := newSkipListN(100)
a := []int{}
sl.ForEach(func(k int, v int) {
a = append(a, k)
})
expectEq(t, len(a), 100)
expectTrue(t, IsSorted(a))
}
ForEachIf 用于遍历时候提前结束的场景:
go
func Test_DList_ForEachIf(t *testing.T) {
l := NewDListOf(1, 2, 3)
c := 0
l.ForEachIf(func(n int) bool {
c = n
return n != 2
})
expectEq(t, c, 2)
}
使用 ForEachMutable 或 ForEachMutable 可以在遍历时候修改元素的值:
func TestSkipList_ForEachMutable(t *testing.T) {
sl := newSkipListN(100)
sl.ForEachMutable(func(k int, v *int) {
*v = -*v
})
for i := 0; i < sl.Len(); i++ {
expectEq(t, *sl.Find(i), -i)
}
}
受语言功能限制,绝大部分算法只支持 Slice。算法的函数名以 If、Func 结尾的,表示可以传递一个自定义的比较函数。
int64 返回 []int32 的和)。float64 返回 []int 的和)。true 的元素的个数true 的值,返回其下标true参考 C++STL。
较多地参考了 C++ STL。T 表示模板。是的,Go 的范型不是模板,但是谁让 C++ 那么影响力,而 STL 又那么有名呢。
很多库的设计采用小的代码仓库或者一个仓库中拆分成多个子包。
比如
import (
"github.com/someone/awesomelib/skiplist"
"github.com/someone/awesomelib/binarysearch"
)
func main() {
sl := skiplist.New()
}
这种写法看似优雅,但是由于好的名字大家都喜欢,在使用中又不得不引入 import 重命名,而不同的使用者别名不一样,增加代码读写的心智负担。
我不太喜欢这种风格。
因此本库全部在 stl4go 包下,期望不会和别人的库重名。
参见 Issue。
以及更详细的文档。
点击查看生成的文档.
$ claude mcp add stl4go \
-- python -m otcore.mcp_server <graph>