【问题标题】:Pointer to interface in method args?指向方法参数中的接口的指针?
【发布时间】:2017-08-05 07:59:32
【问题描述】:

Gist with code

如何在第 30 行使用 Herbivore 界面代替 *Mouse?

我想将实现 Herbivore 接口的不同结构传递给方法 eatingVictim,而不仅仅是鼠标

【问题讨论】:

    标签: pointers go struct interface


    【解决方案1】:

    让我解释一下:

    首先在这个函数中:

    func (predator Cat) eatingVictim(victim *Mouse) {
        fmt.Println(predator.name + "'s eating victim " + victim.name)
        predator.hungry = false
        victim.alive = false
    }
    

    你想通过草食动物。这是一个糟糕的解决方案,因为您不会 在此处使用 Herbivore 接口中的方法。更好的方法是定义 另一个界面。

    type Animal interface {
        GetName() string
        SetAlive(bool)
    }
    

    并为鼠标(如果你愿意,也可以为猫)实现它:

    func (m *Mouse) GetName() string {
        return m.name
    }
    
    func (m *Mouse) SetAlive(alive bool) {
        m.alive = alive
    }
    

    然后将 Predator 界面改为:

    type Predator interface {
        eatingVictim(victim Animal)
    }
    

    并为 Cat 实现它

    func (predator *Cat) eatingVictim(victim Animal) {
        fmt.Println(predator.name + "'s eating victim " + victim.GetName())
        predator.hungry = false
        victim.SetAlive(false)
    }
    

    我需要提一下,如果你希望你的原始结构 被修改然后你需要传递一个指向结构的指针,而不是一个结构 接收者参数:

    此处鼠标结构不会被修改。只有一个副本。

    func (herbivore Mouse) eatingGrass() {
        fmt.Println(herbivore.name + "'s eating a grass.. ^___^")
        herbivore.hungry = false
    }
    

    这是固定版本:

    func (herbivore *Mouse) eatingGrass() {
        fmt.Println(herbivore.name + "'s eating a grass.. ^___^")
        herbivore.hungry = false
    }
    

    如果您想对此进行更好的解释 - 请访问 my blog post

    最后一件事 - 作为最佳实践 - 如果您在您的方法之一中使用了 Struct 指针 type 那么它们都应该有一个指向它的指针。

    最终解决方案:

    package main
    
    import "fmt"
    
    type Predator interface {
        eatingVictim(victim Animal)
    }
    
    type Herbivore interface {
        eatingGrass()
    }
    
    type Animal interface {
        GetName() string
        SetAlive(bool)
    }
    
    type Cat struct {
        name   string
        hungry bool
        alive  bool
    }
    
    type Mouse struct {
        name   string
        hungry bool
        alive  bool
    }
    
    func (herbivore *Mouse) eatingGrass() {
        fmt.Println(herbivore.name + "'s eating a grass.. ^___^")
        herbivore.hungry = false
    }
    
    func (m *Mouse) GetName() string {
        return m.name
    }
    
    func (m *Mouse) SetAlive(alive bool) {
        m.alive = alive
    }
    
    func (predator *Cat) eatingVictim(victim Animal) {
        fmt.Println(predator.name + "'s eating victim " + victim.GetName())
        predator.hungry = false
        victim.SetAlive(false)
    }
    
    func main() {
        cat := Cat{"cat", true, true}
        mouse := Mouse{"mouse", true, true}
    
        fmt.Println(cat)
        fmt.Println(mouse)
    
        mouse.eatingGrass()
        cat.eatingVictim(&mouse)
    
        fmt.Println(cat)
        fmt.Println(mouse)
    }
    

    【讨论】:

      【解决方案2】:

      首先你需要在接口中添加一个Name()和一个SetAlive()方法并导出eatingGrass

      type Herbivore interface {
          Name()string
          SetAlive(bool)
          EatingGrass()
      }
      

      那么你需要为鼠标实现Name()

      func (herbivore *Mouse) Name()string {
          return Mouse.name
      }
      

      然后对 SetAlive 执行相同操作。

      现在可以使用界面了:

      func (predator Cat) eatingVictim(h Herbivore) {
          fmt.Println(predator.name + "'s eating victim " + h.Name())
          predator.hungry = false
          h.SetAlive(false)
      }
      

      注意:您应该实现*Mouse 的所有功能。因为当您设置结构的某些值时,您应该为指针而不是结构实现方法。否则你可能会有错误。

      在实现时,最好像这样定义变量:

      func (m *Mouse) Name() string {
        return m.name
      }
      

      【讨论】:

        猜你喜欢
        • 2017-07-04
        • 1970-01-01
        • 2014-02-16
        • 2015-04-18
        • 1970-01-01
        • 2021-12-10
        • 1970-01-01
        • 2011-11-30
        • 2018-11-06
        相关资源
        最近更新 更多