
Kirill
02.12.2017
09:05:13
второй год юзаю

Александр
02.12.2017
09:05:34
Года 4 назад я открывал какойто файлик в архиве eap ide и ежемесячно менял там дату)

Kirill
02.12.2017
09:11:23

Alexey
02.12.2017
09:12:13

Google

Александр
02.12.2017
09:12:57
А 4 года назад вы пользовались идеей?)

Alexey
02.12.2017
09:13:01
А если просто дату на компе менять, работает?

Александр
02.12.2017
09:13:30

Alexey
02.12.2017
09:13:45
Ну года 2 юзаю

Kirill
02.12.2017
09:14:07

Alexey
02.12.2017
09:14:28

Александр
02.12.2017
09:14:40
Ну вот поэтому и не знали) Выживали как могли)
До этого эклипс был, тот еще тормоз

some_random_anonymous
02.12.2017
09:15:32

Alexey
02.12.2017
09:15:56
От, я тоже с эклипса на джаве начинал, жесть ещё та

Александр
02.12.2017
09:15:57
На тот момент он казался офигенным)

Alexey
02.12.2017
09:16:31

xPushkin
02.12.2017
09:19:07

Google


Александр
02.12.2017
09:21:36
Как можно архитектурно зарефакторить такой код?
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)
}
Как не потерять читаемость, но убрать эту громоздкость?)


Alexey
02.12.2017
09:23:28
Я делаю пакет app и пишу там routers handlers и models

Александр
02.12.2017
09:24:21

Alexey
02.12.2017
09:28:26
В main уже просто сервак
Это вообще норм? Потому как мне удобно так, в стиле django


Александр
02.12.2017
09:32:55
Вот так уже проще) По имени метода понятно, что это за кейс
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)
}


Alexey
02.12.2017
09:35:00
А интерфейс на одну сущность?

Александр
02.12.2017
09:35:08

Alexey
02.12.2017
09:36:22
Аа

Александр
02.12.2017
09:36:25

Alexey
02.12.2017
09:37:12
Оу
Зная норм
Просто чтобы подключить ещё приложение, создам пакет
Я сомневался если честн

Mykyta
02.12.2017
09:49:32
если у тебя есть долгоживующий процесс и тебе надо как бы отслеживать его состояние, лучше возвращать структуру с каналами, откуда ты будешь ловить события
и еще с мапами надо осторожно храня в глобальной переменной

Google

Mykyta
02.12.2017
09:51:36
если будешь читать их с двух рутин, получишь гонку

Slach
02.12.2017
09:55:53
а есть какой то быстрый способ посчитать кол-во аллокаций если у меня маленькая функция main
памяти кроме тестов
и кроме GODEBUG=allocfreetrace=1
?

Александр
02.12.2017
09:57:03
Если с маленькой буквы

Alexey
02.12.2017
10:00:31

Mykyta
02.12.2017
10:01:51

