V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
jdlau
V2EX  ›  Go 编程语言

用一个数据处理库来泛型尝鲜

  •  
  •   jdlau · 2022-04-24 21:09:47 +08:00 · 1362 次点击
    这是一个创建于 733 天前的主题,其中的信息可能已经有所发展或是发生改变。

    这是一个用 Go 实现的数据处理库,升级之前用 interface{}表示参数类型,阅读起来还是容易模糊。现在泛型出了之后,就把它升级一下:

    原来:

    // extract column from table
    // * First Argument:table
    // * Second Argument:column name
    result := query.Column(users, "UserID")
    userIDs := result.([]int)
    
    // generate a map from table,key is column value and value is it's row
    // * First Argument:table
    // * Second Argument:column name
    result = query.ColumnMap(users, "UserID")
    userMap := result.(map[int]User)
    
    // select data from table
    // * First Argument:table
    // * Second Argument:select rule
    result = query.Select(users, func(a User) Sex {
        if len(a.Name) >= 3 && a.Name[0:3] == "Man" {
            return Sex{IsMale: true}
        }
        return Sex{IsMale: false}
    })
    sel := result.([]Sex)
    
    // filter data from table
    // * First Argument:table
    // * Second Argument:filter rule
    result = query.Where(users, func(a User) bool {
        if len(a.Name) >= 3 && a.Name[0:3] == "Man" {
            return true
        }
        return false
    })
    where := result.([]User)
    
    // group data from table
    // * First Argument: left table
    // * Second Argument: group column name
    // * Third Argument: group rule
    result = query.Group(users, "UserID", func(users []User) Department {
        return Department{
            Employees: users,
        }
    })
    group := result.([]Department)
    
    // join data from two table ,support LeftJoin,RightJoin,InnerJoin 和 OuterJoin
    // * First Argument: left table
    // * Second Argument: right table
    // * Third Argument: join condition
    // * Forth Argument: join rule
    result = query.LeftJoin(admins, users, "AdminID = UserID", func(admin Admin, user User) AdminUser {
        return AdminUser{
            AdminID:    admin.AdminID,
            Level:      admin.Level,
            Name:       user.Name,
            CreateTime: user.CreateTime,
        }
    })
    join := result.([]AdminUser)
    

    现在

    // extract column from table
    // * First Argument:table
    // * Second Argument:column name
    userIDs := query.Column[User, int](users, "UserID") // []int
    
    // generate a map from table,key is column value and value is it's row
    // * First Argument:table
    // * Second Argument:column name
    userMap = query.ColumnMap[User, int, map[int]User](users, "UserID") // map[int]User
    // or
    usersMap = query.ColumnMap[User, int, map[int][]User](users, "[]UserID") // map[int][]User
    
    // select data from table
    // * First Argument:table
    // * Second Argument:select rule
    sel = query.Select(users, func(a User) Sex {
        if len(a.Name) >= 3 && a.Name[0:3] == "Man" {
            return Sex{IsMale: true}
        }
        return Sex{IsMale: false}
    }) // []Sex
    
    // filter data from table
    // * First Argument:table
    // * Second Argument:filter rule
    where = query.Where(users, func(a User) bool {
        if len(a.Name) >= 3 && a.Name[0:3] == "Man" {
            return true
        }
        return false
    }) // []User
    
    // group data from table
    // * First Argument: left table
    // * Second Argument: group column name
    // * Third Argument: group rule
    group = query.Group[User, Department, []Department](users, "UserID", func(users []User) Department {
        return Department{
            Employees: users,
        }
    }) // []Department
    // or
    group = query.Group[User, []Department, *[]Department](users, "UserID", func(users []User) []Department {
        return []Department{
            Employees: users,
        }
    }) // *[]Department
    
    // join data from two table ,support LeftJoin,RightJoin,InnerJoin 和 OuterJoin
    // * First Argument: left table
    // * Second Argument: right table
    // * Third Argument: join condition
    // * Forth Argument: join rule
    join = query.LeftJoin(admins, users, "AdminID = UserID", func(admin Admin, user User) AdminUser {
        return AdminUser{
            AdminID:    admin.AdminID,
            Level:      admin.Level,
            Name:       user.Name,
            CreateTime: user.CreateTime,
        }
    }) // []AdminUser
    

    减少了断言,还是挺好的。

    一点问题

    目前的 Go 泛型不支持类型参数内嵌,所以在 Group 函数里使用了指针。

    // 这样是不行的
    func Group[T, E any, R E | []E](data []T, groupType string, groupFunctor func([]T) E) R
    // 只好写成这样
    func Group[T, E any, R *E | []E](data []T, groupType string, groupFunctor func([]T) E) R 
    
    2 条回复    2022-04-25 17:01:22 +08:00
    seakingii
        1
    seakingii  
       2022-04-25 16:43:34 +08:00
    GO 的泛型语法真奇葩
    jdlau
        2
    jdlau  
    OP
       2022-04-25 17:01:22 +08:00
    @seakingii 各花入各眼。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2891 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 14:36 · PVG 22:36 · LAX 07:36 · JFK 10:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.