Skip to main content

接口 Interface

Embedding Interface

type Reader interface {
Read(p []byte) (n int, err error)
}

type Writer interface {
Write(p []byte) (n int, err error)
}

// ReadWriter 接口嵌入了 Reader 和 Writer 接口。
type ReadWriter interface {
Reader
Writer
}

Name interface methods' arguments

type Copier interface {
Copy(string, string) int
}

// Name the arguments of the interface in order to get more readability and clarity
type Copier interface {
Copy(sourceFile string, destinationFile string) (bytesCopied int)
}

Struct 实现 Interface

一个 struct 可以实现一个或多个 interface。

type message interface {
getMessage() string
}

type birthdayMessage struct {
birthdayTime time.Time
recipientName string
}

func (bm birthdayMessage) getMessage() string {
return fmt.Sprintf("Hi $s, it is your birthday on %s", bm.recipientName, bm.birthdayTime)
}

type sendingReport struct {
reportName string
numberOfSends int
}

func (sr sendingReport) getMessage() string {
return fmt.Sprintf(`Your "%s" report is ready. You've send %v num of persones`, sr.reportName, sr.numberOfSends)
}

func sendMessage(msg message) {
fmt.Println(msg.getMessage())
}

func test (m message) {
sendMessage(m)
}

func main() {
test(sendingReport{
reportName: "First Reposrt",
nuberOfSends: 10,
})
test(birthdayMessage{
recipientName: "John Doe",
birthdayTime: time.Date(1994, 03, 21, 0, 0, 0, 0, time.UTC)
})
}

Type assertions in Go

When working with interfaces in Go, every once-in-awhile you'll need access to the underlying type of an interface value. You can cast an interface to its underlying type using a type assertion.

type shape interface {
area() float64
}

type circle struct {
radius float64
}

/*
"c" is a new circle cast from "s" which is an instance of a shape.
"ok" is a bool that is true if "s" was a circle
or false if "s" isn't a circle
*/
c, ok := s.(circle)

Type switches

A type switch makes it easy to do serveral type assertions in a series.

func printNumericValue(num interface{}) {
switch v := num.(type) {
case int:
fmt.Printf("%T\n", v)
case string:
fmt.Printf("%T\n", v)
default:
fmt.Printf("%T\n", v)

}
}

func main() {
printNumericValue(1)
// prints "int"

printNumericValue("1")
// prints "string"

printNumericValue(struct{}{})
// prints "struct{}"
}

Principle

1. Clean interface

Interfaces should have as few methods as possible.

2. Interfaces should have no knowledge of satifying types

type car interface {
Color() string
speed() int
isFiretruck() bool // Wrong
}

3. Interface are not classes

  • Interfaces are not classes, they are slimmer.
  • Interfaces don't have constructors and deconstructors that require that data is creataed or destroyed.
  • Interfaces aren't hierarchical by nature, though there is syntactic suger to create interfaces that happen to be supersets of other interfaces.
  • Interfaces define function signatures, but not underlying behavior.