3

I'm writing a PATCH API and it is not necessary to send all the fields in request. I'd like to update only the new fields. I'm using Datastore, and I think, I need to send entire struct that contains the final value I intend to save, as it replaces all the values. I retrieve existing values from DB in one struct and I have the request in another struct.

type product struct {
    TITLE    string `json:"title"`
    SUMMARY  string `json:"summary"`
    IMAGEURL string `json:"imageUrl"`
    CATEGORY string `json:"category"`
    TYPE     int    `json:"type"`
}

var dbVal product // Holds the existing DB values
var formVal product // Holds the values received from web form (api request)

formVal need not have all the values. It is empty if the field is not sent in the request.

I want the dbVal struct to be updated with the values in formVal ONLY if formVal field is not empty (!= "" for string or != 0 for int).

PS: I searched for more than a day and tried different examples and tried to use reflect from some of the other answers, but not able to find out how to assign values to another struct. If this is already answered, I'm sorry for reposting this - please share the link.

7
  • 1
    You gave the answer to your question already: Checking for "!= "" for string or != 0 for int". Do this for all fields and use some if. No rocket science needed here. Go is a "no magic"-language where you accomplish task by programming and not by magic. But maybe I misunderstood the question? Commented Dec 7, 2017 at 6:31
  • 1
    That's not scalable. I have 14 struct fields! I just gave an example with few of my entire struct. My struct also has bool, int64 and array type data. Commented Dec 7, 2017 at 6:41
  • I'm just looking for a lead to start working on the logic. I know to range a struct, find each field type and get value as interface. The only problem I face is assigning the value to another struct field. Commented Dec 7, 2017 at 6:48
  • Then either write 14 if's (works well for bools as for uint64) and code for arrays. What's wrong with writing code? And if this does not "scale" write code which generalizes this by traversing your struct with package reflect (which is a lot of work and scales even less and is slower). If you run into addressability and thus assignability issues: Traverse three structs in lockstep, building up the third from the first two. This is really more complicated. Google search for "golang merge structs" yields several hits, one even is golanglibs.com/top?q=merge+structs which should help. Commented Dec 7, 2017 at 7:20
  • 2
    See a technique presented here: "Merge" fields two structs of same type. Commented Dec 7, 2017 at 9:09

2 Answers 2

1

I would propose to slightly change the struct to use pointers:

type product struct {
    TITLE    *string `json:"title"`
    SUMMARY  *string `json:"summary"`
    IMAGEURL *string `json:"imageUrl"`
    CATEGORY *string `json:"category"`
    TYPE     *int    `json:"type"`
}

And then you can iterate through the patch entity using reflect and replace non-nil values. Check example in Go Playground.

Sign up to request clarification or add additional context in comments.

Comments

0

Consider writing a utility method on the product type that checks if it is empty and use that to determine whether to update the database values, e.g.:

func (p product) isEmpty() bool {
  return (p.TITLE == "") && (p.SUMMARY == "") && (p.IMAGEURL == "") && (p.CATEGORY == "") && (p.TYPE == 0)
}
// ...

if !formVal.isEmpty() {
  // Update database values...
}

2 Comments

Let's say dbval.TITLE = "Prod1", dbval.SUMMARY = "Desc". formVal.TITLE = "" and formVal.SUMMARY = "New Desc" I want to update only SUMMARY and ignore TITLE property update. Final Result I want is: dbval.TITLE = "Prod1", dbval.SUMMARY = "New Desc".
@deepakssn yes, then write a function to copy only the fields that are present. Also, please update your question with these details

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.