error — встроенный интерфейс с одним методом Error() string. Любой тип с этим методом является ошибкой. Стандартные ошибки создаются через errors.New("text") или fmt.Errorf("format %v", val). Для кастомных ошибок определяешь свой тип: type NotFoundError struct { ID int }; func (e *NotFoundError) Error() string. Это позволяет добавить контекст и проверять тип через errors.As. Ошибки — values, их можно сравнивать, оборачивать, передавать. Нет exceptions — всё явно через возврат error.