Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Copy one struct to another where structs have same members and different types

Tags:

go

I have two struct having the same members, I want to copy one struct to another, see the pseudo code below:

type Common struct {
    Gender int
    From   string
    To     string
}

type Foo struct {
    Id    string
    Name  string
    Extra Common
}

type Bar struct {
    Id    string
    Name  string
    Extra Common
}

Then I have foo of struct Foo, and bar of struct Bar, Is there any way to copy bar from foo?

like image 995
jsvisa Avatar asked May 16 '16 03:05

jsvisa


People also ask

How can you copy one structure to another structure of the same data type give an example?

struct { char string[32]; size_t len; } a, b; strcpy(a. string, "hello"); a. len = strlen(a. string);

How do you assign one structure to another structure in Golang?

A struct variable in Golang can be copied to another variable easily using the assignment statement(=). Any changes made to the second struct will not be reflected back to the first struct.

Can struct be copied?

In C/C++, we can assign a struct (or class in C++ only) variable to another variable of same type. When we assign a struct variable to another, all members of the variable are copied to the other struct variable.


3 Answers

Use a conversion to change the type. The following code uses a conversion to copy a value of type Foo to a value of type Bar:

foo := Foo{Id: "123", Name: "Joe"}
bar := Bar(foo)

playground example

The conversion only works when the underlying types are identical except for struct tags.

like image 168
Bayta Darell Avatar answered Oct 18 '22 03:10

Bayta Darell


https://github.com/jinzhu/copier (same author of gorm) is also quite a good one, I have nested structs and all I do is:

copier.Copy(&employees, &user)

works great

like image 16
mel3kings Avatar answered Oct 18 '22 03:10

mel3kings


If you would like to copy or clone to a different struct, I would suggest using deepcopier

It provides nice features like skipping, custom mapping, and forcing. below is an example from github:

Install:

go get -u github.com/ulule/deepcopier

Example:

package main

import (
    "fmt"

    "github.com/ulule/deepcopier"
)

// Model
type User struct {
    // Basic string field
    Name  string
    // Deepcopier supports https://golang.org/pkg/database/sql/driver/#Valuer
    Email sql.NullString
}

func (u *User) MethodThatTakesContext(ctx map[string]interface{}) string {
    // do whatever you want
    return "hello from this method"
}

// Resource
type UserResource struct {
    //copy from field "Name"
    DisplayName            string `deepcopier:"field:Name"`
    //this will be skipped in copy 
    SkipMe                 string `deepcopier:"skip"`
    //this should call method named MethodThatTakesContext 
    MethodThatTakesContext string `deepcopier:"context"`
    Email                  string `deepcopier:"force"`

}

func main() {
    user := &User{
        Name: "gilles",
        Email: sql.NullString{
            Valid: true,
            String: "[email protected]",
        },
    }

    resource := &UserResource{}

    deepcopier.Copy(user).To(resource)
    //copied from User's Name field
    fmt.Println(resource.DisplayName)//output: gilles
    fmt.Println(resource.Email) //output: [email protected]
    fmt.Println(resource.MethodThatTakesContext) //output: hello from this method
}

Also, some other way you could achieve this is by encoding the source object to JSON and then decode it back to the destination object.

like image 6
Muhammad Soliman Avatar answered Oct 18 '22 03:10

Muhammad Soliman