Home  >  Article  >  Backend Development  >  Go - Idiomatic way of mapping one struct to another

Go - Idiomatic way of mapping one struct to another

WBOY
WBOYforward
2024-02-11 20:03:081054browse

Go - 将一个结构映射到另一个结构的惯用方式

php editor Strawberry will introduce to you a commonly used technique today - Go. This is an idiomatic way of mapping one structure to another. In programming, we often need to convert one data structure into another data structure to meet different needs. Go provides a concise and flexible way to achieve this goal. Whether processing database query results, API responses, or other data transformation scenarios, Go can help us easily complete structure mapping work. Next, let us learn about the specific usage of Go!

Question content

I am using a third-party go language library to query the user's ldap database. The library returns a resultuser slice of searchresult which I need to map to my own user structure. These two structures have different field names, I only need specific fields from resultuser. Is there a more idiomatic way in go to convert one struct to another.

I created a demo below (also linked on the go playground). Thank you in advance for any advice you may have for this go newbie!

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
}

I've seen struct field tags but not sure if there's a better way.

Workaround

I think what you have is pretty much the best solution, although I would move the mapping into a dedicated function, like:

func fromresultuser(r *resultuser) *user {
  return &user{
    id: r.uid,
    firstname: r.fname,
  }
}

Then mapresultstousers becomes:

func mapresultstousers(results searchresults) (users []*user) {
  for _, result := range results {
      users = append(users, fromresultuser(result))
  }
  return users
}

I've seen struct field tags but not sure if there's a better way.

You can combine something so that you can annotate your user structure like this:

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

But implementing this requires a much more complex approach than fromresultuser presented here, and requires familiarity with the reflect package. I think, as one of my colleagues likes to say, "the juice isn't worth the squeeze."

The above is the detailed content of Go - Idiomatic way of mapping one struct to another. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete