В данный момент я разделяю API на 3 слоя: handlers, service, repository.
В repository под PostgreSQL я использую
https://github.com/jackc/pgx и при Query, QueryRow он возвращает ошибку pgx.ErrNoRows и я ее там обрабатывал и эта ошибка сработала, то возвращал просто nil или 0 или "".
code
func (r *UserPGRepo) GetLanguageCodeByID(ctx context.Context, id int64) (string, error) {
const op = "users.repository.pg.GetLanguageCodeByID"
tx, err := r.pgpool.Begin(ctx)
if err != nil {
return "", fmt.Errorf("%s: %w", op, err)
}
defer tx.Rollback(ctx)
if err = postgres.PrepareQuery(ctx, tx, op, getLanguageCodeByID, r.queries); err != nil {
return "", fmt.Errorf("%s: %w", op, err)
}
var langCode string
row := tx.QueryRow(ctx, op, id)
if err = row.Scan(&langCode); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return "", nil
}
return "", fmt.Errorf("%s: %w", op, err)
}
if err = tx.Commit(ctx); err != nil {
return "", fmt.Errorf("%s: %w", op, err)
}
return langCode, nil
}
И просто, когда вызывал в service, то обрабатывал на "пустоту" и там возвращал ошибку, а сейчас решил попробовать сразу с repository возвращать ошибку:
code
func (r *UserPGRepo) GetLanguageCodeByID(ctx context.Context, id int64) (string, error) {
const op = "users.repository.pg.GetLanguageCodeByID"
tx, err := r.pgpool.Begin(ctx)
if err != nil {
return "", fmt.Errorf("%s: %w", op, err)
}
defer tx.Rollback(ctx)
if err = postgres.PrepareQuery(ctx, tx, op, getLanguageCodeByID, r.queries); err != nil {
return "", fmt.Errorf("%s: %w", op, err)
}
var langCode string
row := tx.QueryRow(ctx, op, id)
if err = row.Scan(&langCode); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return "", errtypes.UserLanguageCodeNotFound
}
return "", fmt.Errorf("%s: %w", op, err)
}
if err = tx.Commit(ctx); err != nil {
return "", fmt.Errorf("%s: %w", op, err)
}
return langCode, nil
}
Вот так обрабатывал:
code
func (s *BotService) GetByID(ctx context.Context, id int) (*model.LanguageSQL, error) {
const op = "languages.service.GetByTID"
logger := zerolog.Ctx(ctx).With().Str("op", op).Logger()
language, err := s.languageRepo.PostgreSQL.GetByID(ctx, id)
if err != nil {
if errors.Is(err, errtypes.LanguageNotFound) {
return nil, errtypes.LanguageNotFound
}
logger.Error().Err(err).Msg("failed to get language by id")
return nil, fmt.Errorf("%s: %w", op, err)
}
return language, nil
}
но тут как будто появляется вложенность, старым способом было б:
code
func (s *BotService) GetByID(ctx context.Context, id int) (*model.LanguageSQL, error) {
const op = "languages.service.GetByTID"
logger := zerolog.Ctx(ctx).With().Str("op", op).Logger()
language, err := s.languageRepo.PostgreSQL.GetByID(ctx, id)
if err != nil {
logger.Error().Err(err).Msg("failed to get language by id")
return nil, fmt.Errorf("%s: %w", op, err)
}
if language == nil {
return nil, errtypes.LanguageNotFound
}
return language, nil
}
Какой способ все-таки будет лучше, чтобы в дальнейшем у меня не было } } } } } }, а то потом на стадии разработки брать и переписывать не охото, пришел к вам за советом, может даже лучше кто-то предложит