Skip to content
academia.sh

Course Beginner

Go Fundamentals

Published

By the end of this course

Start course

01

Language Basics

Tying the language's design goals to readability and compile speed, running the first program with module initialization, short declaration alongside sequential constants, the distinction between integer and floating-point types, the defined behavior of every variable left without an initial value, control flow and loop forms gathering into a single keyword, and what a multiple return value and a variadic argument correspond to in an empty call.

  1. 01 Go's Design Goals Four things the Go compiler rejects — an unused variable, an unused import, an unwritten return value, an implicit type conversion — are run from inside the program by calling a compiler; all four stop compilation, and rejecting the implicit conversion grows the source doing the same work from 15 characters to 22.
  2. 02 Environment Setup and the First Program Three things are mandatory for a Go source to compile: a package declaration, an entry point (func main), and a module file; when one of the three is missing, compilation is rejected even if the rest of the source has not changed at all — the module file never sits inside the source itself.
  3. 03 Variables and Constants Short declaration decides a variable's type without ever writing it into the source; only two of a six-constant iota sequence have a value written in the source — the other four come from repeating the previous expression — and the same short-declaration line is rejected at package level while it is accepted inside a function.
  4. 04 Basic Types Four unwritten cases are run through the same frame: an untyped constant's default type turns out to be int, a sum that overflows an int8 wraps to -128, two float64 values added at runtime do not come out equal to 0.3, and a character literal's type is actually int32 — rune is only an alias. Limiting measurement: the implicit-conversion rejection does not hold for constants.
  5. 05 Zero Values Fifteen unwritten cases are run through a single frame: eight find a defined counterpart from the language, four are rejected by the compiler, three are left open to runtime. Limiting measurement: nil can be appended to a slice but cannot be written to a nil map — both are the same kind of zero value.
  6. 06 Control Flow Five forms are measured with the same question — unconditional for, single-condition for, expressionless switch, an early return without an else, a switch branch that does not fall through on its own — and all five fill the unwritten part with a defined counterpart. Limiting measurement: an unwritten break is not needed, but code that wants to fall through has to write an extra word (fallthrough).
  7. 07 Functions A named return value left completely untouched carries its type's zero value; a function never writing a return value at all is rejected at compile time, but a caller ignoring what comes back without ever catching it says nothing at all — since error is itself just a return value in Go, this open behavior is the course's most important example. Limiting measurement: once a return value is captured into a variable and left unused, this openness closes and the unused-variable rejection takes over.
  8. 08 Variadic Functions A variadic parameter given no argument at all becomes a nil slice, arguments written one by one produce a fresh slice, and opening an existing slice with ... shares the same backing array without copying it — a change the callee makes is visible to the caller. Limiting measurement: a nil slice and an empty slice are the same length but diverge on == nil, and this difference becomes visible in their JSON counterpart.

02

Composite Types

The array's fixed length and the slice's length-capacity pair and growth behavior, the copying traps of the shared underlying structure in slice operations, a map's missing key giving two answers at once, struct fields' order and embedding, the consequences of taking an address and choosing between a value and a pointer receiver, and the distinction between a string being a byte array and a rune.

  1. 01 Arrays and Slices The same assignment line produces a copy in an array and sharing in a slice: an array's length is part of its type, and all elements are copied when it is assigned, while assigning a slice copies only the header and shares the backing array with the source. The limiting measure shows that a slice is also a value: sharing is cut off once an append call exceeds capacity, because the copied header now points to a separate backing array.
  2. 02 Slice Operations The same append call, with the same source text, gives two different results at two different capacities: sharing continues within the capacity limit and writing to the derived slice changes the source, while sharing is cut off once capacity is exceeded and the source stays untouched. Two notations close this gap: an independent copy taken with copy, and the three-index slice expression that explicitly bounds capacity.
  3. 03 Maps Reading from a map falls into four separate classes in four separate forms: an existing key gives its value, a missing key gives an absence answer along with the zero value, reading from a nil map is defined but writing to it panics, a deleted key behaves as though it never existed again. Iteration order is deliberately random and is never printed directly anywhere. The limiting measure shows why comma-ok access is necessary: a record whose value is zero and a record that never existed cannot be told apart with single-value access.
  4. 04 Structs The zero value of unwritten fields, the fragility carried by fields being writable positionally, and embedding carrying unwritten names to the outer type are measured: an embedded type's methods can be called without ever being written on the outer type. The limiting measure shows that embedding is not inheritance: when an embedded type's method is called, the receiver is the embedded value itself, not the outer struct.
  5. 05 Pointers Reading from a nil pointer is left open: the language places nothing, the compiler does not reject it either, the result is a panic. Only two of four calls change the caller's value — a value written without taking an address, whether in a function parameter or a method receiver, only operates on its own copy. The limiting measure shows that a pointer is also a value: reassigning a pointer changes only the local copy, while writing to what it points to changes the caller.
  6. 06 Strings and Runes A Go string is a byte array: length counts bytes, indexing returns a byte, only range gives a rune. The same text's byte count, rune count and first byte are measured separately from each other, and the string is shown to be immutable. The limiting measure shows that rune count is also not character count: combining marks can produce text that looks the same with different rune counts.

03

Packages and Tooling

Exporting depending on a single letter and package layout's counterpart in visibility, the module file's selection of an unwritten version, the language's own command family enforcing unwritten rules, the conventions that documentation generation from the source depends on.

  1. 01 Package Layout and Visibility Whether an export is visible from one package to another is tied to the case of a single letter, shown by running the compiler from within a program across four trials: an uppercase function and a struct constructed only with its exported field compile; a lowercase function and an attempt to read a struct's unexported field from another package do not. The limiting measurement shows that two separate files of the same package share each other's lowercase name without any trouble at all — the boundary of visibility is not the file, it is the package.
  2. 02 Modules and Dependencies A dependency's version is most often never written in the source at all; of six requests, three are written in the main module's own source, three are derived from a dependency's own dependency. The module file's rule for filling in an unwritten version — minimal version selection — is modeled and run within the source; no network call is made. The limiting measurement shows that the selected version is not the newest version in a module's catalog, only the largest of the requests actually written.
  3. 03 Go Command Family The language's own command family enforces two unwritten rules, called from within the program. When run through a formatter, a source is compared byte for byte, and 7 of an 18-line source's lines are counted as changed; the vet tool catches a pattern the compiler does not reject (a mismatch between the type a print call's format verb expects and the type of the value given). The limiting measurement shows that two sources, one formatted and one not, give the same output when run — the form changes, the meaning does not.
  4. 04 Documentation Conventions Six names — three exported, three unexported; in each triple, one has a comment adjacent to it, one has a comment separated by a blank line, one has no comment at all — are asked of the doc tool. The number of names that show up depends only on the case of the letter (3/6), while the number that carry a description depends only on the comment's position (1/6). The limiting measurement shows that an incorrect doc comment is displayed exactly the same way: the doc tool never checks the comment's correctness at all.

Final exam

Go Fundamentals — Final Exam

In preparation

This course's question bank is not complete yet. The exam opens here automatically once enough questions are added.

Start typing to search.

↑↓ ↵ Esc navigate · open · close