사용자 지정 데이터베이스 오류

8864 단어 gopostgres
사용자 지정 유효성 검사 오류는 이전 장에 추가되었지만 데이터베이스 오류는 어떻습니까? 이미 존재하는 사용자 이름으로 계정을 만들려고 하면 오류ERROR #23505 duplicate key value violates unique constraint "users_username_key"가 발생합니다. 불행히도 여기에는 유효성 검사기가 없으며 pg 모듈은 대부분의 오류를 map[byte]string로 반환하므로 약간 까다로울 수 있습니다.

이를 수행하는 한 가지 방법은 데이터베이스 쿼리를 수행하여 모든 오류 사례를 수동으로 확인하는 것입니다. 예를 들어, 주어진 사용자 이름을 가진 사용자가 데이터베이스에 이미 존재하는지 확인하려면 새 사용자를 생성하기 전에 다음을 수행할 수 있습니다.

func AddUser(user *User) error {
  err = db.Model(user).Where("username = ?", user.Username).Select()
  if err != nil {
    return errors.New("Username already exists.")
  }
  ...
}


문제는 이것이 상당히 지루해질 수 있다는 것입니다. 데이터베이스와 통신하는 모든 기능의 모든 오류 사례에 대해 수행해야 합니다. 게다가 데이터베이스 쿼리를 불필요하게 늘리고 있습니다. 이 간단한 경우에는 모든 성공적인 사용자 생성에 대해 1개가 아닌 2개의 데이터베이스 쿼리가 있습니다. 또 다른 방법이 있는데, 쿼리를 한 번 시도한 다음 오류가 발생하면 구문 분석하는 것입니다. 보다 사용자 친화적인 사용자 정의 오류 메시지를 생성하는 데 필요한 관련 데이터를 추출하기 위해 정규식을 사용하여 모든 오류 유형을 처리해야 하기 때문에 까다로운 부분입니다. 그럼 시작하겠습니다. 언급했듯이 pg 오류는 대부분 map[byte]string 유형이므로 이미 존재하는 사용자 이름으로 사용자 계정을 만들려고 할 때 이 특정 오류의 경우 아래 그림에 지도가 표시됩니다.



관련 데이터를 추출하기 위해 필드82 and 110를 사용합니다. 오류 유형은 필드82에서 읽고 필드110에서 열 이름을 추출합니다. 다음 함수를 internal/store/store.go에 추가해 보겠습니다.

func dbError(_err interface{}) error {
  if _err == nil {
    return nil
  }
  switch _err.(type) {
  case pg.Error:
    err := _err.(pg.Error)
    switch err.Field(82) {
    case "_bt_check_unique":
      return errors.New(extractColumnName(err.Field(110)) + " already exists.")
    }
  case error:
    err := _err.(error)
    switch err.Error() {
    case "pg: no rows in result set":
      return errors.New("Not found.")
    }
    return err
  }
  return errors.New(fmt.Sprint(_err))
}

func extractColumnName(text string) string {
  reg := regexp.MustCompile(`.+_(.+)_.+`)
  if reg.MatchString(text) {
    return strings.Title(reg.FindStringSubmatch(text)[1])
  }
  return "Unknown"
}


이를 통해 dbError()에서 이 internal/store/users.go 함수를 호출할 수 있습니다.

func AddUser(user *User) error {
  ...

  _, err = db.Model(user).Returning("*").Insert()
  if err != nil {
    log.Error().Err(err).Msg("Error inserting new user")
    return dbError(err)
  }
  return nil
}


이제 기존 사용자 이름으로 새 계정을 만들려고 하면 다음과 같은 멋진 오류 메시지가 표시됩니다.



물론 이것은 시작에 불과합니다. 모든 유형의 오류를 개별적으로 처리해야 하지만 이제 해당 처리가 한 곳에서 이루어지며 추가 쿼리가 필요하지 않습니다. 처리하려는 나머지 오류 사례를 처리하거나 내 솔루션을 확인RGB GitHub repo할 수 있습니다.

좋은 웹페이지 즐겨찾기