Sergey
привет, суслики, столкнулся с такой задачей на проекте, нужен совет: потребители моего сервиса хотят получать ответ со структурой, перечень полей в которой они могут задать в запросе (а-ля graphql). Получать данные они будут списком потенциально до 10к (!) записей. Собственно, два вопроса: 1) Не совсем по go, но про (чистую) архитектуру: на каком уровне мне эти поля отделять? по-идее это уровень представления, то есть из репозитория формирую полную модель, а уже в dto собираю новую структуру только с тем, чем нужно. Но тут момент с производительностью: модель жирная, и получается что из базы выгребается все, а используется лишь малая часть данных. С другой стороны, селект на уровне ДБ даст возможность получить неполную модель из репозитория и случайно использовать ее там, где нужны все данные. Может описать отдельную модель для этого кейса (read model из DDD - это оно?)? 2) Если уж и делать как описал изначально (с перебрасыванием модели в dto), как лучше всего реализовать отбор полей? Самый очевидный вариант - маршалить исходник, размаршалить в map[string]interface{}, создать вторую такую же мапу, перекинуть из первой во вторую только то, что запросили, и потом ее уже маршалить - а можно более эффективно? Старался кратко написать, надеюсь, понятно
Alex
привет, суслики, столкнулся с такой задачей на проекте, нужен совет: потребители моего сервиса хотят получать ответ со структурой, перечень полей в которой они могут задать в запросе (а-ля graphql). Получать данные они будут списком потенциально до 10к (!) записей. Собственно, два вопроса: 1) Не совсем по go, но про (чистую) архитектуру: на каком уровне мне эти поля отделять? по-идее это уровень представления, то есть из репозитория формирую полную модель, а уже в dto собираю новую структуру только с тем, чем нужно. Но тут момент с производительностью: модель жирная, и получается что из базы выгребается все, а используется лишь малая часть данных. С другой стороны, селект на уровне ДБ даст возможность получить неполную модель из репозитория и случайно использовать ее там, где нужны все данные. Может описать отдельную модель для этого кейса (read model из DDD - это оно?)? 2) Если уж и делать как описал изначально (с перебрасыванием модели в dto), как лучше всего реализовать отбор полей? Самый очевидный вариант - маршалить исходник, размаршалить в map[string]interface{}, создать вторую такую же мапу, перекинуть из первой во вторую только то, что запросили, и потом ее уже маршалить - а можно более эффективно? Старался кратко написать, надеюсь, понятно
Суслики, хахаха, а почему же Графкой и не отдать все? 10к не так и много
Sergey
у нас все работает по http апи или grpc, не хочется вносить еще один инструмент для одного эндпоинта
Igor
всем привет. есть у кого-нибудь пример как записывать в 3 связанные таблицы postgresql, через транзакцию ? пакеты "database/sql" "github.com/lib/pq" В две таблицы пишет нормально. Пробовал писать в третью таблицу , но получаю ошибки. Как правильно написать? 1) pq: relation "order_carrier" does not exist _, err = tx.ExecContext( ctx, "INSERT INTO order_carrier(order_key_id, carrier_id, days, description, point_id) VALUES($1, $2, $3, $4, $5)", lastInsertId, o.Carrier.CarrierId, o.Carrier.Days, o.Carrier.Description, o.Carrier.PointId, ) if err != nil { return } 2) Вызывает panic order_1 | panic: runtime error: invalid memory address or nil pointer dereference order_1 | [signal SIGSEGV: segmentation violation code=0x1 addr=0x38 pc=0x8c1eff] order_1 | order_1 | goroutine 49 [running]: order_1 | sync.(*RWMutex).RLock(...) order_1 | /usr/local/go/src/sync/rwmutex.go:48 stmt2, _ := tx.PrepareContext(ctx, pq.CopyIn("order_carrier", "order_key_id", "carrier_id", "days", "description", "point_id")) _, err = stmt2.ExecContext(ctx, lastInsertId, o.Carrier.CarrierId, o.Carrier.Days, o.Carrier.Description, o.Carrier.PointId) if err != nil { return } _, err = stmt2.ExecContext(ctx) if err != nil { return } stmt2.Close()
Alexey
всем привет. есть у кого-нибудь пример как записывать в 3 связанные таблицы postgresql, через транзакцию ? пакеты "database/sql" "github.com/lib/pq" В две таблицы пишет нормально. Пробовал писать в третью таблицу , но получаю ошибки. Как правильно написать? 1) pq: relation "order_carrier" does not exist _, err = tx.ExecContext( ctx, "INSERT INTO order_carrier(order_key_id, carrier_id, days, description, point_id) VALUES($1, $2, $3, $4, $5)", lastInsertId, o.Carrier.CarrierId, o.Carrier.Days, o.Carrier.Description, o.Carrier.PointId, ) if err != nil { return } 2) Вызывает panic order_1 | panic: runtime error: invalid memory address or nil pointer dereference order_1 | [signal SIGSEGV: segmentation violation code=0x1 addr=0x38 pc=0x8c1eff] order_1 | order_1 | goroutine 49 [running]: order_1 | sync.(*RWMutex).RLock(...) order_1 | /usr/local/go/src/sync/rwmutex.go:48 stmt2, _ := tx.PrepareContext(ctx, pq.CopyIn("order_carrier", "order_key_id", "carrier_id", "days", "description", "point_id")) _, err = stmt2.ExecContext(ctx, lastInsertId, o.Carrier.CarrierId, o.Carrier.Days, o.Carrier.Description, o.Carrier.PointId) if err != nil { return } _, err = stmt2.ExecContext(ctx) if err != nil { return } stmt2.Close()
а тебе точно там нужна транзакция? не рассматривал CTE ?
Igor
а тебе точно там нужна транзакция? не рассматривал CTE ?
честно говоря не знаю про CTE ) транзакция думаю оптимальна, чтобы сделать ролбек если не удалось записать в одну из таблиц
Igor
для начала проверь везде ошибки
согласен. вот пытаюсь понять в чем ошибка)
Alexey
честно говоря не знаю про CTE ) транзакция думаю оптимальна, чтобы сделать ролбек если не удалось записать в одну из таблиц
CTE выполняется в одной транзакции и откатывает, если в одну из таблиц не записалось, с одним но - CTE не гарантирует порядок в котором будут добавлены записи в бд
Beta
Ребят, всем привет, что лучше использовать стандартный логгер от джина или подключить какую-нибудь стороннюю либу?
Null
🛠 Инструменты для управления уязвимостями в Go-проекте на текущий момент. ➡️ Читать ⚙️ Vulnerability database @Golang_google
anhckie
есть тут люди, работавшие с fiber? вопрос максимально тупой - как им сделать хттп-запрос))
anhckie
читаю доку и не вижу ответа
anhckie
т.е. мне нужно со своей аппки дернуть сторонний api
Patamen
есть тут люди, работавшие с fiber? вопрос максимально тупой - как им сделать хттп-запрос))
Из базовых моментов 1. Можно юзнуть fasthttp(на нём фибер и так работает, хехе) и просто написать raw запрос 2. Попробовать потыкать в redirect - fiber.Ctx позволяет это сделать
Patamen
3. Самый мега база - написать буквальный http.NewRequest и фигануть клиентиком
Patamen
https://docs.gofiber.io/api/client
Через него на самом очень странно работать кстати
anhckie
https://docs.gofiber.io/api/client
читал. там нет примеров и шо такое AcquireAgent тоже не ясно, импортов нет нкаких
anhckie
anhckie
короче файбер из коробки адекватно не может слать запросы, я так понимаю
Patamen
а что лучше было бы? фастхттп или просто хттп)
В идеале попробовать таки разобраться с клиентом
anhckie
я, собсно, потому и решил сюда обратить, ибо перечитал этого клиента, а как хоть что-то у него вызвать - вообще не въезжаю. импорты не описаны, ide не понимает примеров
anhckie
типа мож я что-то упускаю
Patamen
Напрямую используется функция в тестировании AcquireAgent
Patamen
fiber.AcquireAgent()
anhckie
господи боже мой блеать
anhckie
я дебил
anhckie
занавес
anhckie
спасибо за помощь))))
Patamen
anhckie
еще сразу спрошу - что за первый параметр? не понимаю его задачи. есть урл, есть тело запроса, а это не пойму..
Patamen
По сути по такому же алгоритму, как работа с любым декодером
anhckie
логично. теперь точно понятно стало) еще раз большое спасибо
Anton
ребят, чот не вдупляю, что не так, мб со стороны будет видно суть: есть хендлер, на который в multipart/form приходит файлик .csv забираю его через r.FormFile(). читаю его через encoding/csv (csv.NewReader => Read() ) - все классно, строки видит, всё читает далее создаю файл через f, err := os.Create далее io.Copy (было), переделал на чтение чанками через f.Read() (тот файл, что был в мультиформе) и пишу потом результат через Write в созданный файл . но байты, он, собственно и не пишет в созданный f. (bytes = 0 от функции Write, err = nil) в чем может быть проблема, куда рыть?
anhckie
еще вопрос возник. как понимать, где конкретно случилась ошибка? 2022/09/08 14:01:08 start 14:01:08 | 500 | 0s | 127.0.0.1 | GET | /test2 | runtime error: invalid memory address or nil pointer dereference вот весь код) handler.Get("test2", func(c *fiber.Ctx) error { a := fiber.AcquireAgent() log.Println("start") code, body, err := a.Get(nil, "http://google.com/foo/bar") log.Println(err) log.Println("get" + string(body)) log.Println(code) log.Println("end") return c.SendString("ok") })
anhckie
может, какие-то инструменты есть или только принтовать и код перечитывать?
anhckie
может, какие-то инструменты есть или только принтовать и код перечитывать?
ну и да, вопрос со звёздочкой - так а что пошло не так?))..
Patamen
ну и да, вопрос со звёздочкой - так а что пошло не так?))..
Ну он же напрямую пишет, что не нашёл указатель Ты пытаешься пробросить запрос, при этом указывая местом для хранения ответа nil - соответственно, он не видит указатель как таковой
Илья
нельзя второй раз Body читать, ничего не получишь
Anton
забираю файл с мультиформы
Anton
некст
Илья
а где само чтение?
Anton
ща
Anton
я ж по кускам..
Anton
Anton
замазал - там хуйня, не влияющая
Anton
проверки всякие на содержимое row[0]
Anton
тут все ок, вывело
Anton
некст
Илья
а потом еще раз читаешь боди?
Anton
Anton
способ чтения уебский, но не суть
Anton
io.Copy тоже не отрабатывал, собственно
Anton
нуу, а запись уже
Anton
bytes, err := f.Write(readBytes) if err != nil { log.Errorf("%s, err: %v", method, err) return status.Error(codes.Internal, "errors.common.internal") }
Anton
:cattoCry:
Илья
io.Copy тоже не отрабатывал, собственно
ну во первых make([]byte, 1024) создает 1024 пустых значения, нужно make(...., 0 1024)
Anton
это я понимаю, что len и cap разные вещ
Anton
я просто с примера какого-то взял, не задумываясь
Anton
но была бы проблема в этом - я бы понял, что записало херню
Anton
а не 0 байт
Илья
ты два раза читаешь из одного дескриптера
Илья
создавай буфер, записывай туда, а потом два раза читай
Anton
а че, вообще где-то есть упоминание на тему чтения > 1 раза из одного дескриптера?
Anton
из доки
Илья
ты читаешь напрямую из соединения
Anton
поспрашивал у знакомых мидлов, никто не знает
Anton
а илья фокс знает
Anton
и вот попробуйте после этого сказать
Anton
что он не бог
Илья
а вообще есть request.GetBody func() (io.ReadCloser, error)
Belka
Может кто работал с zendesk API и сталкивался с тем, что тикеты возвращаются не полностью отсортированные по времени(1-2 из 10)?