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




