Комментарии 11
Ошибка rows.Close присваивается другой переменной: closeErr. Прежде чем присвоить ее переменной err, мы проверяем, отличается ли err от nil. Если это так, то ошибка уже была возвращена функцией getBalance, поэтому мы решаем записать err в лог и вернуть существующую ошибку.
Странный момент. Как по мне лучше вернуть и closeErr, если таковая имеется.
err = errors.Join(err, closeErr)
И уже вызывающая сторона решит как реагировать на ошибку.
Можно создать для этого ошибку
var cErr = errors.New("Close error")
Узнать была ли она if errors.In(err, cErr) ...
или через type CloseError struct ... если нужны подробности ошибки
Тогда проверка if _, ok := err.(*CloseError); ok ...
Лень расписывать, кто пишет на golang, тот поймет.
Короче пример очень плохой обработки ошибки (
С утечкой capacity тоже фигня какая-то... Обещали копию всего слайса, а по-факту, копируется только структура с указателем, длиной и размером.
https://go.dev/play/p/MDLJQ6whbwR
Или я что-то не так понял?
Тут скорее вот это https://go.dev/play/p/z1pFsj7eUwN имеется в виду
Тогда причем там аллокация гигабайтов памяти? В общем, складывается впечатление, что автор оригинала не совсем понимает то, что пишет.
А ведь, кстати, да. Объект создаётся новый, но ссылается на тот же массив. Т.е. при изменении b
, изменится и a
. https://go.dev/play/p/K-DVpiwX1n2
Я думаю что там подразумевается что storeMessageType складывает полученный слайс куда-то ещё в память, и GC не придёт за изначальным мегабайтным слайсом данных, т.к. на него ещё висит ссылка в виде 5-элементного слайса, который где-то висит в памяти
Как я понял там речь не про копию слайса, а о том, что если вы решите слайс из 5 элементов (который образован из слайса на 1мб через [:5]) где-то сохранить на длительное время и остальная часть от 1мб вам никогда не понадобится, то gc память не очистит.
При этом, если создадите новый слайс и скопируете 5 элементов, то с условием выше (остальная часть от 1мб вам никогда не понадобится) gc очистит лишнюю память.
Проверить варианты (в 12 строке true и !true):
func getMessageType(msg []byte) []byte {
return msg[:5]
}
func receiveMessage() []byte {
return make([]byte, 1_000_000)
}
func storeMessageType([]byte) {}
Понимаю, что пример синтетический, но нельзя такое в книгах писать: новички видят, потом используют. Во-первых слайс байт, который мы передаём, он же откуда-то взялся. Скорее всего из ридера. "Принимай интерфейсы, отдавай структуры". Автор другим советует принимать интерфейс (вместо файла), а себе не смог. Во-вторых в Go не принято принуждать к аллокациям. А если я а хочу 10 тыс раз сделать receiveMessage()
? А если я точно знаю, что буду делать их по очереди и хотел бы переиспользовать слайс вместо его многократного выделения?
Некоторые советы, которые я почерпнул из книги «100 ошибок в Go»