Types, named and unnamed

February 14, 2023

Types

A type determines a set of values together with operations and methods specific to those values. A type may be denoted by a type name, if it has one, which must be followed by type arguments if the type is generic.

(and jumping ahead a bit)

Predeclared types, defined types, and type parameters are called named types. An alias denotes a named type if the type given in the alias declaration is a named type.

For now, we’re going to skip over the last part of this quotation, which relates to generics, since that’s a whole new can of worms.

Today, I want to call out the phrase “A type may be denoted by a type name, if it has one”. When does a type have a name? And how do you use a type that doesn’t have a name?

Most often, you’re likely to be dealing with types by their names. Names such as int, byte, or string, or user-defined types such as Person or BlogPost or apiError.

But sometimes we use anonymous, or unnamed types, too. This is most common with certain composite types, such as slices, arrays, and maps. []byte, for example, is an anonymous type, representing a byte slice. We could also have a named type with the same structure:

type ByteSlice []byte

But more on that another day.

Anonymous types can also be used in variable declarations, even for complex types, such as structs:

var x = struct {
	Name      string
	Age       int
}{
	Name: "Bob",
	Age:  "43",
}

This is often very cumbersome to use, as you must re-write the entire struct defintion every time you want to access the type, so this particular use of anonymous types is a bit discouraged. Although, there are times when it can be appropriate, as I recently discussed on my YouTube channel in an interview with Mechiel Lukkien: Interactive Go Code Review: mox mail server

And finally, one last example for now of an anonymous type, is the one I actually discussed in yesterday’s email, the anonymous pointer type! I.e. *string is a type, a pointer to a string, but it is unnamed. It is perfectly valid to create a custom type of this, eh, type…

type stringPtr *string

Although, the cases where it’s useful to create a named type to a pointer type are a bit rare, and it’s often confusing to do so. So I don’t generally recommend doing that. :)

Quotes from The Go Programming Language Specification, Version of January 19, 2023


Share this

Direct to your inbox, daily. I respect your privacy .

Unsure? Browse the archive .

Related Content


Non-constant conversions

Yesterday we looked at conversions of constants. Let’s now consider the more common conversion scenarios of variables and other non-constant expressions. Conversions … A non-constant value x can be converted to type T in any of these cases: x is assignable to T. ignoring struct tags (see below), x’s type and T are not type parameters but have identical underlying types. ignoring struct tags (see below), x’s type and T are pointer types that are not named types, and their pointer base types are not type parameters but have identical underlying types.


Declaring variable types

Today I’ll be love coding again. I hope you can join me! I’ll be working on the backlog for my open-source CouchDB SDK, https://kivik.io/. First some light refactoring, then adding a long-missing feature. Join me to see how many mistakes a senior Go dev makes while coding. We ended last week with a look at variable declarations. Today we continue that, with a look at how a variable’s type is determined.


Types with methods

Type definitions … A defined type may have methods associated with it. It does not inherit any methods bound to the given type, but the method set of an interface type or of elements of a composite type remains unchanged: // A Mutex is a data type with two methods, Lock and Unlock. type Mutex struct { /* Mutex fields */ } func (m *Mutex) Lock() { /* Lock implementation */ } func (m *Mutex) Unlock() { /* Unlock implementation */ } // NewMutex has the same composition as Mutex but its method set is empty.