【问题标题】:Inner state of embedded types in golang - how does it work?golang 中嵌入类型的内部状态 - 它是如何工作的?
【发布时间】:2020-03-10 12:33:36
【问题描述】:

我正试图将我的头脑围绕在 golang 中嵌入,当涉及到嵌入另一个类型的状态时,我有点困惑。

这是我的问题:如果我有一个类型为 Embedii 的 int,并且它有一个影响其值的方法,那么它应该出现在嵌入它的类型中吗?

这是我在玩的东西:

package main

import (
  "fmt"
)

type Embedii int

func (y *Embedii) Do() {
  if y == nil {
    y = new(Embedii)
  } else {
    *y = *y + 1
  }
  fmt.Println(*y)
}

type Embedder struct {
  *Embedii
}

func main() {
  embedii := new(Embedii)
  embedii.Do() // prints 1
  embedii.Do() // prints 2

  fmt.Println("---")

  embedder := new(Embedder)
  embedder.Do() // prints 0
  embedder.Do() // prints 0

  fmt.Println("---")

  nembedii := new(Embedii)
  embedo := &Embedder{nembedii}
  embedo.Do() // prints 1
  embedo.Do() // prints 2
}

https://play.golang.org/p/ArqKESVWoS-

我很想知道为什么我必须将现有的 Embedii 实例显式传递给 Embedder 类型才能正常工作

【问题讨论】:

  • if y == nil { y = new(Embedii) } 可能不会像您认为的那样做。不要在 Go 中编写 Javacode。
  • 并不能真正解决您的问题,但这将实现所有三个变体按预期递增; play.golang.org/p/3aUC412mwsm - 很确定你的问题就是沃尔克提到的。不能肯定地说,但可能与将内存地址重新映射到新指针有关。
  • @Mikey 这很有趣,现在我很好奇的是 Embedii 的方法(使用指针引用定义)如何添加到 Embedder 中,即使接收者是一个指针和Embedii 包含在没有*Embedder 结构中。

标签: pointers go methods struct embedding


【解决方案1】:

Embedii.Do() 中,接收者是一个指针值。这是一个副本。给这个指针变量赋值只会修改副本。

y = new(Embedii) 只是分配了一个指向局部变量y 的指针,当Do() 返回时,它就丢失了。再次调用时,y 将再次变为nil,因此它会为其创建并分配一个新值(返回后将再次丢失)。

如果您之前创建了一个Embedii,它会起作用,因为那样您就不会在Do() 中创建和分配它(这会丢失)。

如果你返回新的Embedii(更准确地说是它的地址)并分配它,你会看到它在递增,但它会以0而不是1开头,因为第一次调用只是创建它而不递增,在其他情况下,它已经存在,因此第一次调用会立即递增:

func (y *Embedii) Do() *Embedii {
    if y == nil {
        y = new(Embedii)
    } else {
        *y = *y + 1
    }
    fmt.Println(*y)
    return y
}

并使用它:

embedder := new(Embedder)
embedder.Embedii = embedder.Do() // prints 0
embedder.Embedii = embedder.Do() // prints 1

输出将是(在Go Playground 上尝试):

1
2
---
0
1
---
1
2

【讨论】:

    【解决方案2】:

    “应该以嵌入它的类型出现吗?”是的,它应该,因为它是结构中的另一种类型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-30
      • 2017-08-03
      • 1970-01-01
      • 2011-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多