Go: Interfaces
Table of Contents
1 Interfaces
An interface type is defined by a set of methods. A value of interface type can hold any value that implements those methods. This time we made the greeting feature more generic by defining a function called Greet which takes a param of interface type Namer. Namer is a new interface we defined which only defines one method: Name(). So Greet() will accept as param any value which has a Name() method defined.
package main import ( "fmt" "os" ) type User struct { FirstName, LastName string } func (u *User) Name() string { return fmt.Sprintf("%s %s", u.FirstName, u.LastName) } type Namer interface { Name() string } func Greet(n Namer) string { return fmt.Sprintf("Dear %s", n.Name()) } type Reader interface { Read(b []byte) (n int, err error) } type Writer interface { Write(b []byte) (n int, err error) } type ReadWriter interface { Reader Writer } func main() { u := &User{"Pavel", "Vavilin"} fmt.Println(Greet(u)) var w Writer // os.Stdout implements Writer w = os.Stdout fmt.Fprintf(w, "hello, writer\n") }
Dear Pavel Vavilin hello, writer
The Go convention for interface names is that they should end wiht er
2 Errors
An error is anything that can describe itself as an error string. The idea is captured by the predefined, built-in interface type, error, with its single method, Error, returning a string:
type error interface { Error() string }
The fmt package’s various print routines automatically know to call the method when asked to print an error.
package main import ( "fmt" "time" ) type MyError struct { When time.Time What string } func (e *MyError) Error() string { return fmt.Sprintf("at %v, %s", e.When, e.What) } func run() error { return &MyError{ time.Now(), "it didn't work", } } func main() { if err := run(); err != nil { fmt.Println(err) } }
at 2017-12-12 00:36:21.148564468 +0500 +05, it didn't work