title: GORM create record that might already exist
body: <p>I'm using <a href="http://gorm.io/docs" rel="noreferrer">gorm</a> with postgres in my Go app.</p>
  
  <p>I want to create a new user in the database, but there is a good chance that that user will already exist. If so, I want to not do anything with the database, but I want know about it so I can tell the user.</p>
  
  <p>The good news is, that's already what <a href="http://gorm.io/docs/create.html" rel="noreferrer"><code>gorm.Create(..)</code></a> does. Trying to create a record with a duplicate unique key will return an error. There are two problems:</p>
  
  <ol>
  <li>I want better error messages. I want to write custom user-facing error messages that are different for "This email address already exists" than "There was an actual internal error." I don't know how to diferentiate between these two events other than trying to parse the error string returned by <code>Create()</code> which seems bug prone.</li>
  <li>I don't want to clutter my logs. Calling <code>Create()</code> with an object that already exists logs an error message to stdout. I don't really consider this an "error" since I was expecting it to happen and I don't want to flood my logs with a bunch of these warnings.</li>
  </ol>
  
  <p>I know I could use a transaction to first check for a user with the given id and then create them if one does not already exist, but it seems like there should be a simpler solution to such a basic thing. How are you supposed to do this?</p>
  
  <hr>
  
  <p>I'm currently doing this:</p>
  
  <pre class="lang-golang prettyprint-override"><code>func (self databaseWrapper) CreateUser(user *User) error {
      db := self.db
      db.NewRecord(*user)
      err := db.Create(user).Error
      if err != nil {
          if db.Where(user.ID).Take(&amp;User{}).Error == nil {
              return fmt.Errorf("A user already exists with id %v", user.ID)
          }
  
          if db.Where(User{Email: user.Email}).Take(&amp;User{}).Error == nil {
              return fmt.Errorf("A user already exists with the given email address: %v", user.Email)
          }
  
          return fmt.Errorf("Error creating user")
      }
      return nil
  }
  
  </code></pre>
  
  <p>Which is a little inefficient and gives the ugly output:</p>
  
  <pre><code>go test
  
  (/home/quinn/workspace/aev/sensor/backend/server/database.go:125)
  [2019-09-01 14:45:40]  pq: duplicate key value violates unique constraint "users_pkey"
  
  (/home/quinn/workspace/aev/sensor/backend/server/database.go:125)
  [2019-09-01 14:45:40]  pq: duplicate key value violates unique constraint "uix_users_email"
  PASS
  ok          3.215s
  </code></pre>
  
  <p>even when everything worked as expected.</p>