Slach
02.12.2017
10:03:51
А atomic? Не подходит?
а конкретно ???
ну вот я учу Го
хочу понять как правильно аллоцировать
написал простейший код
https://play.golang.org/p/WQVXfwWzue
хочу понять сколько в нем аллокаций
запустил GODEBUG=allocfreetrace=1 go run test.go
и получил тонну вывода... и большинство аллокаций вообще не в моем коде =(
как померить правильно?

Александр
02.12.2017
10:07:01
нет у тебя гарантии, что код в твоем пакете не будет читать твою мапу из нескольких рутин
Ну, если честно, эти обработчики обрабатываются в пакете, снаружи нужно только предоставлять данные для обработчика внутри и реагировать на события асинхронно.
С реакцией на события соглашусь, можно каналы давать, но что делать, когда нужно получить данные?
Вот у меня есть GetMessages. Он делает какую-то внутренню бизнес-логику, в середине ему нужно получить сообщения от клиентского кода, из них сформировать структуру и отправить в свой канал. Тут каналы не лишнее использовать?

Alexey
02.12.2017
10:09:13

Sergey
02.12.2017
10:09:46

Александр
02.12.2017
10:10:41
просто дёргаю callback

Oleg
02.12.2017
10:11:38
Ну, если честно, эти обработчики обрабатываются в пакете, снаружи нужно только предоставлять данные для обработчика внутри и реагировать на события асинхронно.
С реакцией на события соглашусь, можно каналы давать, но что делать, когда нужно получить данные?
Вот у меня есть GetMessages. Он делает какую-то внутренню бизнес-логику, в середине ему нужно получить сообщения от клиентского кода, из них сформировать структуру и отправить в свой канал. Тут каналы не лишнее использовать?
памятую , давно кто-то мне говорил, если ты задумываешься о том использовать каналы или нет, то их не надо использовать.

Александр
02.12.2017
10:12:46

Oleg
02.12.2017
10:21:23
я думаю, пока забудьте о них на время, разве-что поробуйте и всё. Там есть что учить, а потом на уровне стандартных пакетов разберётесь как и когда их применять. Как говориться, это ты должен сердцем чуять, когда их применять а когда нет. Усложнить и хелловорлд можно , но зачем? Но эт только моё мнение, у каждого свой путь.)

Александр
02.12.2017
10:22:41
Ну, в сервере для чатов сложно о них забыть) Хочешь-не хочешь, а для внутренней работы сервера они 100% нужны

Mykyta
02.12.2017
10:45:43
Ну, если честно, эти обработчики обрабатываются в пакете, снаружи нужно только предоставлять данные для обработчика внутри и реагировать на события асинхронно.
С реакцией на события соглашусь, можно каналы давать, но что делать, когда нужно получить данные?
Вот у меня есть GetMessages. Он делает какую-то внутренню бизнес-логику, в середине ему нужно получить сообщения от клиентского кода, из них сформировать структуру и отправить в свой канал. Тут каналы не лишнее использовать?
Если тебе совсем надо заинкапсулировать обработчик канала, чтобы, например, не дать его закрыть, можешь создать интерфейс, где будешь отдавать канал только на чтение. Надо максимально пытаться избегать коллбек-лапши а-ля жаваскрипт

Google

Mykyta
02.12.2017
10:47:17
Нет
До го 1.6 чтение из мап было при любых обстоятельства нормально, сейчас же, если в мапу происходит запись, чтение из нее вызовет панику

Александр
02.12.2017
10:51:15
Если тебе совсем надо заинкапсулировать обработчик канала, чтобы, например, не дать его закрыть, можешь создать интерфейс, где будешь отдавать канал только на чтение. Надо максимально пытаться избегать коллбек-лапши а-ля жаваскрипт
В том и прикол, что клиент должен записать туда данные, а не читать, если это будет канал, причём либо синхронно, либо 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)
}

Mykyta
02.12.2017
10:52:03
Не стоит пихать все результаты в один канал, создай два
В один канал ошибки, в другой - удачный результат

Александр
02.12.2017
10:54:25
+ нужно его уведомить, что сейчас нужно туда записать

Mykyta
02.12.2017
10:56:39
какая-то лапша. Можешь описать логику, что за сообщения и с кем ты там обмениваешься?

Александр
02.12.2017
11:03:40
В сокеты прилетает что-то типа json-rpc - например, запрашивают список сообщений.
Сервер должен распарсить запрос, понять, что хочет браузер, и отдать этот список сообщений опять же в определенном формате типа json-rpc
Сами сообщения сервер не хранит, и к базе доступа нет, поэтому нужно это сделать другому (клиентскому) коду, но этот код не должен влиять на сам протокол работы сервера.
У нас несколько проектов, и эти чаты нужны оказались на еще одном проекте. Не хочется с нуля писать сервер и разрабатывать свой протокол обмена с браузером, поэтому то, что реализует протокол, решили выделить в отдельный пакет, а всё взаимодействие с конкретным проектом - это должно быть реализовано уже в конкретном проекте

Admin
ERROR: S client not available

