
1 min read
Channel types
Channel types A channel provides a mechanism for concurrently executing functions to communicate by sending and receiving values of a specified element type. The value of an uninitialized channel is nil. ChannelType = ( "chan" | "chan" "<-" | "<-" "chan" ) ElementType . Channels are one of the most confusing parts of Go, for many newcomers. But they don’t need to be. They’re actually quite simple. Think of a channel as an array, which can only be read from one end, and appended to the other.

2 min read
Map length and capacity
Maps, like arrays and slices, have length. Map types … The number of map elements is called its length. For a map m, it can be discovered using the built-in function len and may change during execution. … This should be straight forward, but let’s consider a couple examples for good measure: x := map[string]int{"a": 1, "b": 2, "c": 3} fmt.Println(len(x)) // 3 var y map[string]float64 fmt.Println(len(y)) // 0 And somewhat deceptively, their capacity can also be set, or at least hinted at, but not read.

2 min read
Using maps
Today I’m jumping around a bit, for the sake of coherence. Map types … [Map] elements may be added during execution using assignments and retrieved with index expressions; they may be removed with the delete built-in function. A new, empty map value is made using the built-in function make, … Let’s summarize with examples. We’ll dive into details as the relevant portions of the spec come up. To create a map, you use the built-in function make:

1 min read
Map Keys
The only restriction on map keys is that they must be comparable. The spec explains: Map types … The comparison operators == and != must be fully defined for operands of the key type; thus the key type must not be a function, map, or slice. If the key type is an interface type, these comparison operators must be defined for the dynamic key values; failure will cause a run-time panic.

1 min read
Map types
Map types A map is an unordered group of elements of one type, called the element type, indexed by a set of unique keys of another type, called the key type. The value of an uninitialized map is nil. MapType = "map" "[" KeyType "]" ElementType . KeyType = Type . Maps should be familiar to just about anyone who’s familiar with programming, by one name or another. “Hashmaps,” “dictionaries,” “associative arrays,” or even simply “objects” in JavaScript or JSON.

2 min read
Implementing an interface
It feels like it’s been a month since we started on interfaces. Today we’re covering the final section on this topic! Implementing an interface A type T implements an interface I if T is not an interface and is an element of the type set of I; or T is an interface and the type set of T is a subset of the type set of I. A value of type T implements an interface if T implements the interface.

2 min read
Recursive interfaces
Check out this week’s episode of the Cup o’ Go podcast: What the ʕ◔ϖ◔ʔ? New merch, TDD book interview with Adelina Simion, and more You can probably guess Go’s rules about recursively embedding interfaces. In short: It’s not allowed. General interfaces … An interface type T may not embed a type element that is, contains, or embeds T, directly or indirectly. // illegal: Bad may not embed itself type Bad interface { Bad } // illegal: Bad1 may not embed itself using Bad2 type Bad1 interface { Bad2 } type Bad2 interface { Bad1 } // illegal: Bad3 may not embed a union containing Bad3 type Bad3 interface { ~int | ~string | Bad3 } // illegal: Bad4 may not embed an array containing Bad4 as element type type Bad4 interface { [10]Bad4 } Note however, that, an interface method may refer to the interface itself.
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.

2 min read
Interfaces as type constraints
If you’ve been playing around with interface types while reading about them for the last couple of weeks, you have probably noticed something: Many of the interface types described don’t work as variables. Here we see why: General interfaces … Interfaces that are not basic may only be used as type constraints, or as elements of other interfaces used as constraints. They cannot be the types of values or variables, or components of other, non-interface types.

1 min read
Union restrictions
General interfaces … Implementation restriction: A union (with more than one term) cannot contain the predeclared identifier comparable or interfaces that specify methods, or embed comparable or interfaces that specify methods. Or putting this another way: Unions (that is, interface type parameters with a | character), only work on interfaces defined by other type parameters. interface { int | float32 // Valid int | error // Invalid: error is an interface that specifies a method int | comparable // Invalid: comparable is not a type parameter-defined interface } Quotes from _The Go Programming Language Specification_ Version of December 15, 2022
21 min watch
ChatGPT-4 vs ChatGPT-3 vs Go
ChatGPT didn't do so well when quizzed about Go. Can ChatGPT 4 do better?

2 min read
Type parameter restrictions
We’ll get to a full discussion of type parameters later on, but knowing at least what they look like is useful for the next section. So here’s an example, used in the definition of a generic function: func min[T ~int|~float64](x, y T) T { In this example, min[T ~int|~float64] represents the type parameter. With that in mind… General interfaces … The type T in a term of the form T or ~T cannot be a type parameter, and the type sets of all non-interface terms must be pairwise disjoint (the pairwise intersection of the type sets must be empty).