
2 min read
Type identity wrapup
Today we wrap up our discussion of type identity. This is mostly a recap of what has already been discussed the last few days. Type identity … Given the declarations type ( A0 = []string A1 = A0 A2 = struct{ a, b int } A3 = int A4 = func(A3, float64) *A0 A5 = func(x int, _ float64) *[]string B0 A0 B1 []string B2 struct{ a, b int } B3 struct{ a, c int } B4 func(int, float64) *B0 B5 func(x int, y float64) *A1 C0 = B0 D0[P1, P2 any] struct{ x P1; y P2 } E0 = D0[int, string] ) these types are identical:

2 min read
Type identities of other types
Type identity … Two pointer types are identical if they have identical base types. Given: type ( P = *int Q = P R *int ) P, Q, and *int are all identical to each other, but different from *int32 and R. Two function types are identical if they have the same number of parameters and result values, corresponding parameter and result types are identical, and either both functions are variadic or neither is.

2 min read
Type identities of compound types
So we now know that types are either identical or different. let’s look at the details, with examples. Type identity … In detail: Two array types are identical if they have identical element types and the same array length. So given: type ( X = [10]int Y = X Z [10]int ) Types X, Y, and [10]int are identical to each other, but not to [9]int or [10]int32. Type Z is also different from all the others, due to the fact that it is a named type.
23 min watch
Writing the perfect résumé to land your first Go job
I critique the résumé/CV of someone looking for their first Go job, and offer my suggestions for improvement.
Subscribe to Boldly Go: Daily
Every day I'll send you advice to improve your understanding of Go. Don't miss out! I will respect your inbox, and honor my privacy policy.
Unsure? Browse the archive.

1 min read
Type identity
Type identity Two types are either identical or different. Well now that’s profound, isn’t it? LOL. The real point is that there are not different “degrees of similarity.” The spec continues… A named type is always different from any other type. Otherwise, two types are identical if their underlying type literals are structurally equivalent; that is, they have the same literal structure and corresponding components have identical types. So the rules for type identity are rather simple.

3 min read
Core types
Yesterday we discussed underlying types. Today we’re looking at the somewhat more essoteric concept of a core type. The concept of a core type, as distinct (sometimes) from the underlying type exists for the benefit of some generics-related constructs. This will make more sense as we get to these uses of core types in the future. So for now we’re just going to breeze through the description, without diving into additional detail than what is provided in the spec.

2 min read
Underlying types
We’ve made it through the complete list of types in Go. Now we’re going to dig into some of the fundamentals, with a tour of general “Properties of types and values”. Properties of types and values Underlying types Each type T has an underlying type: If T is one of the predeclared boolean, numeric, or string types, or a type literal, the corresponding underlying type is T itself. Otherwise, T’s underlying type is the underlying type of the type to which T refers in its declaration.

2 min read
Channel synchronization
I’ve made the case that channels are just data types, and non-magical. So why should we care about channels, rather than just using some sort of slice, array, or custom first-in-first-out queue? The reason is that channels provide us certain guarantees with regard to synchronization. The spec explains: Channel types … A single channel may be used in send statements, receive operations, and calls to the built-in functions cap and len by any number of goroutines without further synchronization.

1 min read
Closing channels
Channel types … A channel may be closed with the built-in function close. The multi-valued assignment form of the receive operator reports whether a received value was sent before the channel was closed. Closing a channel is a simple matter of using the built-in close function: // ch must be of type `chan T` or `chan<- T`. A receive-only channel (`<-chan T`) cannot be closed. close(ch) Calling close on a channel takes immediate effect, and prevents further values from being written to the channel (any items already in the channel may still be read).

2 min read
Creating channels
Channel types … A new, initialized channel value can be made using the built-in function make, which takes the channel type and an optional capacity as arguments: make(chan int, 100) Here we have the semi-magical make built-in function again. We’ve already seen it for use with arrays and slices. Consider this yet another clue that a channel is just another type, similar to array and slice, in that it “just” holds a bunch of values, and isn’t magical in any way.

2 min read
Directional channels
Channel types … The optional <- operator specifies the channel direction, send or receive. If a direction is given, the channel is directional, otherwise it is bidirectional. A channel may be constrained only to send or only to receive by assignment or explicit conversion. chan T // can be used to send and receive values of type T chan<- float64 // can only be used to send float64s <-chan int // can only be used to receive ints When you create a new channel, you get a bidirectional channel.