golang实现泛型元组数据结构的插件库go-tuple的使用
Golang实现泛型元组数据结构的插件库go-tuple的使用
go-tuple是一个为Go 1.18+设计的泛型元组实现库,允许你存储1到9个不同类型的值而不需要自定义结构体。
基本用法
// 创建一个包含2个元素的元组
tup := tuple.New2(5, "hi!")
fmt.Println(tup.V1) // 输出: 5
fmt.Println(tup.V2) // 输出: "hi!"
// 创建一个更长的元组
longerTuple := tuple.New5("this", "is", "one", "long", "tuple")
元组在不同场景中的应用
元组可以用作切片或数组项、映射键或值,以及通道负载:
// 映射中保存元组
tupInMap := make(map[tuple.T2[string, string]]Person)
tupInMap[tuple.New2("John", "Doe")] = Person{
FirstName: "John",
LastName: "Doe",
// ...
}
// 通道中保存元组
tupInChan := make(chan tuple.T2[string, error])
go func() {
defer close(tupInChan)
tupInChan <- tuple.New2(os.Getwd())
}()
fmt.Print(<-tupInChan)
从函数调用创建元组
func vals() (int, string) {
return 5, "hi!"
}
func main() {
tup := tuple.New2(vals())
fmt.Println(tup.V1)
fmt.Println(tup.V2)
}
将元组作为函数参数传递
func main() {
tup := tuple.New2(5, "hi!")
printValues(tup.Values())
}
func printValues(a int, b string) {
fmt.Println(a)
fmt.Println(b)
}
访问元组值
tup := tuple.New2(5, "hi!")
a, b := tup.Values()
JSON编组
元组会被编组和解组为JSON数组:
type User struct {
Name string `json:"name"`
Age int `json:"age,omitempty"`
}
type MyJSON struct {
Users []tuple.T2[string, User] `json:"users"`
}
func main() {
data := MyJSON{
Users: []tuple.T2[string, User]{
tuple.New2("foo", User{Name: "foo", Age: 42}),
tuple.New2("bar", User{Name: "bar", Age: 21}),
tuple.New2("baz", User{Name: "baz"}),
},
}
marshalled, _ := json.Marshal(data)
fmt.Printf("%s\n", string(marshalled))
// 输出: {"users":[["foo",{"name":"foo","age":42}],["bar",{"name":"bar","age":21}],["baz",{"name":"baz"}]]}
}
比较
元组从第一个元素到最后一个元素依次比较:
fmt.Println(tuple.Equal3(tuple.New3(1, 2, 3), tuple.New3(3, 3, 3))) // false
fmt.Println(tuple.LessThan3(tuple.New3(1, 2, 3), tuple.New3(3, 2, 1))) // true
tups := []tuple.T3{
tuple.New3("foo", 2, -23),
tuple.New3("foo", 72, 15),
tuple.New3("bar", -4, 43),
}
sort.Slice(tups, func (i, j int) {
return tuple.LessThan3(tups[i], tups[j])
})
fmt.Println(tups) // [["bar", -4, 43], ["foo", 2, -23], ["foo", 72, 15]]
比较结果
// Compare*函数返回OrderedComparisonResult值
result := tuple.Compare3(tuple.New3(1, 2, 3), tuple.New3(3, 2, 1))
// OrderedComparisonResult值是包装的整数
fmt.Println(result) // -1
// OrderedComparisonResult提供了多种方法来以更可读的方式查看结果
fmt.Println(result.GreaterThan()) // false
自定义比较
type person struct {
name string
age int
}
func (p person) CompareTo(guest person) tuple.OrderedComparisonResult {
if p.name < guest.name {
return -1
}
if p.name > guest.name {
return 1
}
return 0
}
func main() {
tup1 := tuple.New2(person{name: "foo", age: 20}, person{name: "bar", age: 24})
tup2 := tuple.New2(person{name: "bar", age: 20}, person{name: "baz", age: 24})
fmt.Println(tuple.LessThan2C(tup1, tup2)) // true
}
格式化
元组实现了Stringer
和GoStringer
接口:
fmt.Printf("%s\n", tuple.New2("hello", "world"))
// 输出:
// ["hello" "world"]
fmt.Printf("%#v\n", tuple.New2("hello", "world"))
// 输出:
// tuple.T2[string, string]{V1: "hello", V2: "world"}
注意事项
- 为了比较元组,所有元组元素必须匹配
constraints.Ordered
- 元组代码和测试代码是由
scripts/gen/main.go
脚本生成的 - 生成是通过使用Go的
text/template
引擎读取tuple.tpl
和tuple_test.tpl
来工作的
更多关于golang实现泛型元组数据结构的插件库go-tuple的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang实现泛型元组数据结构的插件库go-tuple的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
go-tuple: Golang泛型元组数据结构库使用指南
go-tuple 是一个为Golang设计的泛型元组(Tuple)实现库,它利用Go 1.18引入的泛型特性,提供了类型安全的元组数据结构。
安装
go get github.com/barweiss/go-tuple
基本用法
创建元组
package main
import (
"fmt"
"github.com/barweiss/go-tuple"
)
func main() {
// 创建二元组
t2 := tuple.New2("hello", 42)
fmt.Printf("二元组: %v\n", t2)
// 创建三元组
t3 := tuple.New3("go", 1.18, true)
fmt.Printf("三元组: %v\n", t3)
// 创建四元组
t4 := tuple.New4("tuple", 4, 3.14, 'π')
fmt.Printf("四元组: %v\n", t4)
// 最多支持九元组
t9 := tuple.New9(1, 2, 3, 4, 5, 6, 7, 8, 9)
fmt.Printf("九元组: %v\n", t9)
}
访问元组元素
// 访问二元组元素
name, age := t2.V1, t2.V2
fmt.Printf("Name: %s, Age: %d\n", name, age)
// 访问三元组元素
lang, version, isCool := t3.V1, t3.V2, t3.V3
fmt.Printf("Language: %s, Version: %.2f, IsCool: %t\n", lang, version, isCool)
// 访问四元组元素
word, num, pi, symbol := t4.V1, t4.V2, t4.V3, t4.V4
fmt.Printf("Word: %s, Num: %d, Pi: %.2f, Symbol: %c\n", word, num, pi, symbol)
元组比较
// 创建两个相同类型的元组进行比较
t2a := tuple.New2("a", 1)
t2b := tuple.New2("a", 1)
t2c := tuple.New2("b", 2)
fmt.Println("t2a == t2b:", t2a.Equal(t2b)) // true
fmt.Println("t2a == t2c:", t2a.Equal(t2c)) // false
元组作为函数返回值
func getUserInfo(id int) tuple.T2[string, int] {
// 模拟数据库查询
name := fmt.Sprintf("User%d", id)
age := 20 + id%10
return tuple.New2(name, age)
}
func main() {
user := getUserInfo(42)
fmt.Printf("User: %s, Age: %d\n", user.V1, user.V2)
}
元组作为Map的键
func main() {
// 使用元组作为map的键
userScores := make(map[tuple.T2[string, int]]int)
userScores[tuple.New2("Alice", 25)] = 95
userScores[tuple.New2("Bob", 30)] = 88
score, exists := userScores[tuple.New2("Alice", 25)]
if exists {
fmt.Println("Alice's score:", score)
}
}
高级用法
元组解构
func processUser(info tuple.T2[string, int]) {
name, age := info.V1, info.V2
fmt.Printf("Processing %s, age %d\n", name, age)
}
func main() {
user := tuple.New2("Charlie", 35)
processUser(user)
}
元组切片
func main() {
users := []tuple.T2[string, int]{
tuple.New2("Alice", 25),
tuple.New2("Bob", 30),
tuple.New2("Charlie", 35),
}
for _, user := range users {
fmt.Printf("%s is %d years old\n", user.V1, user.V2)
}
}
自定义元组类型
type UserInfo tuple.T2[string, int]
func (u UserInfo) String() string {
return fmt.Sprintf("%s (%d)", u.V1, u.V2)
}
func main() {
user := UserInfo(tuple.New2("Dave", 40))
fmt.Println(user) // 输出: Dave (40)
}
性能考虑
go-tuple 的实现非常轻量级,基本上只是对多个值的简单包装。与使用结构体相比,性能开销可以忽略不计。
限制
- 元组元素数量最多支持9个(T1到T9)
- 由于Go泛型的限制,元组元素必须是可比较的类型才能使用Equal方法
替代方案
如果你需要更灵活的元组实现,也可以考虑:
- 使用匿名结构体
- 使用多个返回值
- 其他类似的库如github.com/samber/go-tuple
go-tuple 的优势在于提供了标准化的元组实现和便利的方法,适合需要在代码中频繁使用元组的场景。
希望这个指南能帮助你理解和使用go-tuple库!