Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Error() have priority over String()

Tags:

string

go

I've been looking through the tour for go, and I can't figure out why this happens.

When you have a Stringer (String() string), fmt will use that method for printing to console. Like suggested in https://tour.golang.org/methods/6

However if you add Error() string, this method gets called instead of String() string.

package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

func (p *Person) String() string {
    return fmt.Sprintf("%v (%v years)", p.Name, p.Age)
}

func (p *Person) Error() string {
    return fmt.Sprintf("Failed")
}

func main() {
    a := &Person{"Arthur Dent", 42}
    z := &Person{"Zaphod Beeblebrox", 9001}
    fmt.Println(a, z)
}

Results:

Failed Failed

I don't understand why fmt.Println uses Error instead of String.

like image 749
Arian Faurtosh Avatar asked Dec 10 '22 23:12

Arian Faurtosh


2 Answers

Simply because this is how it is implemented. An error is more important in practice, so if the error interface is implemented, that will be printed.

This is documented, read the package doc of fmt:

Except when printed using the verbs %T and %p, special formatting considerations apply for operands that implement certain interfaces. In order of application:

  1. If an operand implements the Formatter interface, it will be invoked. Formatter provides fine control of formatting.

  2. If the %v verb is used with the # flag (%#v) and the operand implements the GoStringer interface, that will be invoked.

If the format (which is implicitly %v for Println etc.) is valid for a string (%s %q %v %x %X), the following two rules apply:

  1. 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).

  2. 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).

So error is 3rd on the list while String() is only 4th.

like image 83
icza Avatar answered Dec 25 '22 18:12

icza


The reason is simple: when fmt uses any of it's print functions, it does a type switch for each argument to determine how it should be printed, and in that type switch case error appears just before case Stringer.

like image 31
LemurFromTheId Avatar answered Dec 25 '22 18:12

LemurFromTheId