Back to Home

Why does Go have an ampersand and an asterisk (& and *)?

c · b · bcpl · go · pointers · unix

Why does Go have an ampersand and an asterisk (& and *)?

  • Tutorial

If you have ever been confused, which means the symbol "ampersand" ( &) or "asterisk" ("multiplication sign", *) or got confused when to use what, then this article is for you. The authors of Go tried to make the language familiar to most programmers, and many elements of the syntax were borrowed from the C language. But in 2017, it is already difficult to understand whether most programmers own C or not, and I dare to assume that they no longer. Therefore, the concepts that are familiar to the past generation of developers may look like perfect gibberish for the new generation. Let's dig a little history and put all the dots over ї in questions of pointers in Go and the use of symbols &and *.



Pointers


I wrote about what pointers are and how they work in the article “How not to step on a rake in Go,” which I recommend reading to even non-beginners in Go. Short reiteration about pointers:


in fact, this is one memory block that contains the address of another memory block where the data is located. If you hear the phrase "dereference a pointer", it means "find data from the memory block that this address points to."

Here is the visualization from the article:
image


Here Point{10, 20}it is a “literal” - a new variable declared in place, “memory block”, and & is “address of this memory block”.


That is, in the code:


var a int
var b = &a
fmt.Println(a, b) //  выведет "0 0x10410020"

the variable bwill be a pointer and contain the address a.


The same code, but write type b explicitly:


    var a int
    var b *int = &a
    fmt.Println(a, b) //  выведет "0 0x10410020"

here an asterisk means "type pointer to a number." But, if it is used not before the type, but before the variable itself, then the value changes to the opposite - "value at this address":


    var a int
    var b *int = &a
    var c int = *b
    fmt.Println(a, b, c)  //  выведет "0 0x10410020 0"

This can be confusing and confusing, especially to people who have never worked with pointers that are not there, for example, in such popular languages ​​as JavaScript or Ruby. Moreover, in languages ​​like C and C ++ there are still a lot of uses for pointers, for example, "pointer arithmetic", which allows you to directly run with raw memory offsets and implement incredibly fast data structures by modern standards. It is also very convenient to receive buffer overflows due to this, creating bugs that cause billions of dollars worth of damage. There are even entire books on how to understand pointers in C .


But if the mechanics of working with pointers in Go is relatively simple, the question remains - why ampersand and asterisk - what does this even mean? Maybe it's because the symbols next to the keyboard ( Shift-7and Shift-8)? Well, to understand any topic, there is no better way than digging its story.


History


And the story is like that. One of the authors of Go was the legendary Ken Thompson , one of the pioneers of computer science who gave us regular expressions, UTF-8, and the programming language B , from which C appeared, on the basis of which, 35 years later, Go appeared. In general, the Go genealogy is a little more complicated, but C was taken as a basis for the simple reason that it is a language that for decades has been the standard for studying programming in universities, well, I think there is no need to talk about its popularity at the time.


Although Ken Thompson has now moved away a bit from Go and is flying his private jet, his decisions entered Go long before Go. In his youth, he was entertained by writing new programming languages ​​for breakfast (slightly exaggerating), and one of the languages ​​that he created together with another computer science legend Denis Ritchie was programming language B (Bi) .


At that time, Ken Thompson wrote the assembly system for the PDP-7 computer , which cost $ 72,000 - which is about half a million dollars today - had 9 KB of memory (expandable to 144 KB) and looked like this:



Actually, this operating system was called Unics, and then was renamed to UNIX. And when it came to rewriting it for the new cool PDP-11 computer , it was decided to write in some higher-level programming language. The BCPL that was the predecessor of B was too verbose - many letters. B was more concise, but had other problems that made him a poor candidate for porting UNIX to PDP-11. It was then that Denis Ritchie began working on a new language, largely based on B, specifically for writing UNIX under PDP-11. The name C was chosen as the next letter of the alphabet after B.


But back to the topic of ampersand and asterisk. The asterisk ( *) was still in the BCPL language, and it got into B with the same meaning of the pointer designation, simply because it was in BCPL. Exactly for the same reason, migrated to C.


But the ampersand (&), meaning "variable address", appeared in B (and also migrated to C simply because), and was chosen for several reasons:


  • needed one character, not two or a whole word
  • the choice of characters was very limited (more on that below)
  • as Ken Thompson himself says , the word "ampersand" sounded mnemonic like "address" and was chosen for that very reason.

If I confused you, then it’s more obvious:


And here you need to look carefully at the keyboard of that time. A little higher in the PDP-7 picture you can see the input device, which was Teletype 33 . It is worth looking at his keyboard more closely to understand the realities of that time, and to understand what limitations programmers and designers of programming languages ​​faced at that time:



As you can see, there was no touchbar or emoji :), and the characters had to be selected only from the set that was in the teletype. Also, it is noteworthy that the ampersand and asterisk were then not nearby, but as many as 4 keys apart, which refutes the idea of ​​choosing an ampersand due to the proximity of the keys. Actually, of all the available keys, Ken Thompson at that time most liked the "ampersand", similar to the "address".


Well, then you know - C became the language of the century (past), influenced a huge number of other languages, and books on C became the desktop bibles of programmers for several decades. In the same form, pointers, along with an asterisk and ampersand, also got into C ++ - another mainstream language in which most Go network and server software was written before Go.


Therefore, the decision to include pointers (without pointer arithmetic, fortunately) in Go with the same syntax was quite logical and natural. For C / C ++ programmers, these are the same basic and simple concepts as parentheses {and }.


And yet it is amazing to realize how powerful historical decisions made half a century ago on modern technology have a strong influence.


Conclusion


If you are still insecure with pointers in Go, remember two simple rules:


  • "Ampersand" &sounds like "Address" (well, both the word and the other on "A" begin, at least)))), therefore it &xreads like "address of variable X"
  • the asterisk *does not seem to sound like anything, but can be used in two cases - before the type ( var x *MyType- means "pointer type to MyType") and before the variable ( *x = y- means "value by address")

I hope this helps someone a little better understand the meaning of the pointers and characters behind them in Go.

Read Next