FAQ
Hi,

I've got kind of a weird syntax question and I'm not sure exactly what's
going on here. I might just be doing something oddly too. I'm not sure.

Given this code:

https://play.golang.org/p/Zqo5VK1Xz8

I'm building a B+ tree and am messing around with putting the keys into a
Keys slice. A Key is an interface, so a Keys type is a slice of Key
interfaces. I have an InsertAt method that is trying to put data into a
Keys slice based on a specific position. E.g InsertAt(5, key) would put
"key" at keys[5] after moving all elements at position [5:] right along the
array by 1 position, so the current position 6 becomes 7, then 5 becomes 6,
then I put my element in at 5. If I use the signature "func (ks Keys)
InsertAt(p int, k Key)" it seems like a copy of ks (which a Keys type,
which is actually []Key) is created and passed to InsertAt, and any
modifications that happen to it don't affect the original as one would
expect with a copy.

However, if I pass it as a reference with "func (ks *Keys) InsertAtRef(p
int, k Key)" it does operate on the original as expected with a reference.

What's confusing me here is I thought slices were already pointers from
https://golang.org/doc/effective_go.html#slices - does "masking" the fact
it's a slice by assigning it through a type definition change some
fundamental property of passing references vs passing values?

What's even weirder is it seems like it's somehow "dropping" the new length:

https://play.golang.org/p/a6CXm6W1AA - added a bunch more instrumentation
around the "InsertAt" method which has some odd output:

InsertAt without explicit reference to slice
  // Initial state
0x10444400 [0x10438390 0x104383a0 0x104383b0] len 3 cap 15

// Added a nil to the end to extend len, then do the copy
[p:] 0x10444410 [0x104383b0 <nil>] len 2 cap 13
[p+1:] 0x10444418 [<nil>] len 1 cap 12

// Copied elements right by one. Note len is now 4 as expected.
0x10444400 [0x10438390 0x104383a0 0x104383b0 0x104383b0] len 4 cap 15

// Set ks[p] to nil to mark where the new element is going to be inserted
0x10444400 [0x10438390 0x104383a0 <nil> 0x104383b0] len 4 cap 15

// What the changed area looks like after the copy and nil set
[p:] 0x10444410 [<nil> 0x104383b0] len 2 cap 13
[p+1:] 0x10444418 [0x104383b0] len 1 cap 12

// Inserted the new element at position ks[2]
0x10444400 [0x10438390 0x104383a0 0x104383c0 0x104383b0] len 4 cap 15

// Look at the state of ks one final time before leaving the method. Where did the last element go and why did cap drop back to 3?
0x10444400 [0x10438390 0x104383a0 0x104383c0] len 3 cap 15

Any insight you have would be appreciated.

--
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+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Search Discussions

  • Ian Lance Taylor at Sep 25, 2015 at 7:30 pm

    On Fri, Sep 25, 2015 at 10:59 AM, wrote:
    I've got kind of a weird syntax question and I'm not sure exactly what's
    going on here. I might just be doing something oddly too. I'm not sure.

    Given this code:

    https://play.golang.org/p/Zqo5VK1Xz8

    I'm building a B+ tree and am messing around with putting the keys into a
    Keys slice. A Key is an interface, so a Keys type is a slice of Key
    interfaces. I have an InsertAt method that is trying to put data into a Keys
    slice based on a specific position. E.g InsertAt(5, key) would put "key" at
    keys[5] after moving all elements at position [5:] right along the array by
    1 position, so the current position 6 becomes 7, then 5 becomes 6, then I
    put my element in at 5. If I use the signature "func (ks Keys) InsertAt(p
    int, k Key)" it seems like a copy of ks (which a Keys type, which is
    actually []Key) is created and passed to InsertAt, and any modifications
    that happen to it don't affect the original as one would expect with a copy.

    However, if I pass it as a reference with "func (ks *Keys) InsertAtRef(p
    int, k Key)" it does operate on the original as expected with a reference.
    Yes, that is how it works.
    What's confusing me here is I thought slices were already pointers from
    https://golang.org/doc/effective_go.html#slices - does "masking" the fact
    it's a slice by assigning it through a type definition change some
    fundamental property of passing references vs passing values?
    Slices are not fully reference types. They contain a reference to the
    underlying array, but the length and capacity are values.

    I think it should be clear if you read https://blog.golang.org/slices .

    Ian

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Tiru Srikantha at Sep 25, 2015 at 7:47 pm
    That's what I was missing, thanks. The header was being copied when passed
    by value, which explains why I was seeing the value change but the length
    not.
    On Friday, September 25, 2015 at 12:31:02 PM UTC-7, Ian Lance Taylor wrote:

    On Fri, Sep 25, 2015 at 10:59 AM, <tiru.sr...@gmail.com <javascript:>>
    wrote:
    I've got kind of a weird syntax question and I'm not sure exactly what's
    going on here. I might just be doing something oddly too. I'm not sure.

    Given this code:

    https://play.golang.org/p/Zqo5VK1Xz8

    I'm building a B+ tree and am messing around with putting the keys into a
    Keys slice. A Key is an interface, so a Keys type is a slice of Key
    interfaces. I have an InsertAt method that is trying to put data into a Keys
    slice based on a specific position. E.g InsertAt(5, key) would put "key" at
    keys[5] after moving all elements at position [5:] right along the array by
    1 position, so the current position 6 becomes 7, then 5 becomes 6, then I
    put my element in at 5. If I use the signature "func (ks Keys)
    InsertAt(p
    int, k Key)" it seems like a copy of ks (which a Keys type, which is
    actually []Key) is created and passed to InsertAt, and any modifications
    that happen to it don't affect the original as one would expect with a copy.
    However, if I pass it as a reference with "func (ks *Keys) InsertAtRef(p
    int, k Key)" it does operate on the original as expected with a
    reference.

    Yes, that is how it works.
    What's confusing me here is I thought slices were already pointers from
    https://golang.org/doc/effective_go.html#slices - does "masking" the fact
    it's a slice by assigning it through a type definition change some
    fundamental property of passing references vs passing values?
    Slices are not fully reference types. They contain a reference to the
    underlying array, but the length and capacity are values.

    I think it should be clear if you read https://blog.golang.org/slices .

    Ian
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedSep 25, '15 at 6:14p
activeSep 25, '15 at 7:47p
posts3
users2
websitegolang.org

People

Translate

site design / logo © 2021 Grokbase