On Fri, 3 Feb 2017 17:48:18 +0530
Rejoy Nair <rejo...@gmail.com> wrote:

> > > I am trying to pass a slice of data to a struct field . The field
> > > has a type of another struct. I get blank values in the output.
> > >
> > > Here is the code: https://play.golang.org/p/-YZ7UUI--D
> > >
> > > I 'd like to understand how to pass on the slice data to a struct
> > > field.
> >
> > It's not clear what do you want to achieve as the question mentions
> > slices, the code example deals with JSON unmarshaling and unrelated
> > value juggling.
> >
> > But is <https://play.golang.org/p/FxcA0vW9ZU> what you're after?
> > (See line 36 there.)
>
> Thanks!. thats what I was looking for.
> 
>  I had tried using the assignment Dt.P = Pr before the unmarshalling
> of the JSON to the variable pdata and it would not work.

I see.

Then, you absolutely positively need to read [1] and then [2] --
in this order.

As to your particular case, here's a bunch of related facts to ponder:

* json.Unmarshal() is told to unmarshal into a slice value.

* The slice it's passed is of length 0, which means that function has
  to perform several appends to that slice (two, in fact).

* Appending to a slice in Go _may update the slice value_ because it
  might result in relocation of the slice's backing array.

* In your case it works because json.Unmarshal() was passed not a slice
  value itself but a pointer to it (or, to put it differently, an
  address of the slice value kept in memory somewhere).

  Because of this, when json.Unmarshal() appends new elements to your
  slice it merely re-writes that slice's value each time -- via the
  pointer supplied to it.

* When json.Unmarshal() exits, the slice value whose address was passed
  to that function now represents the "final" state of the slice --
  filled with values.

  We then take it and assign it to a field of your custom struct value.
  Now the original slice value and that field represent the same
  slice (and refer to the same underlying array).

* If you do this "backwards" -- like you supposedly did by doing
  something like
  
    Pr = make([]Prdata, 0)
    Dt.P = Pr
    json.Unmarshal(..., &Pr)

  you ended up in a situation where json.Unmarshal() changed the value
  at Pr one or more times when it was appending new elements to that
  slice, and the slice value ended up being kept in Pr was different
  from the value kept in the field Dt.P (which supposedly was still
  nil).

* With all these things considered, it's better to rewrite your code
  to produce [4], or simplify it even further by relying on the fact
  appending to an uninitialized slice value (nil) allocates the
  underlying array for that slice as if you called make() for it;
  this way we can simply initialize only what matters in your custom
  struct value and let json.Unmarshal() handle slice allocation [5].

TL;DR

Doing

  a := make([]whatever)
  b := append(a, elem)

is allowed to produce b != a, and that's why appending to a slice
most of the time is done using

  a = append(a, elem)

In your case this effect was obscured by appending done in a function
you did not write but that was due to the fact you weren't familiar
with how slices work in Go, so please work through [1, 2].

1. https://blog.golang.org/slices
2. https://blog.golang.org/go-slices-usage-and-internals
3. https://play.golang.org/p/kaTjPTE2Hx
4. https://play.golang.org/p/Z6B8JUS9ON

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to