golang的interface的使用以及作用

检测是否实现接口

 // 检查 *myWriter 类型是否实现了 io.Writer 接口
    var _ io.Writer = (*myWriter)(nil)

    // 检查 myWriter 类型是否实现了 io.Writer 接口
    var _ io.Writer = myWriter{}

指针实现和值实现

//必须是指针才可使用
func (w *Woman) Say() {
    fmt.Println("I'm a woman")
}
//指针和值都可以使用
func (m Man) Say() {
    fmt.Println("I'm a man")
}

防止或者解决包相互依赖的情况

  • 情况说明

    • 当你a、b两个包都需要相互使用各自内部的函数、结构体的时候,就会形成包相互依赖的情况
  • 解决方法:

    • 新开一个文件夹c,定义一个interface的接口,随便选择其中一个包,比如我们选择a包,让a这个包里面需要用到b包的函数方法都写入到interface中,让a包导入c包,然后通过接口来使用b包中的方法,这样就不需要导入b包了
  • 示例:

    • 使用接口前,可以看出现在就是互相导入的情况了
    //Room.go
    package modelroom
    import "....../modelclient"
    type Room struct {
        RoomID     string
        PlayerList map[string]*modelclient.Client
        StatesList map[string]*calculate.StateController
        //管理地图的状态
        RoomMapManager *Map.MapManager
        IsGameBegin    bool
        IsGameEnd      bool
        EndChan        chan struct{}
        //用于数据转发
        DataChan           chan map[string]interface{}
        FilterableDataChan chan FilterableData
        // 限制清除房间的goroutine只有一个
        ifClearing bool
    
        RoomLock sync.RWMutex
    
        logger *zap.Logger
    }
    
    //client.go
    package modelclient
    import "....../modelroom"
    type Client struct {
        UserID string
        //玩家标识的颜色
        UserColor       int
        Room            *modelroom.Room
        Conn            *websocket.Conn
        StateController *calculate.StateController
        //用于判断此玩家当前是否在线
        IsInGame bool
        //用于判断此玩家是否已经注册到hub中
        logger   *zap.Logger
        dataChan chan []byte
    }
    • 使用接口后,就不会有相互导入的情况了
    //roomcontroller.go
    package roomcontroller
    type RoomController interface {
        Lock()
        Unlock()
        GetChannelWithoutFilter() chan<- map[string]interface{}
        GetChannelWithFilter() chan<- filter.FilterableData
        GetEndChannel() chan<- struct{}
        //查看游戏是否结束
        CheckEnd() bool
        //返回IsGameBegin
        GetIsGameBegin() bool
        //返回IsGameEnd
        GetIsGameEnd() bool
        //清理倒计时
        CountTimeClear()
        GetStateController(id string) (*calculate.StateController, error)
        GetRoomManager() (*Map.MapManager, error)
        HandlePlayerClose(id string) error
    }
    
    //Room.go,Room结构体已经实现了RoomController的接口
    package modelroom
    import "....../modelclient"
    type Room struct {
        RoomID     string
        PlayerList map[string]*modelclient.Client
        StatesList map[string]*calculate.StateController
        //管理地图的状态
        RoomMapManager *Map.MapManager
        IsGameBegin    bool
        IsGameEnd      bool
        EndChan        chan struct{}
        //用于数据转发
        DataChan           chan map[string]interface{}
        FilterableDataChan chan FilterableData
        // 限制清除房间的goroutine只有一个
        ifClearing bool
    
        RoomLock sync.RWMutex
    
        logger *zap.Logger
    }
    
    //client.go
    package modelclient
    import "....../roomcontroller"
    type Client struct {
        UserID string
        //玩家标识的颜色
        UserColor       int
        RoomController  roomcontroller.RoomController
        Conn            *websocket.Conn
        StateController *calculate.StateController
        //用于判断此玩家当前是否在线
        IsInGame bool
        //用于判断此玩家是否已经注册到hub中
        logger    *zap.Logger
        dataChan  chan []byte
        hubManger hubmanager.HubManager
    }

    变量私有化以及实现构造器

    • 接口本身不能创建实例,但是可以指向实现了接口的变量,这样可以实现动态绑定
    package example
    
    type A interface {
      ID() string
    }
    //结构体小写,因此外包是无法使用这个结构体
    type a struct {
      id string
    }
    //通过接口来接收widget的实例,这样就不会暴露实例,用户只能通过这个NewWidget才可以获取到实例,就实现了构造器的思想
    func New_a() A {
      return a{
        id: xid.New().String(),
      }
    }
    //实现接口
    func (ins a) ID() string {
      return ins.id
    }

Tags:

Comments are closed

       

粤公网安备44011302004556号