赞
踩
最近在看context底层源码时发现了一个奇怪的用法:struct里边嵌入interface,struct又没有完全实现interface的所有接口,以前真心没注意到这种用法,只见过interface嵌套interface的,决定提笔记录一下。
直接上源码吧:src\context\context.go
- type Context interface {
- Deadline() (deadline time.Time, ok bool)
- Done() <-chan struct{}
- Err() error
- Value(key interface{}) interface{}
- }
cancelCtx 结构体的定义和具体实现
- type cancelCtx struct {
- Context
- mu sync.Mutex // protects following fields
- done atomic.Value // of chan struct{}, created lazily, closed by first cancel call
- children map[canceler]struct{} // set to nil by the first cancel call
- err error // set to non-nil by the first cancel call
- }
-
- func (c *cancelCtx) Value(key interface{}) interface{} {
- if key == &cancelCtxKey {
- return c
- }
- return c.Context.Value(key)
- }
-
- func (c *cancelCtx) Done() <-chan struct{} {
- d := c.done.Load()
- if d != nil {
- return d.(chan struct{})
- }
- c.mu.Lock()
- defer c.mu.Unlock()
- d = c.done.Load()
- if d == nil {
- d = make(chan struct{})
- c.done.Store(d)
- }
- return d.(chan struct{})
- }
-
- func (c *cancelCtx) Err() error {
- c.mu.Lock()
- err := c.err
- c.mu.Unlock()
- return err
- }
timerCtx 结构体的定义和具体实现
- type timerCtx struct {
- cancelCtx
- timer *time.Timer // Under cancelCtx.mu.
- deadline time.Time
- }
- func (c *timerCtx) Deadline() (deadline time.Time, ok bool) {
- return c.deadline, true
- }
Context接口有4个方法,但是cancelCtx只实现了3个方法,Deadline()它并没有实现,而timerCtx只实现了Deadline(),其他3个并没有实现。
在我的认知当中没见过这种写法,实现一个接口就是实现这个接口的所有方法,比如源码中的emptyCtx
- type emptyCtx int
-
- func (*emptyCtx) Deadline() (deadline time.Time, ok bool) {
- return
- }
-
- func (*emptyCtx) Done() <-chan struct{} {
- return nil
- }
-
- func (*emptyCtx) Err() error {
- return nil
- }
-
- func (*emptyCtx) Value(key interface{}) interface{} {
- return nil
- }
-
- func (e *emptyCtx) String() string {
- switch e {
- case background:
- return "context.Background"
- case todo:
- return "context.TODO"
- }
- return "unknown empty Context"
- }
-
- var (
- background = new(emptyCtx)
- todo = new(emptyCtx)
- )
当时看到这种用法,直接懵逼了,还是自己基础不牢。。。。
嵌入interface作为struct的一个匿名成员,就可以假设这个struct就是此成员interface的一个实现,而不管struct是否已经实现interface所定义的函数。
- type Student interface {
- Run()
- Walk()
- }
- type Pupil struct {
- age int
- Student
- }
- func NewPupil(age int) *Pupil{
- return &Pupil{age: age}
- }
- //func (p *Pupil) Run() {
- //
- //}
- //
- //func (p *Pupil) Walk(){
- //
- //}
- func main(){
- p := NewPupil(100)
- var s Student = p
- fmt.Printf("%#v\n",s)
- }
struct Pupil没有实现interface中的任何函数,只是在声明的时候把Student作为一个匿名成员,main函数能正常运行并没有报错,说明p确实被认为是Student的具体实现。
既然没有实现函数,那如何调用接口尼?答案就是 没有实现肯定是不能调用,一旦调用就crash。只能调用已经实现的函数。上边注释掉的 Run()和Walk() 放开哪个,s就可以调用哪个。。。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。