Александр
02.12.2017
11:04:19
Клиенты для ios/android/js есть, их можно переиспользовать, только если протокол не изменится

xPushkin
02.12.2017
11:04:56
Друзья, насколько "костыльно" использовать build тэги с сорцах? В доках на эту тему целая страница, но в коде на гитхабе такое редко встречаются..

Daniel
02.12.2017
11:05:30
Они редко нужны

xPushkin
02.12.2017
11:06:16
Ну вот если я точно знаю, что буду билдить только под linux, то могу вставить чтобы каждый раз не писать GOOS=linux?

Daniel
02.12.2017
11:06:41
Это другое

Александр
02.12.2017
11:07:01

Daniel
02.12.2017
11:07:06
Проще экспорт сделать переменной

Mykyta
02.12.2017
11:08:26
В сокеты прилетает что-то типа json-rpc - например, запрашивают список сообщений.
Сервер должен распарсить запрос, понять, что хочет браузер, и отдать этот список сообщений опять же в определенном формате типа json-rpc
Сами сообщения сервер не хранит, и к базе доступа нет, поэтому нужно это сделать другому (клиентскому) коду, но этот код не должен влиять на сам протокол работы сервера.
У нас несколько проектов, и эти чаты нужны оказались на еще одном проекте. Не хочется с нуля писать сервер и разрабатывать свой протокол обмена с браузером, поэтому то, что реализует протокол, решили выделить в отдельный пакет, а всё взаимодействие с конкретным проектом - это должно быть реализовано уже в конкретном проекте
Получается, что сервер, который обрабатывает с броузера запросы, еще отправляет запрос к третьему серверу и ждет от него ответа?

Александр
02.12.2017
11:09:01
пока не ждёт, но идея такая

Mykyta
02.12.2017
11:10:08

Google

Vladislav
02.12.2017
11:11:10

Mykyta
02.12.2017
11:13:33
Так почему бы не заюзать брокер сообщений? Ну реально выходит, что приходится костылять свой

Александр
02.12.2017
11:16:35
точнее, у на 4 проекта и 4 команды, но чаты пока на 2-х нужны, на 1-м реализованы, но там жёсткая связанность с конкретным проектом

Mykyta
02.12.2017
11:17:52

Vladislav
02.12.2017
11:19:01

Александр
02.12.2017
11:19:14

Vladislav
02.12.2017
11:19:38
Ну сделай в либе функцию установить хэндлер под такое событие и все.

Александр
02.12.2017
11:20:25
Вот я и делаю, говорят хрень какая-то) Маппинги на них пока что

Mykyta
02.12.2017
11:20:53
Ну мы же не видим всю картинку целиком

Александр
02.12.2017
11:22:28
Ну вот я и спрашиваю) Тут client.GetChatMessages(event) - это кастомный обработчик
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)
}

Vladislav
02.12.2017
11:23:19

Александр
02.12.2017
11:23:28
А с клиента скорее всего будет server.handler(action, handler)
Ну вообще, да, так http и делает
type ServeMux struct {
mu sync.RWMutex
m map[string]muxEntry
hosts bool // whether any patterns contain hostnames
}
//...
mux.m[pattern] = muxEntry{explicit: true, h: handler, pattern: pattern}

Sergey
02.12.2017
12:43:31
много читателей не приводит к панике, к панике приводит много писателей
хотя, нет, я не прав, два читателя при одновременном доступе тоже приведут к панике если есть запись

Daniel
02.12.2017
15:10:46

Anatoliy
02.12.2017
15:11:25
Народ, а как можно сделать анонимно что-то вроде:
res := Result{
Status: status,
Result: H{
"token": tokenString,
},
Error: error,
}
type Result struct {
Status bool `json:"status"`
Error string `json:"error,omitempty"`
Result map[string]interface{} `json:"result,omitempty"`
}
type H map[string]interface{}
Что бы не потребовалось type H делать?

Daniel
02.12.2017
15:12:19
этот код не должен компиляться