Пікірлер
@young_flex3077
@young_flex3077 4 сағат бұрын
41:40 вранье чистой воды, если ошибетесь на собеседовании, даже если опечатаетесь, не важно как быстро вы исправитесь, в фидбеке напишут, что задачу не решил
@young_flex3077
@young_flex3077 5 сағат бұрын
Зачем позвали школьников на роль ведущих 😂😂😂😂😂😂😂😂😂 они ж даже разрешение трансляции нормальное выставить не смогли 😂😂😂😂😂😂😂😂😂
@anton6643
@anton6643 Күн бұрын
Вторая задача разве это не обычный обход графа в ширину?
@ИнтернетСпасётМир
@ИнтернетСпасётМир 2 күн бұрын
Как-то так, например: package main import ( "fmt" "slices" ) // composeStopToBusMap describes what buses arrive to every stop // for routes := [][]int{{1, 2, 7}, {3, 6, 7}} => map[1:[0] 2:[0] 3:[1] 6:[1] 7:[0 1]] func composeStopToBusMap(routes [][]int) map[int][]int { stopToBus := make(map[int][]int, len(routes)) for bus, busRoute := range routes { for _, stop := range busRoute { stopToBus[stop] = append(stopToBus[stop], bus) } } return stopToBus } // Use BFS to find minimum number of buses to reach the target stop func detect(routes [][]int, source int, target int, sb map[int][]int) int { var lvl int = 0 // This is zero level q := []int{source} // We start with the source stop at zero level skipBuses := map[int]struct{}{} // Store processed buses skipStops := map[int]struct{}{} // Store processed stops for len(q) > 0 { nextQ := []int{} // Next level queue with stops for _, checkingStop := range q { skipStops[checkingStop] = struct{}{} // Collect stops for the queue of the next level. for _, bus := range sb[checkingStop] { _, ok := skipBuses[bus] if ok { continue } skipBuses[bus] = struct{}{} for _, st := range routes[bus] { if _, ok = skipStops[st]; !ok { if st == target { return lvl + 1 } nextQ = append(nextQ, st) } } } } // We didn't find target stop during search at this level, // Since we have collected some stops for the new queue, // then let's search again for a target stop at the next level. lvl++ slices.Sort(nextQ) q = slices.Compact(nextQ) } return -1 } func numBusesToDestination(routes [][]int, source int, target int) int { // Build graph where each stop is associated with buses that arrive to it sb := composeStopToBusMap(routes) // Don't need to travel when source and target is the same if source == target { return 0 } // Check if source and target stops are among visited by buses _, ok := sb[source] if !ok { return -1 } _, ok = sb[target] if !ok { return -1 } return detect(routes, source, target, sb) } func main() { routes2 := [][]int{{7, 12}, {4, 5, 15}, {6}, {15, 19}, {9, 12, 13}} fmt.Println(numBusesToDestination(routes2, 15, 12)) routes5 := [][]int{{1, 2, 3}, {3, 4, 5, 6}, {6, 7}, {6, 7, 8}, {7, 11}, {8, 9, 10}} fmt.Println(numBusesToDestination(routes5, 3, 10)) }
@Prof-Shor
@Prof-Shor 2 күн бұрын
Паша, хорош хлебать)))
@artemkas4191
@artemkas4191 3 күн бұрын
Спасибо большое за такой хороший пример решения более-менее реалистичного задания! А вот если бы было желание вынести часть логики, не связанной с доступом к данным (например, проверка пересечений интервалов бронирования и времени работы мастерской) из репозитория на слой ApplicationService/UsesCases, то как в этом случае быть с транзакциями - добавлять АПИ транзакций (а-ля TransactionManager) и оборачивать в транзакцию несколько запросов репозитория уже на уровне AplicationService?
@SeverSiter1
@SeverSiter1 Күн бұрын
Да.
@AkaEretic
@AkaEretic 4 күн бұрын
Супер! Ага с append вообще надо быть очень внимательным
@maxsmeh
@maxsmeh 8 күн бұрын
Когда смотрю мок интервью, чувствую себя Светлаковым из нашей раши, который смотрит телек
@АлександрРаков-м7п
@АлександрРаков-м7п 13 күн бұрын
func tee будет читать синхронно в вашем решении, и если произойдет блокировка одного из каналов на серверной стороне, второй будет его ждать. Для реализации асинхронного решения: func tee(in <-chan int) (a <-chan int, b <-chan int) { a = make(<-chan int) b = make(<-chan int) buff1 := make([]int, 0, 5) buff2 := make([]int, 0, 5) for v := range in { buff1 = append(buff1, v) buff2 = append(buff2, v) } go func() { defer close(a) for _, v := range buff1 { a <- v } }() go func() { defer close(b) for _, v := range buff2 { b <- v } }() return a, b }
@ИнтернетСпасётМир
@ИнтернетСпасётМир 12 күн бұрын
Оно не асинхронное - в нём надо ждать закрытия канала in.
@thenexia111
@thenexia111 13 күн бұрын
func tee(ch1 <-chan int) (ch2 chan int, ch3 chan int) { ch2 = make(chan int) ch3 = make(chan int) go func() { defer close(ch2) defer close(ch3) for num := range ch1 { ch2 <- num ch3 <- num } }() return }
@ИнтернетСпасётМир
@ИнтернетСпасётМир 12 күн бұрын
Не будет работать, если чтение происходит только из одного канала.
@ИнтернетСпасётМир
@ИнтернетСпасётМир 14 күн бұрын
Решение для задачи tee будет работать только если вы планируете последовательно читать из a и b канала приходящее значение, а если вы хотите послать в in 1,3,5 и прочитать эти значения только из одного канала, тогда цикл чтения из канала in зависнет на записи в другой канал, который не читается. Если добавить default, тогда канал который не читается, будет пропускаться. Но это решение не подходит, потому что мы можем захотеть прочитать из второго канала значения 1,3,5 после того, как эти значения были прочитаны первым каналом. Для решения такой задачи можно попробывать записывать каждое значение в оба канала в отдельной горутине, но так потеряется последовательность значений, потому что горутины исполнятся в случайном порядке. func tee(in <-chan any) (<-chan any, <-chan any) { a := make(chan any) b := make(chan any) go func() { defer close(a) defer close(b) wg := sync.WaitGroup{} for v := range in { wg.Add(1) v1 := v a1, b1 := a, b go func() { defer wg.Done() for range [2]int{} { select { case a1 <- v1: a1 = nil case b1 <- v1: b1 = nil } } }() } wg.Wait() }() return a, b }
@alexandreabramtsev9160
@alexandreabramtsev9160 14 күн бұрын
Мне кажется, в первом примере строки 65 и 70 лишние. Я за то чтобы был мьютекс чуть длиннее - с 63 строки по 72. А так - интересная тема (как и веселый нэйминг xD)
@mistandok
@mistandok 14 күн бұрын
а sync.Once нельзя использовать по условиям задачи?
@Jonatanail
@Jonatanail 14 күн бұрын
прикольная задача, на закрытие канала не нужен мьютекс, у него там под капотом свой есть
@MrLotrus
@MrLotrus 18 күн бұрын
1:04:00 Как ни странно говорят о таких вещах как секционирование, но ни разу не слышал про нормализацию таблиц в мок собесах. А ведь это база). И из вопроса непонятно как именно стоит разбивать таблицу. Может там 1000 колонок.
@MrLotrus
@MrLotrus 18 күн бұрын
1:00:00 По-моему правильней действительно посмотреть через запросы какая селективность. Вот так предполагая по диапазону есть риск ошибиться. Ведь записи по этим полям могут быть распределены неравномерно
@MrLotrus
@MrLotrus 18 күн бұрын
50:00 hash индекс имеет много нюансов и ограничений. Большой вопрос стоит ли его использовать ради возможного мизерного выигрыша
@thre-c7b
@thre-c7b 19 күн бұрын
самый бестолковый собес из всех что я встречал кто то из него вообще понял какие задачи на го этот парень может сделать?
@KeibyBigBalls
@KeibyBigBalls 21 күн бұрын
Даня красавчик! Акиму спасибо за содержательное интервью, за пояснения и рекомендации к изучению
@blu3h4t
@blu3h4t 22 күн бұрын
ты знаешь что имеет аптаймы 9999 да? и это не го
@Andrii-mt8ef
@Andrii-mt8ef 23 күн бұрын
вкатунов с быдлокодинга на пхп тяжело на нормальные языки перетащить не просто так чтобы они выучили синтаксис и функции стандартной библиотеки а имели глубокие знания не только о го но и о общем программировании которое не применимо к пхп например потоки, tcp/udp и сисколлы - тестовые на го я бы делал не на написание каких-то рудиментарных рест апи а на что-то более интересное типа задач на конкурентность
@MouseSilent
@MouseSilent 23 күн бұрын
Зашел на видео увидев превью - "как я перешел с PHP на golang", я думаю, что ответ на этот вопрос такой - "Отлично перешел!". Так же можно было назвать видео "как я перешел с PHP на любой другой язык?" - "Замечательно перешел!!"
@Tosha.V
@Tosha.V 23 күн бұрын
научите меня бесплатно, очень хочется писать приложения работающие годами)
@3ombieautopilot
@3ombieautopilot 23 күн бұрын
Отличный видос! Будут ли еще задачи с собеседований? Вы отличный наставник.
@ipavlyukov
@ipavlyukov 23 күн бұрын
Конечно, впереди также видео с обзором неочевидных Баз Данных!
@Andrii-mt8ef
@Andrii-mt8ef 23 күн бұрын
@@ipavlyukov неочевидных в плане подводных камней? например различия в имплементации SQL? или какую-то диковинку вроде непопулярных баз данных? расскажите лучше про S3 во втором случае и про разные фичи вроде CAS
@andreybalatsan9336
@andreybalatsan9336 24 күн бұрын
Как меня порадовал смех, когда и nginx упал
@ivantimofeev2515
@ivantimofeev2515 24 күн бұрын
Ну к слову в первой задаче сейчас в Go 1.23 это уже не так
@buginsystem8925
@buginsystem8925 25 күн бұрын
А где-то можно почитать подробней про использование кэшей CPU при переборе слайсов/массивов? Об этом говорят на 16:20, не смог быстро нагуглить на английском
@Nikolai-k7h
@Nikolai-k7h 29 күн бұрын
Задачка крутая, вопросы норм. Но по устройству мапы слишком упарываетесь, как будто эти знания каждый день в работе используете.
@thenexia111
@thenexia111 Ай бұрын
Хорошо объясняешь на самом деле. Но челы пришли смотреть как решать задачки на многопоточку без минимальной базы, поэтому много разжевывания того, что есть везде
@lisov1k492
@lisov1k492 Ай бұрын
с кайфом
@MrLotrus
@MrLotrus Ай бұрын
Хорошая задачка. И асинхронность, и немного алгоритмы.
@Ярослав-е2ш
@Ярослав-е2ш Ай бұрын
Почему дедлок этр паника?
@Ярослав-е2ш
@Ярослав-е2ш Ай бұрын
Вроде бы, clear(batch) не будет работать, он все значения к зиро вэлью приведёт просто, и длина не станет равна нулю
@Ярослав-е2ш
@Ярослав-е2ш Ай бұрын
Для мап clear удаляет элементы
@davidikus29
@davidikus29 Ай бұрын
Ссылку на гитхаб конечно никто не оставил
@oo_ilin
@oo_ilin Ай бұрын
В последней задаче mergeChannel решение с worker pool не корректно относительно первичной постановки задачи. В первом решении каналы читались все одновременно и как только в них поступали данные, они сразу вылетали в выходной канал. Как только канал закрывался, он переставал слушаться, но остальные продолжали одновременно сливать данные в выходной канал. Во втором решении мы по факту слушаем первых пять каналов и если никто из них не будет закрываться, то значения из всех остальных каналов не будут мержиться никогда. А это уже не мерж каналов. Так что второе решение не корректно с точки зрения бизнес логики
@thestrikem
@thestrikem Ай бұрын
В условии не было обговорено, мы допускаем тот факт, что сейчас одновременно не считываем из всех каналов, которые нам передаются, потому что просто физически не можем это сделать, т.к. каналов слишком много. Релевантно будет повысить константу с 5 на большее число в продакшн варианте, в видео просто обсуждался воркер пул в контексте этой задачи. Здесь, к сожалению, мы жертвуем тем, что не читаем все каналы одновременно ради того, чтобы не взорваться и итеративно все проработать, поэтому где-то на той стороне допускаем, что какие-то горутины-отправители в канал припаркуются в ожидании прослушивания. Этот трейдофф стоило упомянуть в решении, согласен
@nikitayaskevich813
@nikitayaskevich813 Ай бұрын
Крутое и детальное объяснение, спасибо.
@alexzav1327
@alexzav1327 Ай бұрын
Видео очень полезное, иногда возвращаюсь к нему, чтобы что-то вспомнить.
@thestrikem
@thestrikem Ай бұрын
Кстати, можно глянуть такой же ультимативный видео-ролик по слайсам у меня на канале)
@leshi_1
@leshi_1 Ай бұрын
Совсем не читает 😂
@dmitrykorolev4943
@dmitrykorolev4943 Ай бұрын
Илья из завтра, после прогули, видать начал готовить видео про тесты)) Уже когда-то давно видел твоё видео по теме go, у тебя хорошо получается объяснять, т.ч и про тесты будет интересно посмотреть! Удачи!
@lukin_io
@lukin_io Ай бұрын
@Эйч Навыки - менторская программа Вы б шарили исходники тех задач, которые задаете? :-) я что-то на ya.cc не нашел по той ссылке что в видео.
@QazaqCode
@QazaqCode Ай бұрын
Все зависит от details, а details зависит от fabric 😂😂
@staspanyukov4822
@staspanyukov4822 Ай бұрын
DDD на мидла на тестовое.. никто не оценит, многие даже и не поймут… А так красиво все делаешь, явно не мидл)
@ChorumTheDevourer
@ChorumTheDevourer Ай бұрын
"Какого-то доктора". Далеки не хотят привлекать внимание только одного Доктора. "Доктор? Доктор Кто?"
@MrPaisho
@MrPaisho Ай бұрын
ещё замечу, что если в данном случае констраинт подходит, то в других случаях, когда не получится задать ограничения, можно использовать select for update
@ipavlyukov
@ipavlyukov Ай бұрын
Верно! Есть ситуации, когда можно использовать другой способ блокировки, а именно SELECT FOR UPDATE. В нашей же ситуации, он неприменим, поскольку в момент проверки в БД еще нет строки под блокировку.
@MrPaisho
@MrPaisho Ай бұрын
Есть воркшоп блокироваться можно об него
@ipavlyukov
@ipavlyukov Ай бұрын
@@MrPaisho Согласен, это отличный вариант, если мы готовы к тому, что заблокируем весь склад для конкурентных бронирований. Немножко снижаем RPS, зато упрощаем код и запросы к БД!
@MrPaisho
@MrPaisho Ай бұрын
@@ipavlyukov а как работает констраит? Он, насколько я понимаю блочит всю таблицу, разве нет?
@ipavlyukov
@ipavlyukov Ай бұрын
@@MrPaishoв том то и дело, что нет. Блокировка частичная, благодаря индексу.
@MrPaisho
@MrPaisho Ай бұрын
я правильно понимаю, что в доменной модели должны быть сущности, которые все используют, а по факту получается, что в том виде, котором они есть, они нафиг никому не сдались? Какая-то шизофрения эти паттерны.
@dpnpd
@dpnpd Ай бұрын
В общем и целом все используют go-project-layout и на него натягивают трехслойную архитектуру, сдались тогда когда в бизнесе много человек, чтобы не писать отсебятину и все было понятно, а не терять время на изучения новых патернов
@stanton_arch
@stanton_arch Ай бұрын
"Далеки" всё никак не угомонятся🤣
@artie5913
@artie5913 Ай бұрын
43:10 разве такая проверка достаточна? Что если ваше новое бронирование будет содержать внутри себя время уже существующего?
@ipavlyukov
@ipavlyukov Ай бұрын
Верно, нужно это условие проверять в обе стороны. То есть и для нового отрезка и для старого. Именно потому, что условие становится громоздким, мы дальше используем готовый оператор OVERLAPS.
@insentijke
@insentijke Ай бұрын
56:18 канал из тикера возвращается же напрямую (ticker.C), метода .C() у time.Ticker нет