Let say we want to extend Error()
function on error
interface. We can simply create a struct derived from string implementing the Error()
method. For example:
type NewUser struct {
Email string
Password string
}
type ErrMissingField string
func (e ErrMissingField) Error() string {
return string(e) + " is required"
}
func (u *NewUser) OK() error {
if len(u.Email) == 0 {
return ErrMissingField("email")
}
if len(u.Password) == 0 {
return ErrMissingField("password")
}
return nil
}
Above code will return either email is required
or password is required
.
But, if I create my own interface, let say ResponseError
, like this:
type ResponseError interface {
ErrorMsg() string
}
type CustomErr string
func (c CustomErr) ErrorMsg() string {
return "[Error] " + string(c)
}
func (u *NewUser) NewOK() ResponseError {
if len(u.Email) == 0 {
return CustomErr("Email required!")
}
if len(u.Password) == 0 {
return CustomErr("Password Required!")
}
return nil
}
It won't print the method implementation I wrote with [Error]
. It just prints the string I passed into the struct Email required!
or Password Required!
.
How to work on this?
If you are using fmt to print, then from https://golang.org/pkg/fmt
If an operand implements the error interface, the Error method will be invoked to convert the object to a string, which will then be formatted as required by the verb (if any).
If an operand implements method String() string, that method will be invoked to convert the object to a string, which will then be formatted as required by the verb (if any)
That's why when you implement Error interface, it prints by invoking Error()
function. If you want custom output for other interface like ResponseError
implement String()
method.
package main
import (
"fmt"
)
type NewUser struct {
Email string
Password string
}
type ResponseError interface {
ErrMsg()
String() string
}
type CustomErr string
func (c CustomErr) String() string {
return "[Error] " + string(c)
}
func (c CustomErr) ErrMsg() {}
func (u *NewUser) NewOK() ResponseError {
if len(u.Email) == 0 {
return CustomErr("Email required!")
}
if len(u.Password) == 0 {
return CustomErr("Password Required!")
}
return nil
}
func main() {
u := &NewUser{}
fmt.Println(u.NewOK())
}
Go playground: https://play.golang.org/p/khAAtLodEND
Go treats type
s that implement error
differently when printing. Your interface ResponseError
does not implement error
through adding Error() string
.
To visualize what I'm talking about see the following example using error
interface:
type NewUser struct {
Email string
Password string
}
type ResponseError interface {
error
ErrorMsg() string
}
type CustomErr string
func (c CustomErr) ErrorMsg() string {
return "[Error] " + string(c)
}
func (c CustomErr) Error() string {
return c.ErrorMsg()
}
func (u *NewUser) NewOK() ResponseError {
if len(u.Email) == 0 {
return CustomErr("Email required!")
}
if len(u.Password) == 0 {
return CustomErr("Password Required!")
}
return nil
}
func main() {
user := NewUser{}
fmt.Printf("Using %%s: %s
", user.NewOK())
fmt.Printf("Using %%v: %v
", user.NewOK())
fmt.Printf("Using %%v and call function ErrorMsg: %v
", user.NewOK().ErrorMsg())
fmt.Printf("Using %%s and call function ErrorMsg: %s
", user.NewOK().ErrorMsg())
}
This will print the following:
Using %s: [Error] Email required!
Using %v: [Error] Email required!
Using %v and call function ErrorMsg: [Error] Email required!
Using %s and call function ErrorMsg: [Error] Email required!
However without error
interface:
type NewUser struct {
Email string
Password string
}
type ResponseError interface {
ErrorMsg() string
}
type CustomErr string
func (c CustomErr) ErrorMsg() string {
return "[Error] " + string(c)
}
func (u *NewUser) NewOK() ResponseError {
if len(u.Email) == 0 {
return CustomErr("Email required!")
}
if len(u.Password) == 0 {
return CustomErr("Password Required!")
}
return nil
}
func main() {
user := NewUser{}
fmt.Printf("Using %%s: %s
", user.NewOK())
fmt.Printf("Using %%v: %v
", user.NewOK())
fmt.Printf("Using %%v and call function ErrorMsg: %v
", user.NewOK().ErrorMsg())
fmt.Printf("Using %%s and call function ErrorMsg: %s
", user.NewOK().ErrorMsg())
}
The output is :
Using %s: Email required!
Using %v: Email required!
Using %v and call function ErrorMsg: [Error] Email required!
Using %s and call function ErrorMsg: [Error] Email required!