Задать вопрос
@setupx
Go & TS developer

На каком слое принято обрабатывать ошибки?

В данный момент я разделяю 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
}



Какой способ все-таки будет лучше, чтобы в дальнейшем у меня не было } } } } } }, а то потом на стадии разработки брать и переписывать не охото, пришел к вам за советом, может даже лучше кто-то предложит
  • Вопрос задан
  • 74 просмотра
Подписаться 1 Простой Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы