Home > front end >  All entries in slice end up identical after copying from another slice
All entries in slice end up identical after copying from another slice

Time:01-14

I have a slice of uuid.UUID elements. From the source, a uuid.UUID is just a type alias for a byte array: type UUID [16]byte.

I'm trying to convert this slice of uuid.Uuids to a slice of []byte using the following code:

package main

import (
    "fmt"
    "github.com/google/uuid"
)

func main() {
    ids := []uuid.UUID {
        uuid.New(),
        uuid.New(),
        uuid.New(),
    }
    fmt.Printf("ids: %v\n", ids)
    idBytes := make([][]byte, len(ids))
    for i, id := range ids {
        idBytes[i] = id[:]
    }
    fmt.Printf("idBytes: %x\n", idBytes)
}

playgroud link

For some reason, this produces the following output:

ids: [66b4bb26-3c1f-4dd7-a608-aa8f799e4bfe 014e0537-c326-4021-be38-165f49595eed 5c71efff-ddb5-4f6e-8f85-c1dab013b5d1]
idBytes: [5c71efffddb54f6e8f85c1dab013b5d1 5c71efffddb54f6e8f85c1dab013b5d1 5c71efffddb54f6e8f85c1dab013b5d1]

There are clearly 3 distinct UUIDs, but the output slice contains only the last one, repeated 3 times. What's going on here?

Things I've tried:

  1. Use a non-slice type instead of a slice type (that is, use []uint64 as input and output instead of []uuid.UUID and [][]byte). This shows the expected behavior (I see 3 distinct values instead of the last value repeated 3 times), but it doesn't actually solve my problem.
  2. Set only the last element (put the idBytes[i] = id[:] inside an if i == len(ids) - 1 block). This sets only the last element (the first two elements remain nil).

CodePudding user response:

Two facts to consider:

  • id is of type UUID, which is [16]byte.
  • Loop variables a overwritten at each iteration

Thus, there is only one instance of id is allocated and shared between all iterations of the for loop. Since id is an array (not a slice), contents of each UUID are copied to id. All the slices id[:], thus, point to the same shared underlying byte array, which, when the loop ends, contains the latest contents of id.

To fix:

idBytes[i] = ids[i][:]

which will create separate slices for each UUID.

  •  Tags:  
  • Related