gorm.Errors, which usefully implements `error` for an `[]error` as
returned by `DB.GetError()` was already exported, but because it used a
private field `errors`, it was not able to be created due to the
compile-time error:
implicit assignment of unexported field 'errors' in gorm.Errors literal
The trivial solution would be to export the `errors` field on
`gorm.Errors`, but this led to the issue that the common pattern of
checking `err != nil` failed because a struct{error: nil} != nil.
We can take advantage of type aliasing here to make Errors an []error,
which can in fact be nil and would pass `err != nil` on the happy path.
* Remove `(Errors) GetErrors()`, as it's less useful when Errors is an
[]error which can be iterated over. While this is technically a
breaking change, we never expose an Errors and its difficult to build
one (it can be done with the existing `(Errors) Add(error)`), but
awkwardly. This removal can be reverted without issue and we can make
it an identity method, but it seemed an opportune time to reduce API
surface area on something that likely isn't used.
* Remove errorsInterface, as it's not useful without `(Errors)
GetErrors()`
* Change `(*Errors) Add(error)` => `(Errors) Add(error...) Errors`
because we can't modify even a *Errors when it's a type alias. This is
more idiomatic as it follows the pattern of `slice = append(slice,
element)` Go developers are familiar with.
When using `Preload` to include the results of a "has many"
relationship, Gorm previously returned an uninitialized slice for any
such relations that bore zero records. This distinction was most
apparent when the results were marshalled to a JSON representation--a
record with zero related records would be represented with `null`.
For example, consider the following schema:
id | name
---|------
1 | Lorin
2 | Sue
id | p_id | value
---|------|-------------------
1 | 1 | lorin@example.com
2 | 1 | lorin2@example.com
Querying with:
db.Preload("Email").Find(&people)
And marshalling the resulting value of `people` to JSON would yield the
following string:
[
{
"name": "Lorin",
"email": [
"lorin@example.com",
"lorin2@example.com"
]
},
{
"name": "Sue",
"email": null
}
]
Beyond being inconsistent, the value `null` in this response differs
semantically from the actual state of the database. The database
actually has zero related records for the second user, so a JSON value
of `[]` is appropriate.
Update the callback that processes "has many" relationships to
communicate empty query results with an empty slice.