Golang中使用结构体实现泛型
Golang中使用结构体实现泛型
以下是我在我的数据库工具 Bobb 中使用 Go 泛型的示例。问题案例是以泛型方式将数据库记录结构体类型转换为字节切片 []byte,然后再转换回原始结构体类型。处理单个记录很简单,但记录切片和映射则是更复杂的问题。我可能忽略了一些看似简单但一直没找到的解决方案。
1 回复
更多关于Golang中使用结构体实现泛型的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go语言中,结构体本身不支持泛型,但可以通过泛型函数或方法实现类似功能。根据你的需求,处理数据库记录结构体类型与字节切片之间的转换,特别是针对切片和映射,可以使用泛型函数结合encoding/json或gob等序列化方式实现。以下是一个使用json.Marshal和json.Unmarshal的泛型实现示例,适用于单个记录、切片和映射。
package main
import (
"encoding/json"
"fmt"
)
// 泛型函数:将任意类型转换为字节切片
func ToBytes[T any](data T) ([]byte, error) {
return json.Marshal(data)
}
// 泛型函数:将字节切片转换回原始类型
func FromBytes[T any](b []byte) (T, error) {
var data T
err := json.Unmarshal(b, &data)
return data, err
}
// 示例结构体
type Record struct {
ID int `json:"id"`
Name string `json:"name"`
}
func main() {
// 单个记录转换
record := Record{ID: 1, Name: "Test"}
bytes, err := ToBytes(record)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("Bytes:", bytes)
var decodedRecord Record
decodedRecord, err = FromBytes[Record](bytes)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("Decoded Record:", decodedRecord)
// 切片转换
records := []Record{{ID: 1, Name: "A"}, {ID: 2, Name: "B"}}
sliceBytes, err := ToBytes(records)
if err != nil {
fmt.Println("Error:", err)
return
}
var decodedSlice []Record
decodedSlice, err = FromBytes[[]Record](sliceBytes)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("Decoded Slice:", decodedSlice)
// 映射转换
recordMap := map[int]Record{1: {ID: 1, Name: "MapTest"}}
mapBytes, err := ToBytes(recordMap)
if err != nil {
fmt.Println("Error:", err)
return
}
var decodedMap map[int]Record
decodedMap, err = FromBytes[map[int]Record](mapBytes)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("Decoded Map:", decodedMap)
}
这个示例中,ToBytes 和 FromBytes 是泛型函数,可以处理任意类型 T,包括结构体、切片和映射。通过 json.Marshal 和 json.Unmarshal 实现序列化和反序列化。注意,这种方法依赖于JSON标签,如果结构体字段未导出或缺少标签,可能会导致错误。对于更复杂的场景,可以考虑使用 gob 或其他二进制序列化库,但原理类似。

