liveBook · Manning

User-defined type

As explained in Learn Go with Pocket-Sized Projects

A custom type is a programmer-defined Go type that gives a distinct name and type identity to an underlying representation.

A user-defined Go type gives a familiar representation a more precise meaning. Define one when a built-in type alone does not tell a caller what a value represents: a language code is more specific than a string, and a user ID is more specific than an int. Typed parameters make an API clearer and make accidental mix-ups harder. section 2.2.1 section 2.6

Select a greeting by language

Declare `type language string`, then accept `language` in `greet(l language)`. The call `greet("en")` uses the function signature to type the constant; a switch selects the English or French greeting. The name tells callers what the string means, while the switch handles the supported values. section 2.2.1

Listing 2.6 main.go: Adding a new language
package main

import "fmt"

func main() {
    greeting := greet("en")
    fmt.Println(greeting)
}

// language represents the language's code
type language string #1

// greet says hello to the world in the specified language
func greet(l language) string {
    switch l { #2
    case "en":
        return "Hello world"
    case "fr":
        return "Bonjour le monde"
    default:
        return ""
    }
}

The complete greeting example shows the type declaration, typed parameter, call, and switch together. section 2.2.1

Names also help at domain boundaries. A habit has separate `ID` and `Name` types even though both use strings, plus a `WeeklyFrequency` based on `uint`. A function taking an ID and a name can therefore document which argument belongs where. Creating a valid habit still requires work: its domain logic trims the name, rejects an empty one, and fills missing values. section 10.3.1

Listing 10.12 internal/habit/habit.go: Defining the business types
// ID is the identifier of the Habit.
type ID string

// Name is a short string that represents the name of a Habit.
type Name string

// WeeklyFrequency is the number of times a Habit should happen every week.
type WeeklyFrequency uint

// Habit to track.
type Habit struct {
    ID              ID #1
    Name            Name
    WeeklyFrequency WeeklyFrequency
    CreationTime    time.Time #1
}

The habit declarations show named field types alongside the entity that uses them. section 10.3.1

A custom type can also hide a representation behind a package API. `Decimal` keeps its `subunits` and `precision` fields private, so callers need a construction function rather than depending on those fields. Its string parser avoids starting with imprecise floats and can return errors for malformed or oversized values. The representation can then change without requiring callers to use different fields. section 6.2.4

How Learn Go with Pocket-Sized Projects covers it

How deep it goes
Works through declarations, typed calls, private fields, parsing, and validation; does not examine runtime type internals.
Examples
Shows language-coded greetings, a privately represented Decimal, and separately typed habit IDs, names, and weekly frequencies.
What it assumes
Assumes familiarity with Go functions and structs while introducing named types through concrete string and numeric declarations.
What you can do after
Build it from scratch with Go type declarations and typed fields, then add construction or validation where values need constraints.
How it connects
Connects named types to function signatures, switches, structs, encapsulation, parsing, and domain validation.

Also explained in

Compare how 5 books explain user-defined type →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Go with Pocket-Sized Projects. The section links point to the parts of the book it draws on.