Сергей
Andrey
нет ты объявляешь один логер на уровне мейн и передаешь этот логер в мидлварю которая его кладет в контекст джиновский
Andrey
каждый раз при создании конекста не надо инициализировать новый логер
Илья
Илья
добавьте
if err != nil {
log....
quit <- nil
}
Сергей
Сергей
Сергей
Andrey
а на уровнях service и repository меиновский?
тут не очень понял вопрос, в сервисе и в репозитории у тебя просто методы которые принимают контекст который интерфейс context.Context и контекст ты туда передаешь уже тот который у тебя есть из того места где ты эти методы вызываешь
Andrey
если ты будешь вызывать методы сервиса из хендлера то ты передашь туда контекст который достал из джина
Andrey
контекст он на то и контекст. что бы управлять всей цепочкой вызова, например вот нужен тебе таймаут какой-то операции, ты сделал контекст с таймаутом и передал дальше и тебе не надо знать что функция которую ты таймаутишь внутри себя делает, потому что она дальше будет управлять своими зависимостями через тот контекст что ты ей передал
Andrey
а если ты будешь рвать контекст и передавать в разных местах разные, то тогда весь смысл его теряется
Andrey
контекст он сделан как матрешка, если тебе надо добавить какой-то функционал к нему, то ты создаешь новый из старого, и все что было в старом сохраняется в новом, по этому ты можешь добавлять что-то свое при этом не особо задумываться что там в нем уже есть
Сергей
тогда в main нельзя так делать: repos := repository.NewRepository(ctx) ?
Andrey
контекст это вообще обычно короткоживущая структура, и в случае апи контекст живет столько, сколько выполняется запрос, и потом этот контекст уничтожается, и для другого запроса создается новый
Сергей
если брать REST, то по логике лучше чтобы контекст все-таки шел по цепочке от handler-а джиновский, а не от main, верно?
Andrey
а если ты в конструкторе передаешь контекст, то значит предполагаешь что объект который ты создаешь тоже будет короткоживущим
Andrey
Сергей
понял, спасибо
Сергей
Andrey
Ron Mount
Ron Mount
he doesnt know
Alexey
migrate create -ext sql -dir db/migration -seq init_shema
error: unknown option `-x'
Друзья в чем может быть дело? что ему не понравилось -ext же один флаг, да и команда взята буквально из документации
пытаюсь сделать миграции
Alexander
Может -- надо
Alexander
Ну и вероятно в других местах
Null
✏️ Потоковая обработка на go1.18
В версии 1.18 языка Go появились генерики, дающие возможность писать обобщенный код, то есть код, не зависящий от конкретного типа данных. Например можно написать код, обрабатывающий потоки данных - применить к ним одну и ту же функцию, отфильтровать, просуммировать и т.д., не завязываясь на конкретные типы данных. Так как я вижу потенциал в парадигме поточной обработки с помощью итераторов/стримов и теперь есть возможность реализовать ее в Go, я решил сделать это.
Эта идея появилась у меня после данной публикации. В ней рассказывается о библиотеке для языка Go для обработки данных с использованием генериков. Я попробовал эту библиотеку в своем проекте и столкнулся с следующими недостатками:
настойчивое использование IO[A], который по сути представляет собой func()(A,error) то есть любую функцию, которая может вернуть ошибку. При написании кода это создает неудобства, потому что нужно всё заворачивать в этот IO и код превращается в жонглирование io.Map и io.FlatMap. Видимо это вдохновлено библиотеками с чисто функциональным подходом. Сделано это было, чтобы была функциональная чистота, что в итоге не очень (как по мне) ложится на процедурность языка Go.
Stream[A] это обертка над стейт-машиной. Стейт-машина в данном случае это структура, в которой либо ничего нет (конец потока), либо значение и продолжение (следующее состояние) машины. В итоге это создает две проблемы. Первая: чтобы создать стрим, нужно создать его продолжение, продолжение продолжения и тд. Единственный адекватный способ этим пользоваться, который я нашел - это рекурсия. Вкупе с отсутствием Tail call optimization это приводит к второй проблеме.
Работа с стримами переполняет стек. Модель потока как стейт-машины была построена так, что переход к новому состоянию - вызов функции. Поэтому, чтобы обойти стрим целиком, надо уйти в рекурсию на глубину, равную длине потока.
Построение типа Either[A,B]. По моему скромному мнению, это вообще тип, которого не хватает в Go и который разумно реализован в языке Rust. В библиотеке этот тип это структура, содержащая и элемент типа A и элемент типа B . Плюс булевое поле как способ идентификации какой из полей действителен на самом деле. Важно то, что по сути тип Either[A,B], семантика которого элемент типа A ИЛИ B, представляется в языке как пара из элемента типа A И элемента типа B.
Не совсем очевидный интерфейс. Хотя это скорее я не до конца разобрался, что и почему. Так или иначе, я считаю, что построил интерфейс более простой и прямолинейный, не потеряв в общности.
Читать дальше
@Golang_google
Илья
✏️ Потоковая обработка на go1.18
В версии 1.18 языка Go появились генерики, дающие возможность писать обобщенный код, то есть код, не зависящий от конкретного типа данных. Например можно написать код, обрабатывающий потоки данных - применить к ним одну и ту же функцию, отфильтровать, просуммировать и т.д., не завязываясь на конкретные типы данных. Так как я вижу потенциал в парадигме поточной обработки с помощью итераторов/стримов и теперь есть возможность реализовать ее в Go, я решил сделать это.
Эта идея появилась у меня после данной публикации. В ней рассказывается о библиотеке для языка Go для обработки данных с использованием генериков. Я попробовал эту библиотеку в своем проекте и столкнулся с следующими недостатками:
настойчивое использование IO[A], который по сути представляет собой func()(A,error) то есть любую функцию, которая может вернуть ошибку. При написании кода это создает неудобства, потому что нужно всё заворачивать в этот IO и код превращается в жонглирование io.Map и io.FlatMap. Видимо это вдохновлено библиотеками с чисто функциональным подходом. Сделано это было, чтобы была функциональная чистота, что в итоге не очень (как по мне) ложится на процедурность языка Go.
Stream[A] это обертка над стейт-машиной. Стейт-машина в данном случае это структура, в которой либо ничего нет (конец потока), либо значение и продолжение (следующее состояние) машины. В итоге это создает две проблемы. Первая: чтобы создать стрим, нужно создать его продолжение, продолжение продолжения и тд. Единственный адекватный способ этим пользоваться, который я нашел - это рекурсия. Вкупе с отсутствием Tail call optimization это приводит к второй проблеме.
Работа с стримами переполняет стек. Модель потока как стейт-машины была построена так, что переход к новому состоянию - вызов функции. Поэтому, чтобы обойти стрим целиком, надо уйти в рекурсию на глубину, равную длине потока.
Построение типа Either[A,B]. По моему скромному мнению, это вообще тип, которого не хватает в Go и который разумно реализован в языке Rust. В библиотеке этот тип это структура, содержащая и элемент типа A и элемент типа B . Плюс булевое поле как способ идентификации какой из полей действителен на самом деле. Важно то, что по сути тип Either[A,B], семантика которого элемент типа A ИЛИ B, представляется в языке как пара из элемента типа A И элемента типа B.
Не совсем очевидный интерфейс. Хотя это скорее я не до конца разобрался, что и почему. Так или иначе, я считаю, что построил интерфейс более простой и прямолинейный, не потеряв в общности.
Читать дальше
@Golang_google
кстати про джененики:
разработчики хотят переделать реализации с any или одним типом (целые, дробные), то есть sync.Map[K,V], math.Min[int, float], sync.Pool[T] и т.д.
Для обратной совместимости предлагают добавить sync.PoolOf[T] , sync.MapOf[K,V] , ...Of[T]
Но, с другой стороны, не хотят навязывать приставку Of для всего с generic-type , которые должны стать основными в будущем
Вот такой парадокс, https://github.com/golang/go/discussions/48287
Alexander
Хеее)
Alexander
Непонятно как из этого выходить. Но с другой стороны есть же модули. У тебя в проекте го 1.19 и ты юзаешь дженерики без оф, а то что импортируешь и ещё не перешло компилируется со старой версией на интерфейсах
Alexander
Хочешь апнуть версию в модуле, переписываешь эти моменты. Почему бы не так?
Alexander
Что мешает?
minone
Alexander
1.19 ?
воображаемый 1.19 в котором можно сделаь так
Илья
вроде бета вышла
Maks
Интересно
Maks
Хотя че интересно скорее всего так и будет
Maks
Умножить на 0.5 почти в 2 раза быстрее чем поделить на 2
Maks
В го
Anonymous
а clang это что?
Anonymous
что она делает с билдом?
Anonymous
./a.out
whois
Друзья, а как корректно работать с числами с плавающей точкой в GO?
var f1 float64 = 0.3
var f2 float64 = 0.6
t.Log(f1 + f2) // 0.8999999999999999
Юра (Юрий Александрович)
При работе с числами с плавающей запятой нужно наперед понимать, какая необходима точность, округлять до этой точности, и с помощью математических методов проверять, обеспечивает ли алгоритм требуемую точность.
whois
🕷
Покажет тебе разница между числом 1 и 2 больше или меньше 0.001
🕷
Можешь указать нужную тебе точность
Юра (Юрий Александрович)
А есть парочка примеров кода?
К сожалению нет, давно не приходилось с ними работать.
Но общие принципы такие:
1) Весь вывод на экран или отдача внешним сервисам идет с округлением до определенного знака.
2) Все сравнения чисел идут, как написал Иван: - через сравнение модуля разности чисел с "дельтой" - (например той самой погрешностью).
3) Когда делаешь арифметические операции с числами, учитываешь что накапливается погрешность (тут лучше смотреть сами операции, чем уходить в теорию, которая может не пригодиться).
Юра (Юрий Александрович)
Собственно числа с плавающей запятой используются в науке, инженерии, географии, (чуть не забыл: в играх)
В большинстве распространенных остальных областей обходятся без них или можно обойтись без них. При финансовых рассчетах числа с плавающей запятой не используются почти никогда (именно потому что могут дать расхождение в "копейку", а то и больше).
🕷
Илья
Илья
запустил бенчи, разница до 20%
Maks
Хотя возможно это из за преобразования типов еще
Alexander
Dilame
Меня занесло в Go из TypeScript. Сейчас пытаюсь пропатчить кое-что. Мне надо создать новую структуру типа TLSExtension.
Я в GoLand жму на Go To Implementations, выбираю один из вариантов – меня перекидывает на SupportedVersionsExtension.
И я вот никак не могу понять, каким вообще образом SupportedVersionsExtension имплементирует TLSExtension?
У них и интерфейсы разные, и да и указания явного нет, типа
type SupportedVersionsExtension implements TLSExtension.
Может кто-нибудь объяснить что это?) Ну или ссылку кинуть?
Dilame
Dilame
innit?
innit?
whois
innit?
явно это нигде не обозначается
innit?
утиная типизация
Dilame
А можно как-то заставить компилятор следить за тем, чтобы тип имплементировал все методы?
Например, если я изменю интерфейс, чтобы не забыть изменить все типы?
innit?
Артем
Herman
Herman
В рантайме можно проверить