Marcin Pietraszek
Marcin Pietraszek

Reputation: 3214

String function in syscall.Errno

Reading through the 7.8 section of "The Go Programming Language" I spotted following code:

var err error = syscall.Errno(2)
fmt.Println(err.Error()) // "no such file or directory"
fmt.Println(err)         // "no such file or directory"

I understand the first and second line. error interface is saitisfied by syscall.Errno, thus Error() function returning string is available.

I don't understand third one. Going through syscall's sources I can't find any place where syscall.Errno satisfies stringer interface - String() function is not defined.

Why third one prints string representation of sysscall.Errno?

Upvotes: 1

Views: 969

Answers (1)

Jonathan Hall
Jonathan Hall

Reputation: 79586

The answer is found in the fmt documentation here:

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 actually, for any value that supports both, the String() method is never called at all, since the error interface takes precidence over the Stringer interface. You can test this with a program like this one:

package main

import (
    "fmt"
)

type foo string

func (f foo) String() string {
    return "string"
}

func (f foo) Error() string {
    return "error"
}

func main() {
    fmt.Println(foo(""))
}

Output:

error

Upvotes: 5

Related Questions