Skip to content

Instantly share code, notes, and snippets.

@Sc4ramouche
Created January 1, 2024 21:38
Show Gist options
  • Save Sc4ramouche/a90826d6ca36579910edbae314442c8f to your computer and use it in GitHub Desktop.
Save Sc4ramouche/a90826d6ca36579910edbae314442c8f to your computer and use it in GitHub Desktop.
Golang Notes

Frontendmasters course on Go basics — Source.

Notes

  • Three main pillars of Go philosophy: ease of coding, efficient compilation, efficient execution.l
  • main function is an entry point for a Go program.
  • Go programs consist of packages. In most cases, one can thing of a package like a folder with source code files.
  • A package actually ends up compiled as a single long file, even if you had broken up the package into multiple files.
    • This explains why variables and functions are available across files within a package.
    • Package name has no relationwith the folder name containing the package (i.e. they can be different).
    • It's not advised to have nested packages in Go. It is possible to have a private sub-package though.
  • In Go, module mostly stands for an application.
  • Variables of different types have different "default" values: emtpty string, 0, false, nil for pointers.
  • Q: there's print function available by default, why use fmt package? A: fmt tries to be a robust way to provide values to standard output, while print might not work on every OS or platform.
  • Visibility is simple in Go — things starting with uppercase are visible, while lowercase properties are private.
  • In Go it's possible to convert types, i.e. an int can be converted to float64var i = 10; float64(i).
  • Arrays are explicit about their nature in Go. Since arrays have fixed size, it is clear from the type, i.e. [3]string.
  • In Go, every source file can have an init function — documentation.
    • Usecases: complex initialisation that cannot be expressed as declarations or checking the current state of the program to possibly reset state/recover in any way.
  • In Go, nothing is an object. Thus executing things like myArray.length doesn't make sense in Go (here we'd use len(myArray)).
  • Operating with slices (a.k.a dynamic arrays in Go) looks a lot like working with immutable arrays in JavaScript.
  • Arguments are always passed by value in Go functions. Thus, when we need a side effect, we pass a pointer.
  • Formatting can be quite simple in Go — there's a shortcut of %v that we can use as a placeholder for a value in a function like fmt.Sprintf.
  • I didn't know this, but it is possible to have a pointer to a pointer in Go. I assume the same should be possible in C too, although I've never seen a pointer to a pointer yet (for good reasons perhaps).
  • Functions can panic. This is complete halt of execution.
    • Side note — at first I was wondering if function signature can express if a panic is possible, but on the second thought, knowing that in advance won't help, as execution will be stopped before we can recover.
  • defer is a useful keyword in Go. It helps to defer execution of a line of code until the end of the block scope of a function. Can be nice for closing database connections, etc.
    • Also, defers are executed before panic shuts down the program.
  • In golang, there's only for loop available. However, it has quite a flexible structure (can work with conditional expression for instance).
  • You can create a variable, that will only be accessible within the scope of the if block, quite handy.
  • Go has sweet switch statement, which allows to specify a dedicated condition for every case (something I miss in JS's switch).
  • In Go, you are one keystroke away from reading source files of the dependencies you use (follow definition from your text editor or IDE). That's a relief after walls of TS declarations.
  • In Go, you can introduce a type alias for one of the standard types. You can define a method for a type alias, which is not possible for the standard types.
  • It is not mandatory to pass all values when creating a struct in Go.
    • This initially made me think "oh and how do I ensure that a certain property is populated?". The answer seems to be constuctor functions (referred to as "factory functions" in the course).
  • In Go there's no inheritance, but we have type embeddings instead. One type can incorporate another in it's definition, and both will be "merged".`
    • When embedding a type, methods defined on the embedded type also become available.
  • If you define a String method on a struct, you can then pass it to fmt.Printf.
  • If you add a comment to a type, it becomes visible like "docs" to the type (i.e. when doing Shift+K).
  • In Go, interfaces are used to define a shape that types must conform to (i.e. to be able to pass a certain type to a function).
    • You don't need to explicitly specify that a certain type implements a certain interface. This is called "implicit implementation".
  • Note to self — while goroutines are easy, I should at some point properly learn multithreading, parallelism, green threads and other key terms.
  • Goroutines are not guaranteed to get executed. If the main goroutine ends, that's it.
  • If your function is supposed to return a value of particular type, say (Rate, error), you cannot just use nil as the value there. The trick in Go to work around that is to return a pointer to the value - (*Rate, error). Pointers can be nil, so it's ok.
    • This is why most of the times when an API has to return a structure, it returns a pointer to a structure instead.
  • Dot operator also serves as a shortcut to dereference a pointer.
  • Since JSON responses might not exactly map to the types of our applications, it is common to create a ResponseType specifically for a third party API, which can later be "converted" to a type that we initially had in mind.
  • Structs can have those comments declared, and for example json package relies on those comments to match json properties to properties of the ResponseType. To be clear, this is done as ResponseType properties are starting with Uppercase letters to be public, and JSON is unlikely to have uppercase letters in properties.
  • I was amazed how even async operations looks like synchronous operations in Go. It turns out, those operations are in fact synchronous — there's a chance that if we look into the sources of functions like http.Get, there will be a for loop waiting for results.
  • There's a new concept of test "Fuzzing", I should probably look it up later.
  • Something I ran into: if I just execute go test in root, it will report there are no test files. It turns out, that one should test recursively with go test -v ./... command.
  • Random reflection — I compare my experience of learning Go with my experience of learning OCaml. And I feel tenfold more confident following a video course, as you have your questions along the way, and if the instructor is good, they will add extra context that will help to answer your questions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment