4

Purpose: I have a big buffer, and I would like to have an array/slice of pointer pointing to different loc in the buffer.

What I am doing:

datPtrs := make([][]byte, n)
for i:=0; i<n; i++{
    datPtrs[i] = bigBuf[i*m:(i+1)*m]
}

My Question:

  1. Will this copy memory? My guess is not, but I cannot find anywhere to confirm this.
  2. What is the best way/tool to find out whether there is memory copy or not?
1a1a11a
  • 1,187
  • 2
  • 16
  • 25
  • 2
    Incomplete answer to your second question: if you have [some test code,](https://play.golang.org/p/xJdJHAqqZz_1) you can verify things like this empirically by just writing new information to one of the values; if it affects the other one, then you have a new reference instead of a copy of the original memory. – Jesse Amano Mar 18 '19 at 18:57
  • 2
    Where did you look for information on this topic? I'm sure this exact topic is documented really well. You should at least read the introduction and the effective go documents, both available at https://golang.org. – Roland Illig Mar 18 '19 at 18:58
  • 3
    Technical answer to the second question: *everything is a copy*, you just need to know *what* you are copying. In the case of slices, maps, pointers, and interfaces, it's a pointer that's being copied. – Adrian Mar 18 '19 at 19:00
  • Thank you all, the information is really helpful! – 1a1a11a Mar 18 '19 at 22:29

2 Answers2

4

Go slices are implemented as a struct:

src/runtime/slice.go:

type slice struct {
    array unsafe.Pointer
    len   int
    cap   int
}

You are assigning/copying the slice struct, which does not copy the underlying array, only its pointer.


A simple illustration:

package main

import (
    "fmt"
)

func main() {
    buf := make([]byte, 8)
    for i := range buf {
        buf[i] = byte(i)
    }
    sub := buf[1:3]
    fmt.Println(buf)
    fmt.Println(sub)
    for i := range sub {
        sub[i] += 43
    }
    fmt.Println(buf)
    fmt.Println(sub)
}

Playground: https://play.golang.org/p/4OzPwuNmUlY

Output:

[0 1 2 3 4 5 6 7]
[1 2]
[0 44 45 3 4 5 6 7]
[44 45]

See The Go Blog: Go Slices: usage and internals,

peterSO
  • 158,998
  • 31
  • 281
  • 276
3
  1. No

Slice is just a pointer to memory + len and cap
see: Why can not I duplicate a slice with `copy()` in Golang?


  1. Like so:
package main

import (
    "fmt"
)

func main() {
    bigBuf := []byte{1, 2, 3, 4, 5}

    datPtrs := make([][]byte, 2)
    for i := 0; i < 2; i++ {
        datPtrs[i] = bigBuf[i : i+1]
    }
    fmt.Println(bigBuf) // [1 2 3 4 5]
    datPtrs[0][0] = 10
    fmt.Println(bigBuf) // [10 2 3 4 5]

    datPtrs[1][0] = 20
    fmt.Println(bigBuf) // [10 20 3 4 5]
}

wasmup
  • 14,541
  • 6
  • 42
  • 58