Functions in Go are first-class values: they can be assigned to variables, passed as arguments, returned from other functions, and stored in maps. A variadic parameter func sum(nums ...int) appears inside the function as a []int, and callers can either spread individual arguments or pass a slice with s.... Higher-order functions such as sort.Slice, http.HandlerFunc, and many generic helpers accept function arguments, while anonymous function literals (add := func(a, b int) int { return a + b }) are commonly passed inline to go, defer, and callback APIs. A closure is a function literal that captures variables from its enclosing scope, which is why the classic counter factory returns a function that retains and updates n across calls.
Methods extend a named type by attaching a receiver. The choice between a value receiver (t T) and a pointer receiver (t *T) has concrete consequences: a value receiver operates on a copy and cannot mutate the original, while a pointer receiver modifies the actual value and avoids copying large structs. Because of how method sets are defined, the method set of *T includes both pointer-receiver and value-receiver methods, but the method set of T only includes value-receiver methods. This asymmetry affects interface satisfaction and is the reason receivers should be consistent within a type. A method value such as t.Add binds the method to a specific receiver, producing a closure-like value that can be passed around, while a method expression like (*Time).Add produces a function whose first parameter is the receiver.
Interfaces are Go's primary abstraction mechanism, and unlike Java or C# they are satisfied implicitly. A type satisfies an interface simply by implementing all of its methods; no implements keyword is required. This structural approach encourages small, focused interfaces such as io.Reader and fmt.Stringer. The empty interface interface{} (aliased as any since Go 1.18) is satisfied by every type, making it the universal container, but extracting the concrete value requires a type assertion v, ok := i.(string) or a type switch switch v := i.(type). Compile-time interface satisfaction can be enforced with a blank assignment such as var _ io.Reader = (*MyType)(nil). A subtle pitfall involves typed-nil interfaces: assigning a nil pointer to an interface variable does not produce a nil interface, so callers should check the underlying pointer explicitly. Finally, Go 1.18 added generics, allowing type-parameterized functions and types like func Map[T any, U any](s []T, f func(T) U) []U, which dramatically reduces the need for code generation or interface{}-based containers.