Go Builtin Functions You Should Know Cold Before Coding
All eighteen Go builtin functions in one table, grouped by purpose, with real output and the traps in len, copy, delete, min and print.

The builtin functions are the part of Go's vocabulary that you never import and rarely read about, because each one is obvious until the day it is not. They are defined by the language and not by any package, which is why several of them do things ordinary functions cannot: len works on strings, arrays, slices, maps and channels, make takes a type as its first argument and append changes its result type with its input. This reference lists all of them, runs each against real values, and notes the corner that bites. It is part of the Go basics path, and each of the data structures has its own article.
Tested with Go 1.25.6, macOS on Apple Silicon (arm64)
The list
| Builtin | What it does | Works on |
|---|---|---|
append(s, x...) | Returns a slice with the elements added | Slices (and []byte plus a string) |
len(x) | Number of elements or bytes | String, array, slice, map, channel |
cap(x) | Capacity | Array, slice, channel |
make(T, n...) | Allocates and initializes | Slice, map, channel |
new(T) | Allocates a zeroed T, returns *T | Any type |
copy(dst, src) | Copies elements, returns the count | Slices, and a string source for []byte |
delete(m, k) | Removes a key | Maps |
clear(x) | Empties a map or zeroes a slice's elements | Maps, slices |
close(ch) | Marks a channel as having no more sends | Channels |
min(x...), max(x...) | Smallest or largest argument | Ordered types |
complex(r, i), real(c), imag(c) | Build and take apart complex numbers | Floats and complex values |
panic(v) | Stops the normal flow and unwinds | Any value |
recover() | Stops a panic, inside a deferred function | |
print(...), println(...) | Low level output to standard error | Basic types |
That is eighteen names counting min and max, real and imag, and print and println separately. Outside the list sit the predeclared constants and values, true, false, iota and nil, and the predeclared types such as int, string, error and any.
Running each
One program, with its output, exercises every row in the table:
package main
import (
"fmt"
"math"
)
func main() {
s := []int{1, 2, 3}
s = append(s, 4, 5)
t := append([]byte("go"), " lang"...)
fmt.Println(s, len(s), cap(s) >= 5, string(t))
arr := [4]int{}
m := map[string]int{"a": 1}
ch := make(chan int, 3)
ch <- 1
fmt.Println(len("héllo"), len(arr), cap(arr), len(m), len(ch), cap(ch))
a := make([]int, 2, 10)
b := make(map[string]bool, 100)
c := make(chan struct{})
fmt.Println(len(a), cap(a), len(b), c != nil)
p := new(int)
*p = 7
fmt.Println(*p)
dst := make([]int, 2)
n := copy(dst, s)
bs := make([]byte, 3)
n2 := copy(bs, "hello")
fmt.Println(n, dst, n2, string(bs))
delete(m, "a")
delete(m, "missing")
fmt.Println(len(m))
clear(s)
fmt.Println(s)
fmt.Println(min(3, 1, 2), max(2.5, 1), min("b", "a"), max(1, 2.5))
fmt.Println(min(1, math.NaN()), max(math.Inf(-1), 0))
z := complex(3, 4)
fmt.Println(real(z), imag(z), z*z)
close(ch)
v, ok := <-ch
fmt.Println(v, ok)
v, ok = <-ch
fmt.Println(v, ok)
defer func() {
fmt.Println("recovered:", recover())
}()
panic("boom")
}[1 2 3 4 5] 5 true go lang
6 4 4 1 1 3
2 10 0 true
7
2 [1 2] 3 hel
0
[0 0 0 0 0]
1 2.5 a 2.5
NaN 0
3 4 (-7+24i)
1 true
0 false
recovered: boomRead the results against the table. After append, the slice has five elements, and a capacity of at least five, which is all the language promises. The byte slice append used the special form that accepts a string with .... len("héllo") is 6, counting bytes, as strings explain. An array's cap equals its length. A buffered channel reports the number of queued values with len and its buffer size with cap, so len(ch) was 1 after one send. make with a length and capacity gave a slice of length 2 and capacity 10, and the size argument to a map is a hint and not a limit.
The corners, builtin by builtin
append returns a new slice header, and ignoring the result is a compile error, append(s, 1) (value of type []int) is not used. It may or may not reuse the array, which the append trap explains in detail.
len and cap are evaluated at compile time for arrays and constant strings. For a nil slice, map or channel, len is zero.
make is for slices, maps and channels only. make([]int, n) creates n zero elements, which is not what you want before appending, as slices explained warns. new(T) returns a pointer to a zero T, and &T{} is more common for structs, as pointers in Go notes.
copy copies as many elements as the shorter of the two slices, 3 bytes here from "hello". It handles overlapping ranges correctly, so you can shift elements inside one slice, and it accepts a string source only for a byte destination. The destination must already have length, as copy a slice the safe way shows.
delete on a missing key or on a nil map is a no-op and does not panic.
clear sets every map entry to nothing for a map and every element to its zero value for a slice, without changing the slice's length. It arrived in Go 1.21.
min and max, also Go 1.21, take two or more values of one ordered type, and untyped constants mix as in max(1, 2.5), which printed 2.5. If any argument is a floating NaN, min and max return NaN, as the output NaN shows. For strings they compare bytes. They replace the hand-written if and the math.Min calls, which always use float64.
close is for channels, and the receive after close returns the zero value and false, the "comma ok" form that the output shows as 0 false. Sending on a closed channel panics, and closing a nil or already closed channel panics. The rules are in closing channels and who may do it.
complex, real, imag are rarely used outside numeric code. The result of complex(3, 4) squared is (-7+24i).
panic and recover are the exception mechanism, covered in recovering from panics. recover only works inside a deferred function, and returns nil otherwise.
print and println write to standard error, with their own formatting, not fmt's, and the specification says they are not guaranteed to stay. Use them to debug the runtime or in a program with no imports, and use fmt or log for anything else. A println of a float prints in a scientific format that is surprising the first time.
What is not on the list
Familiar functions that are not builtins: fmt.Println, strings.Contains, sort.Ints, os.Exit. Anything you have to import is a library function. The standard math package has math.Max and math.Min, but they work on float64 only, and min and max are the better choice for new code. Operations that look like builtins, such as len on a string, are language features and cannot be passed as function values. To use len as a callback, wrap it in a function literal. The authoritative definitions are in the specification's list of built-in functions, and the same section of the Go 1.21 release notes describes the additions.


