接口 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.