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

Related Content

Empty structs

We finally we have enough knowledge for the EBNF format not to seem completely foreign, so let’s jump back and take a look at that, with the examples provided in the spec… Struct types … StructType = "struct" "{" { FieldDecl ";" } "}" . FieldDecl = (IdentifierList Type | EmbeddedField) [ Tag ] . EmbeddedField = [ "*" ] TypeName [ TypeArgs ] . Tag = string_lit . // An empty struct.

Struct tags

Struct types … A field declaration may be followed by an optional string literal tag, which becomes an attribute for all the fields in the corresponding field declaration. An empty tag string is equivalent to an absent tag. The tags are made visible through a reflection interface and take part in type identity for structs but are otherwise ignored. struct { x, y float64 "" // an empty tag string is like an absent tag name string "any string is permitted as a tag" _ [4]byte "ceci n'est pas un champ de structure" } // A struct corresponding to a TimeStamp protocol buffer.

Struct method promotion

Yesterday we saw an example of struct field promotion. But methods (which we haven’t really discussed yet) can also be promoted. Struct types … Given a struct type S and a named type T, promoted methods are included in the method set of the struct as follows: If S contains an embedded field T, the method sets of S and *S both include promoted methods with receiver T. The method set of *S also includes promoted methods with receiver *T.