package test
import (
"fmt"
"testing"
)
// 定义一个动物的接口
type animal interface {
Say() string
Color() string
}
// 可以理解cat类
type Cat struct{}
func (c Cat) Say() string { return "i am a cat" }
func (c Cat) Color() string {
return "i am black"
}
// 可以理解为dog类
type Dog struct{}
func (d Dog) Say() string { return "i am a dog" }
func (d Dog) Color() string {
return "i am white"
}
// 可以理解为汽车
type Car struct{}
func introduceSelf(input animal) {
fmt.Println(input.Say() + " and " + input.Color())
}
func TestMain1(t *testing.T) {
c := Cat{}
d := Dog{}
introduceSelf(c)
introduceSelf(d)
//car := Car{}
//printSelf(car) 这两行不注释就会报错,因为car没有实现animal接口
}
package main
import (
"fmt"
"sort"
)
type Person struct {
Name string
Age int
}
func (p Person) String() string {
return fmt.Sprintf("%s: %d", p.Name, p.Age)
}
// ByAge implements sort.Interface for []Person based on
// the Age field.
type ByAge []Person //自定义
func (a ByAge) Len() int { return len(a) }
func (a ByAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
func main() {
people := []Person{
{"Bob", 31},
{"John", 42},
{"Michael", 17},
{"Jenny", 26},
}
fmt.Println(people)
sort.Sort(ByAge(people))
fmt.Println(people)
}
// 这里开始是 withCancel
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
c := newCancelCtx(parent)
propagateCancel(parent, &c)
return &c, func() { c.cancel(true, Canceled) }
}
// newCancelCtx returns an initialized cancelCtx.
func newCancelCtx(parent Context) cancelCtx {
return cancelCtx{
Context: parent,
done: make(chan struct{}),
}
}
// A cancelCtx can be canceled. When canceled, it also cancels any children
// that implement canceler.
type cancelCtx struct {
Context
done chan struct{} // closed by the first cancel call.
mu sync.Mutex
children map[canceler]struct{} // set to nil by the first cancel call
err error // set to non-nil by the first cancel call
}
// 这里开始是 WithValue
func WithValue(parent Context, key, val interface{}) Context {
if parent == nil {
panic("cannot create context from nil parent")
}
if key == nil {
panic("nil key")
}
if !reflectlite.TypeOf(key).Comparable() {
panic("key is not comparable")
}
return &valueCtx{parent, key, val}
}
// A valueCtx carries a key-value pair. It implements Value for that key and
// delegates all other calls to the embedded Context.
type valueCtx struct {
Context
key, val interface{}
}
package main
// 假设这是redis客户端
type Redis struct {
}
func (r Redis) GetValue(key string) string {
panic("not implement")
}
// 不通过接口实现:检查用户是否有权限的功能
func AuthExpire(token string, rds Redis) bool { // 这里要修改
res := rds.GetValue(token) // 这里可能也要修改
if res == "" {
return false
} else {
// 正常处理
return true
}
}
// 这里如果有其他的函数引用了 rds Redis, 那肯定也全部要改
// .......
func main() {
token := "test"
rds := Redis{} // 这里要修改
AuthExpire(token, rds) // 这里rds这个名字可能要修改
}
package main
type Cache interface {
GetValue(key string) string
}
// 假设这是redis客户端
type Redis struct {
}
func (r Redis) GetValue(key string) string {
panic("not implement")
}
// 假设这是自定义的一个缓存器
type MemoryCache struct {
}
func (m MemoryCache) GetValue(key string) string {
panic("not implement")
}
// 通过接口实现:检查用户是否有权限的功能
func AuthExpire(token string, cache Cache) bool {
res := cache.GetValue(token)
if res == "" {
return false
} else {
// 正常处理
return true
}
}
func main() {
token := "test"
cache := Redis{} // Cache := MemoryCache{},修改这一句即可
AuthExpire(token, cache)
}
how-to-use-interfaces-in-go:https://www.digitalocean.com/community/tutorials/how-to-use-interfaces-in-go
empty interface:https://www.calhoun.io/how-do-interfaces-work-in-go/
what, how,why: http://legendtkl.com/2017/06/12/understanding-golang-interface/
go 设计与实现: https://draveness.me/golang/docs/part2-foundation/ch04-basic/golang-interface/
why-i-use-interfaces:https://krancour.medium.com/go-pointers-why-i-use-interfaces-in-go-338ae0bdc9e4