Go -将一个结构体Map到另一个结构体的惯用方法

r1zhe5dt  于 2023-02-27  发布在  Go
关注(0)|答案(1)|浏览(126)

我正在使用third party Go lang library来查询LDAP用户数据库。库返回ResultUser的一个SearchResult切片,我需要将它Map到我自己的User结构体。这两个结构体有不同的字段名,我只需要ResultUser中的特定字段。在Go语言中有没有更惯用的方法来将一个结构体转换为另一个结构体?
我在下面创建了一个演示(链接也在Go Playground上)。提前感谢你给予这个围棋新手的任何建议!

package main

import "fmt"

type (
    User struct {
        id        int32
        firstName string
    }

    ResultUser struct {
        uid   int32
        fname string
    }
    SearchResults []ResultUser
)

func main() {
    results := getSearchResults()
    users := mapResultsToUsers(results) // <-- This is the problem
    fmt.Println("User struct:", users[0].id, users[0].firstName)
    fmt.Println("User struct:", users[1].id, users[1].firstName)
}

// Simulates a query to a data with a library
func getSearchResults() (results SearchResults) {
    return append(results, ResultUser{1, "John"}, ResultUser{2, "Jane"})
}

// Seems like a code smell to have to do this
// Is there a more idiomatic way to do this?
func mapResultsToUsers(results SearchResults) (users []User) {
    for _, result := range results {
        users = append(users, User{result.uid, result.fname})
    }
    return users
}

我见过结构域标记,但不确定是否有更好的方法。

ql3eal8s

ql3eal8s1#

我认为您所得到的几乎是最好的解决方案,尽管我会将Map移到一个专用函数中,例如:

func fromResultUser(r *ResultUser) *User {
  return &User{
    id: r.uid,
    firstName: r.fname,
  }
}

mapResultsToUsers变为:

func mapResultsToUsers(results SearchResults) (users []*User) {
  for _, result := range results {
      users = append(users, fromResultUser(result))
  }
  return users
}

我见过结构域标记,但不确定是否有更好的方法。
你可以把一些东西放在一起,这样你就可以像这样注解你的User结构体:

User struct {
    id        int32     `mappedFrom:"uid"`
    firstName string    `mappedFrom:"fname"`
}

但是实现它所需的方法实际上要比这里介绍的fromResultUser复杂得多,而且需要熟悉reflect包。我认为,正如我的一位同事喜欢说的那样,"果汁不值得压榨"。

相关问题