Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conceptual memory model of the Go language

Tags:

go

I've a question to the Go programmers amongst you. I can't find information about the details of the memory model of Go. I shall try to describe my problem:

If I declare and define a variable or array in C, I know that this exists somewhere in the RAM at exactly one position with one specific address, until I do something that will change this.

This is not the case in Python: Python does the whole memory management for me, I can't be sure that my data will be located always at one position. E.g. strings are in practice immutable, even though the language suggests that they is not. This makes secure programming with sensitive data nearly impossible (or at least very impractical).

My question is: How does Go work from this perspective. Is it more like C or like Python? Or is it completely different? Is it possible to handle sensitive data as comfortably as in C?

like image 613
dieser_K3 Avatar asked Feb 13 '23 12:02

dieser_K3


1 Answers

Note: as mention in "Go Slices: usage and internals":

The in-memory representation of [4]int is just four integer values laid out sequentially:

http://blog.golang.org/go-slices-usage-and-internals_slice-array.png

Go's arrays are values.

An array variable denotes the entire array; it is not a pointer to the first array element (as would be the case in C). This means that when you assign or pass around an array value you will make a copy of its contents.
(To avoid the copy you could pass a pointer to the array, but then that's a pointer to an array, not an array.)

One way to think about arrays is as a sort of struct but with indexed rather than named fields: a fixed-size composite value.

If you are looking at "a pointer to an array", then you would need a slice.

A slice is a descriptor of an array segment. It consists of a pointer to the array, the length of the segment, and its capacity (the maximum length of the segment).

Our variable s, created earlier by make([]byte, 5), is structured like this:

http://blog.golang.org/go-slices-usage-and-internals_slice-1.png

For the way memory allocation work for array and slice, you can check out "Effective Go"

Go has two allocation primitives, the built-in functions new and make.
They do different things and apply to different types, which can be confusing, but the rules are simple.

  • Let's talk about new first. It's a built-in function that allocates memory, but unlike its namesakes in some other languages it does not initialize the memory, it only zeros it.
    That is, new(T) allocates zeroed storage for a new item of type T and returns its address, a value of type *T.
    In Go terminology, it returns a pointer to a newly allocated zero value of type T.

  • allocation with make: The built-in function make(T, args) serves a purpose different from new(T). It creates slices, maps, and channels only, and it returns an initialized (not zeroed) value of type T (not *T).
    The reason for the distinction is that these three types represent, under the covers, references to data structures that must be initialized before use.
    A slice, for example, is a three-item descriptor containing a pointer to the data (inside an array), the length, and the capacity, and until those items are initialized, the slice is nil.

See more at "Understanding Pointers and Memory Allocation".

like image 74
VonC Avatar answered Mar 08 '23 06:03

VonC