Александр
да
Anonymous
Спасибо
Anonymous
Теперь имею представление как это реализовать.
Anonymous
когда клиент подключается к ws, ассоциированная с клиентом рутина начинает слушать канал уведомлений для юзера. как только туда что-то приходит, рутина посылает это в сокет клиенту
Anonymous
Не реклама
Anonymous
Видели?
Anonymous
Alexey Troyanov: http://xidea.online/
Anonymous
Лицензировать любой продукт jetbrains
Anonymous
Интересно с goland сработает?
Александр
Уже несколько лет назад появились такие сервера. Но лучше купить или получить бесплатно, если есть opensource-продукт
Kirill
еще студ лицухи есть)
Anonymous
Ну так goland триал только? Я вот pycharm качаю CE
Kirill
у jetBrains
Kirill
второй год юзаю
Александр
Года 4 назад я открывал какойто файлик в архиве eap ide и ежемесячно менял там дату)
Александр
А 4 года назад вы пользовались идеей?)
Anonymous
А если просто дату на компе менять, работает?
Александр
А если просто дату на компе менять, работает?
Кажется, нет. Там был xml, где указана дата выпуска и когда сдохнет триалка
Anonymous
Ну года 2 юзаю
Kirill
А 4 года назад вы пользовались идеей?)
4 года назад я на си лабы только писать начал😁
Александр
Ну вот поэтому и не знали) Выживали как могли)
Александр
До этого эклипс был, тот еще тормоз
Anonymous
От, я тоже с эклипса на джаве начинал, жесть ещё та
Александр
На тот момент он казался офигенным)
Anonymous
😂👍
Александр
Как можно архитектурно зарефакторить такой код? switch incomeEvent.Action { case models.CALL: switch incomeEvent.Method { case models.GET: getRequestHandler(incomeEvent) case models.POST: postRequestHandler(incomeEvent) } case models.SUBSCRIBE: switch incomeEvent.Method { case models.POST: postSubscribeHandler(incomeEvent) } } P.S. Внутри этих методов еще switch. Полиморфизм? Регистрация колбеков? Мб еще варианты есть? В golang новичок. Такая вложенность, еще и раскиданная по файлам мне не нравится
Попробовал сделать. Мне не нравится, много действий нужно сделать. Но сам switch стал хотя бы читаемый type IncomingHandlerPool struct { messages MessagesHandler } type MessagesHandler interface { GetMessages(event models.IncomeEvent) GetChatsCount(event models.IncomeEvent) SendMessage(event models.IncomeEvent) MarkRead(event models.IncomeEvent) NotifyTyping(event models.IncomeEvent) } const ( requestMessages = "request_messages" requestChatsCount = "request_chats_count" sendMessage = "send_message" markRead = "mark_read" notifyTyping = "notify_typing" ) var ( handlerKeys = map[string]string{ requestMessages: handleKey(models.CALL, models.GET, models.TYPE_MESSAGE), requestChatsCount: handleKey(models.CALL, models.GET, models.TYPE_COUNTS), sendMessage: handleKey(models.CALL, models.POST, models.TYPE_MESSAGE), markRead: handleKey(models.CALL, models.POST, models.TYPE_READ), notifyTyping: handleKey(models.CALL, models.POST, models.TYPE_TYPING), } ) // ... switch handleKey(incomeEvent.Action, incomeEvent.Method, incomeEvent.Type) { case requestMessages: handlers.messages.GetMessages(incomeEvent) case requestChatsCount: handlers.messages.GetChatsCount(incomeEvent) case sendMessage: handlers.messages.SendMessage(incomeEvent) case markRead: handlers.messages.MarkRead(incomeEvent) case notifyTyping: handlers.messages.NotifyTyping(incomeEvent) } // ... func handleKey(a int, m string, t string) string { return fmt.Sprintf("%s-%s-%s", a, m, t) }
Александр
Как не потерять читаемость, но убрать эту громоздкость?)
Anonymous
Я делаю пакет app и пишу там routers handlers и models
Александр
Я делаю пакет app и пишу там routers handlers и models
И как это уменьшит громоздкость?
Anonymous
В main уже просто сервак
Anonymous
Это вообще норм? Потому как мне удобно так, в стиле django
Anonymous
И как это уменьшит громоздкость?
Никак, просто стиль такой
Александр
Вот так уже проще) По имени метода понятно, что это за кейс type IncomingHandlers struct { messages MessagesHandler } type MessagesHandler interface { GetMessages(event models.IncomeEvent) GetChatsCount(event models.IncomeEvent) SendMessage(event models.IncomeEvent) MarkRead(event models.IncomeEvent) NotifyTyping(event models.IncomeEvent) } var ( handlers = IncomingHandlers{ messages: &MessagesServerHandler{}, } ) // ... switch handleKey(incomeEvent.Action, incomeEvent.Method, incomeEvent.Type) { case handleKey(models.CALL, models.GET, models.TYPE_MESSAGE): handlers.messages.GetMessages(incomeEvent) case handleKey(models.CALL, models.GET, models.TYPE_COUNTS): handlers.messages.GetChatsCount(incomeEvent) case handleKey(models.CALL, models.POST, models.TYPE_MESSAGE): handlers.messages.SendMessage(incomeEvent) case handleKey(models.CALL, models.POST, models.TYPE_READ): handlers.messages.MarkRead(incomeEvent) case handleKey(models.CALL, models.POST, models.TYPE_TYPING): handlers.messages.NotifyTyping(incomeEvent) }
Anonymous
А интерфейс на одну сущность?
Александр
Александр
А интерфейс на одну сущность?
не, там несколько сущностей будет
Anonymous
Аа
Anonymous
Оу
Anonymous
Зная норм
Anonymous
Просто чтобы подключить ещё приложение, создам пакет
Anonymous
Я сомневался если честн
Nikita
если у тебя есть долгоживующий процесс и тебе надо как бы отслеживать его состояние, лучше возвращать структуру с каналами, откуда ты будешь ловить события
Nikita
и еще с мапами надо осторожно храня в глобальной переменной
Nikita
если будешь читать их с двух рутин, получишь гонку
Slach
а есть какой то быстрый способ посчитать кол-во аллокаций если у меня маленькая функция main памяти кроме тестов и кроме GODEBUG=allocfreetrace=1 ?
Александр
если у тебя есть долгоживующий процесс и тебе надо как бы отслеживать его состояние, лучше возвращать структуру с каналами, откуда ты будешь ловить события
А предоставлять из пакета в клиентский код каналы нормально вообще?) Я просто хз, не хотелось бы применять там, где не надо
Александр
и еще с мапами надо осторожно храня в глобальной переменной
Если глобальный мап в отдельном пакете - он доступен только пакету ж
Александр
Если с маленькой буквы
Nikita
Если глобальный мап в отдельном пакете - он доступен только пакету ж
нет у тебя гарантии, что код в твоем пакете не будет читать твою мапу из нескольких рутин
Slach
А atomic? Не подходит?
а конкретно ??? ну вот я учу Го хочу понять как правильно аллоцировать написал простейший код https://play.golang.org/p/WQVXfwWzue хочу понять сколько в нем аллокаций запустил GODEBUG=allocfreetrace=1 go run test.go и получил тонну вывода... и большинство аллокаций вообще не в моем коде =( как померить правильно?
Александр
нет у тебя гарантии, что код в твоем пакете не будет читать твою мапу из нескольких рутин
Ну, если честно, эти обработчики обрабатываются в пакете, снаружи нужно только предоставлять данные для обработчика внутри и реагировать на события асинхронно. С реакцией на события соглашусь, можно каналы давать, но что делать, когда нужно получить данные? Вот у меня есть GetMessages. Он делает какую-то внутренню бизнес-логику, в середине ему нужно получить сообщения от клиентского кода, из них сформировать структуру и отправить в свой канал. Тут каналы не лишнее использовать?
Александр
Александр
Александр
просто дёргаю callback
Александр
памятую , давно кто-то мне говорил, если ты задумываешься о том использовать каналы или нет, то их не надо использовать.
Я в golang новичок (3 недели), и паттернов каких-то именно для go у меня еще не набралось, поэтому вот и спрашиваю, как что лучше)
Oleg
я думаю, пока забудьте о них на время, разве-что поробуйте и всё. Там есть что учить, а потом на уровне стандартных пакетов разберётесь как и когда их применять. Как говориться, это ты должен сердцем чуять, когда их применять а когда нет. Усложнить и хелловорлд можно , но зачем? Но эт только моё мнение, у каждого свой путь.)
Александр
Ну, в сервере для чатов сложно о них забыть) Хочешь-не хочешь, а для внутренней работы сервера они 100% нужны
Nikita
Нет
До го 1.6 чтение из мап было при любых обстоятельства нормально, сейчас же, если в мапу происходит запись, чтение из нее вызовет панику
Александр
Если тебе совсем надо заинкапсулировать обработчик канала, чтобы, например, не дать его закрыть, можешь создать интерфейс, где будешь отдавать канал только на чтение. Надо максимально пытаться избегать коллбек-лапши а-ля жаваскрипт
В том и прикол, что клиент должен записать туда данные, а не читать, если это будет канал, причём либо синхронно, либо wg какой-нибудь func (c *MessagesServerHandler) GetMessages(event models.IncomeEvent) { response, err := client.GetChatMessages(event) if err != nil { resultChan <- event.CreateResult(nil, err.Error()) return } resultChan <- event.CreateResult(response, nil) }
Nikita
Не стоит пихать все результаты в один канал, создай два
Nikita
В один канал ошибки, в другой - удачный результат
Александр
Не стоит пихать все результаты в один канал, создай два
До этого я еще доберусь, тут много интересного написано) Что делать с получением сообщений? Давать канал клиенту, чтобы он туда записал сообщения?
Александр
+ нужно его уведомить, что сейчас нужно туда записать
Nikita
какая-то лапша. Можешь описать логику, что за сообщения и с кем ты там обмениваешься?
Александр
В сокеты прилетает что-то типа json-rpc - например, запрашивают список сообщений. Сервер должен распарсить запрос, понять, что хочет браузер, и отдать этот список сообщений опять же в определенном формате типа json-rpc Сами сообщения сервер не хранит, и к базе доступа нет, поэтому нужно это сделать другому (клиентскому) коду, но этот код не должен влиять на сам протокол работы сервера. У нас несколько проектов, и эти чаты нужны оказались на еще одном проекте. Не хочется с нуля писать сервер и разрабатывать свой протокол обмена с браузером, поэтому то, что реализует протокол, решили выделить в отдельный пакет, а всё взаимодействие с конкретным проектом - это должно быть реализовано уже в конкретном проекте
Александр
Клиенты для ios/android/js есть, их можно переиспользовать, только если протокол не изменится
Chebyrash
Друзья, насколько "костыльно" использовать build тэги с сорцах? В доках на эту тему целая страница, но в коде на гитхабе такое редко встречаются..