В функции loadpage вы возвращаете два значения, одно - указатель на страницу, а другое - ошибку.
func loadPage(title string) (*Page, error) {
filename := title + ".txt"
body, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
return &Page{Title: title, Body: body}, nil
}
Это причина того, что в коде есть ошибка, и она не равна нулю. Затем верните ошибку. Но так как вам нужно вернуть Page также, он должен быть nil, поскольку это означает нулевое значение для указателя. Это показывает, что значение для Page пусто.
return &Page{Title: title, Body: body}, nil
Но если ошибки нет, вы снова возвращаете два значения, одно из которых является адресом структуры страницы со значениями, присвоенными полям страницы, но не равными ошибке.
Если значение типа не содержит никакого значения. Он должен быть инициализирован с нулевым значением, равным
false для логических значений, 0 для числовых типов, "" для строк и ноль для
указатели, функции, интерфейсы, срезы, каналы и карты.
Возвращаемое значение или значения могут быть явно указаны в выражении «return». Каждое выражение должно быть однозначным и присваиваться соответствующему элементу типа результата функции.
func complexF1() (re float64, im float64) {
return -7.0, -4.0
}
Список выражений в операторе «return» может быть одним вызовом многозначной функции. Эффект такой, как если бы каждое значение, возвращаемое из этой функции, было присвоено временной переменной с типом соответствующего значения, за которым следует оператор «return», перечисляющий эти переменные, после чего применяются правила предыдущего случая.
func complexF2() (re float64, im float64) {
return complexF1()
}
Примечание:
Независимо от того, как они объявлены, все значения результата
инициализируется нулевыми значениями для их типа при входе в
функция. Оператор return, который указывает результаты, устанавливает результат
параметры перед выполнением любых отложенных функций.
Посмотрите на спецификации Golang для Заявления о возврате