I read “Understanding Go Language from Basics”. Since the book was published in 2012, the Go version is a bit old (Go 1.0.3), but I think the syntax and concepts haven’t changed much. I might use Go in the future, so I’m taking notes on points of interest.

  • Instance Creation and Initialization: There are several options for creating instances, as shown in the code example below. What you especially need to be careful about is that Go also has the concept of pointers, so the question is whether a pointer or the actual value is generated. Also note that if you don’t explicitly specify initial values for struct elements when creating an instance, those elements are assigned zero values. As an exception, slices, channels, and maps are reference types, so use make instead of new.
var x T     // T type
y := T{ }   // T type
z := &T{ }  // *T type
w := new(T) // *T type
  • Blank Fields: In struct definitions, defining unnamed elements like _ byte allows you to implement padding.
  • Interfaces and nil: When you assign a value x of type T to an interface, internally it’s stored as a pair like <T,x> of type and value. Because of this, when checking whether an interface type value p is nil, use reflect.ValueOf(p).IsNil() instead of simply comparing with nil.
var p1 *int
var p2 interface{} = p1
fmt.Println(p1 == nil) // true
fmt.Println(p2 == nil) // false
fmt.Println(reflect.ValueOf(p2).IsNil()) // true
  • Recovery: When a fatal error occurs, such as referencing an index beyond an array’s bounds, or when calling the panic function, the program enters a panic state. In panic state, function execution is interrupted and the call stack is unwound back to the main function. However, functions deferred by defer statements are executed along the way. If the panic can be handled in a function called deferred by defer, the recover built-in function can interrupt the chain of call stack unwinding caused by the panic.

  • len and cap: A slice s has a pointer to an array, length len, and capacity cap. Here, if you reference a sub-element of slice s with v := s[2:4], then v and s will reference the same array. If you want a copy, you must explicitly use the copy function. It’s better to code this area while considering the internal structure.

  • Channel Usage Examples: In Go, to implement data sharing between threads, the concept of channels is introduced instead of shared memory. Channels are FIFO communication mechanisms that atomically send and receive arbitrary data between threads. Using channels well, you can implement synchronization, mutexes (semaphores), and data sharing. For example, for synchronization, a worker thread writes some data to a channel when a task finishes, and the master thread monitors the channel. For mutexes, you create a channel of size 1, and multiple threads compete to get that data. For data sharing, similarly create a channel of size 1, the thread that successfully retrieves the data updates it, and writes it back to the channel.

  • select statement When receiving values from multiple channels, using the select statement with syntax similar to the switch statement, you can select a channel that can receive.