Go- Copy all common fields between structs

golang deep copy struct
convert one struct to another golang
golang clone struct pointer
golang deep copy slice
golang deep copy string
golang struct
golang protobuf deep copy
golang struct pointer field

I have a database that stores JSON, and a server that provides an external API to whereby through an HTTP post, values in this database can be changed. The database is used by different processes internally, and as such have a common naming scheme.

The keys the customer sees are different, but map 1:1 with the keys in the database (there are unexposed keys). For example:

This is in the database:

{ "bit_size": 8, "secret_key": false }

And this is presented to the client:

{ "num_bits": 8 }

The API can change with respect to field names, but the database always has consistent keys.

I have named the fields the same in the struct, with different flags to the json encoder:

type DB struct {
    NumBits int  `json:"bit_size"`
    Secret  bool `json:"secret_key"`
}
type User struct {
    NumBits int `json:"num_bits"`
}

I'm using encoding/json to do the Marshal/Unmarshal.

Is reflect the right tool for this? Is there an easier way since all of the keys are the same? I was thinking some kind of memcpy (if I kept the user fields in the same order).


Here's a solution using reflection. You have to further develop it if you need more complex structures with embedded struct fields and such.

http://play.golang.org/p/iTaDgsdSaI

package main

import (
    "encoding/json"
    "fmt"
    "reflect"
)

type M map[string]interface{} // just an alias

var Record = []byte(`{ "bit_size": 8, "secret_key": false }`)

type DB struct {
    NumBits int  `json:"bit_size"`
    Secret  bool `json:"secret_key"`
}

type User struct {
    NumBits int `json:"num_bits"`
}

func main() {
    d := new(DB)
    e := json.Unmarshal(Record, d)
    if e != nil {
        panic(e)
    }
    m := mapFields(d)
    fmt.Println("Mapped fields: ", m)
    u := new(User)
    o := applyMap(u, m)
    fmt.Println("Applied map: ", o)
    j, e := json.Marshal(o)
    if e != nil {
        panic(e)
    }
    fmt.Println("Output JSON: ", string(j))
}

func applyMap(u *User, m M) M {
    t := reflect.TypeOf(u).Elem()
    o := make(M)
    for i := 0; i < t.NumField(); i++ {
        f := t.FieldByIndex([]int{i})
        // skip unexported fields
        if f.PkgPath != "" {
            continue
        }
        if x, ok := m[f.Name]; ok {
            k := f.Tag.Get("json")
            o[k] = x
        }
    }
    return o
}

func mapFields(x *DB) M {
    o := make(M)
    v := reflect.ValueOf(x).Elem()
    t := v.Type()
    for i := 0; i < v.NumField(); i++ {
        f := t.FieldByIndex([]int{i})
        // skip unexported fields
        if f.PkgPath != "" {
            continue
        }
        o[f.Name] = v.FieldByIndex([]int{i}).Interface()
    }
    return o
}

Copy one struct to another where structs have same members and , go get -u github.com/ulule/deepcopier To(resource) //copied from User's Name field fmt. of gorm) is also quite a good one, I have nested structs and all I do is: type Common struct { Gender int From string To string } A struct variable in Go can be copied to another variable very easily using the assignment statement: package main import ( "fmt" ) type Dog struct { age int name string } func main() { roger := Dog{5, "Roger"} mydog := roger if roger == mydog { fmt.Println("Roger and mydog are equal structs") } } play mydog and roger are two separate variables, but comparing them property-by-property they are exactly the same.


buf := bytes.Buffer{}
err := gob.NewEncoder(&buf).Encode(&DbVar)
if err != nil {
    return err
}
u := User{}
err = gob.NewDecoder(&buf).Decode(&u)
if err != nil {
    return err
}

Go- Copy all common fields between structs - json - html, Go- Copy all common fields between structs - json. Println(dbj) // unmarshal from full db record to User struct var u User if err := json.Unmarshal([]byte(dbj), &u​);  Iterate over the fieldnames of B to copy them using dynamic field names: A = struct ('f1', 1, 'f2', 2, 'f3', 3); B = struct ('f1', 4, 'f2', 5); for fn = fieldnames (B)'. A. (fn {1}) = B. (fn {1});


Couldn't struct embedding be useful here?

package main

import (
    "fmt"
)

type DB struct {
    User
    Secret bool `json:"secret_key"`
}

type User struct {
    NumBits int `json:"num_bits"`
}

func main() {
    db := DB{User{10}, true}
    fmt.Printf("Hello, DB: %+v\n", db)
    fmt.Printf("Hello, DB.NumBits: %+v\n", db.NumBits)
    fmt.Printf("Hello, User: %+v\n", db.User)
}

http://play.golang.org/p/9s4bii3tQ2

jinzhu/copier: Copier for golang, copy value from struct to , Copier for golang, copy value from struct to struct and more field to method with same name; Copy from slice to slice; Copy from struct to slice View all issues  # structs ./main.go:12:13: unknown field 'model' in struct literal of type computer.Spec Since model field is unexported, it cannot be accessed from other packages. Structs Equality. Structs are value types and are comparable if each of their fields are comparable. Two struct variables are considered equal if their corresponding fields are equal.


Using struct tags, the following would sure be nice,

package main

import (
    "fmt"
    "log"

    "hacked/json"
)

var dbj = `{ "bit_size": 8, "secret_key": false }`

type User struct {
    NumBits int `json:"bit_size" api:"num_bits"`
}

func main() {
    fmt.Println(dbj)
    // unmarshal from full db record to User struct
    var u User
    if err := json.Unmarshal([]byte(dbj), &u); err != nil {
        log.Fatal(err)
    }
    // remarshal User struct using api field names 
    api, err := json.MarshalTag(u, "api")
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(string(api))
}

Adding MarshalTag requires just a small patch to encode.go:

106c106,112
<       e := &encodeState{}
---
>       return MarshalTag(v, "json")
> }
> 
> // MarshalTag is like Marshal but marshalls fields with
> // the specified tag key instead of the default "json".
> func MarshalTag(v interface{}, tag string) ([]byte, error) {
>       e := &encodeState{tagKey: tag}
201a208
>       tagKey       string
328c335
<               for _, ef := range encodeFields(v.Type()) {
---
>               for _, ef := range encodeFields(v.Type(), e.tagKey) {
509c516
< func encodeFields(t reflect.Type) []encodeField {
---
> func encodeFields(t reflect.Type, tagKey string) []encodeField {
540c547
<               tv := f.Tag.Get("json")
---
>               tv := f.Tag.Get(tagKey)

Making a copy of a struct in Go, A struct variable in Go can be copied to another variable very easily using the assignment package main import ( "fmt" ) type Dog struct { age int name string } func main() { roger It makes it really easy to deep copy a struct without explicitly managing each field. Here's an example, all we need is copier. The line *userb = *userb is saying "hey, the User struct stored at pointer userb should have the same data as the struct stored at pointer usera.. When you say user.username on the next line, you're doing the equivalent of C++'s (*userb).username.


Here's a solution without reflection, unsafe, or a function per struct. The example is a little convoluted, and maybe you wouldn't need to do it just like this, but the key is using a map[string]interface{} to get away from a struct with field tags. You might be able to use the idea in a similar solution.

package main

import (
    "encoding/json"
    "fmt"
    "log"
)

// example full database record
var dbj = `{ "bit_size": 8, "secret_key": false }`

// User type has only the fields going to the API
type User struct {
    // tag still specifies internal name, not API name
    NumBits int `json:"bit_size"`
}

// mapping from internal field names to API field names.
// (you could have more than one mapping, or even construct this
// at run time)
var ApiField = map[string]string{
    // internal: API
    "bit_size": "num_bits",
    // ...
}

func main() {
    fmt.Println(dbj)
    // select user fields from full db record by unmarshalling
    var u User
    if err := json.Unmarshal([]byte(dbj), &u); err != nil {
        log.Fatal(err)
    }
    // remarshal from User struct back to json
    exportable, err := json.Marshal(u)
    if err != nil {
        log.Fatal(err)
    }
    // unmarshal into a map this time, to shrug field tags.
    type jmap map[string]interface{}
    mInternal := jmap{}
    if err := json.Unmarshal(exportable, &mInternal); err != nil {
        log.Fatal(err)
    }
    // translate field names
    mExportable := jmap{}
    for internalField, v := range mInternal {
        mExportable[ApiField[internalField]] = v
    }
    // marshal final result with API field names
    if exportable, err = json.Marshal(mExportable); err != nil {
        log.Fatal(err)
    }
    fmt.Println(string(exportable))
}

Output:

{ "bit_size": 8, "secret_key": false } {"num_bits":8}

Edit: More explanation. As Tom notes in a comment, there's reflection going on behind the code. The goal here is to keep the code simple by using the available capabilities of the library. Package json currently offers two ways to work with data, struct tags and maps of [string]interface{}. The struct tags let you select fields, but force you to statically pick a single json field name. The maps let you pick field names at run time, but not which fields to Marshal. It would be nice if the json package let you do both at once, but it doesn't. The answer here just shows the two techniques and how they can be composed in a solution to the example problem in the OP.

Copy Struct Type in Go Programming Language, Copy Struct Type Using Value and Pointer Reference. r2 will be the same as Here, Structure is a common method between two interfaces Vehicle and Human. Copier for golang, copy value from struct to struct and more - jinzhu/copier


Go- Copy all common fields between structs - Golang, I have a database that stores JSON, and a server that provides an external API to whereby through an HTTP post, values in this database can  Go’s structs are typed collections of fields. They’re useful for grouping data together to form records.


Structs and Interfaces, This allocates memory for all the fields, sets each of them to their zero value and One thing to remember is that arguments are always copied in Go. In between the keyword func and the name of the function we've added a “receiver”. One, structs have fields, not elements. Two, we access the fields of a struct by names, not indices. And three, fields within the same struct can have different types. What's especially cool is that the field of struct can be another struct, and that ability of a struct to have another struct inside it makes structs very versatile.


copying structs with unexported fields, of the export rules, as pointed out recently by atom symbol. I think that putting an opaque unique id field from one structure to another. More mechanism is  Struct Fields. Struct fields are accessed using a dot. 3/27 > struct-fields.go Syntax Imports