Go pq and Postgres appropriate error handling for constraints
<p>I'm currently using the <code>pq</code> lib for Go to communicate with my PostgreSQL database. Error checking is proving to be a little more difficult than anticipated. The easiest way to describe my question is through an example scenario.</p>

<p>Imagine a web form:  </p>

<pre><code>Username  ________
Email     ________
Voucher   ________
Password  ________
</code></pre>

<p>A rough schema:</p>

<pre><code>username VARCHAR(255) UNIQUE NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
voucher VARCHAR(255) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL
</code></pre>

<p>Ignore the presumed plain text password for now. If a person submits the form, I can do all of my validation to verify constraints such as length/allowed characters/etc.</p>

<p>Now it comes to putting it in the database, so we write a prepared statement and execute it. If the validation was done correctly, the only thing that can really go wrong is the <code>UNIQUE</code> constraints. In the event that someone attempts to enter an existing username, database/sql is going to fire back an error.</p>

<p>My problem is that I have no idea what to do with that error and recover from (what should be) a recoverable error. pq provides <a href="https://github.com/lib/pq/blob/master/error.go#L25" rel="nofollow">some support</a> for this, but there still appears to be come ambiguity to what's returned.</p>

<p>I can see two solutions, neither of which sound particularly appealing to me:
A <code>SERIALIZABLE</code> transaction which checks every single form value prior to insertion. Alternatively, some form of parsing on the pq error struct.</p>

<p>Is there a common pattern for implementing such a system? I'd like to be able to say to a user <code>Sorry that username exists</code> rather than <code>Sorry something bad happened</code></p>

<p>As a sidenote, the PostgreSQL documentation states:  </p>

<blockquote>
  <p>The fields for
  schema name, table name, column name, data type name, and constraint
  name are supplied only for a limited number of error types; see
  <a href="http://www.postgresql.org/docs/current/static/errcodes-appendix.html" rel="nofollow">Appendix A.</a></p>
</blockquote>

<p>but the linked page isn't very helpful with respect to values returned in the database object.</p>