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()
Илья
всем привет.
есть у кого-нибудь пример как записывать в 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
Beta
Ребят, всем привет, что лучше использовать стандартный логгер от джина или подключить какую-нибудь стороннюю либу?
Null
🛠 Инструменты для управления уязвимостями в Go-проекте на текущий момент.
➡️ Читать
⚙️ Vulnerability database
@Golang_google
anhckie
есть тут люди, работавшие с fiber? вопрос максимально тупой - как им сделать хттп-запрос))
anhckie
читаю доку и не вижу ответа
anhckie
т.е. мне нужно со своей аппки дернуть сторонний api
Не ну это
Alexey
Patamen
3. Самый мега база - написать буквальный http.NewRequest и фигануть клиентиком
anhckie
anhckie
короче файбер из коробки адекватно не может слать запросы, я так понимаю
anhckie
я, собсно, потому и решил сюда обратить, ибо перечитал этого клиента, а как хоть что-то у него вызвать - вообще не въезжаю. импорты не описаны, ide не понимает примеров
anhckie
типа мож я что-то упускаю
Patamen
Patamen
Напрямую используется функция в тестировании
AcquireAgent
Patamen
fiber.AcquireAgent()
anhckie
господи боже мой блеать
anhckie
я дебил
anhckie
занавес
anhckie
спасибо за помощь))))
Patamen
Patamen
anhckie
еще сразу спрошу - что за первый параметр? не понимаю его задачи. есть урл, есть тело запроса, а это не пойму..
Patamen
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
Илья
ребят, чот не вдупляю, что не так, мб со стороны будет видно
суть: есть хендлер, на который в 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)
в чем может быть проблема, куда рыть?
покажи код
Илья
нельзя второй раз Body читать, ничего не получишь
Anton
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:
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)?