【问题标题】:How can I prevent initialization of an exported type in Go?如何防止在 Go 中初始化导出的类型?
【发布时间】:2017-05-08 22:42:02
【问题描述】:

编辑:我不是在问如何正确初始化变量。我在问如何防止它们被错误地初始化,以便采用该类型的函数不必显式验证它们的参数。

在 Go 中,我有一个包含地图的类型,例如:

package foo

type Bar struct {
  baz map[string]int
  total int
}

func NewBar() *Bar {
  return &Bar{baz: map[string]int{}}
}

func (b *Bar) IncrementBaz(key string) {
    f.baz[key] = f.baz[key] + 1
    f.total++
}

// ...

如果另一个包初始化了该类型,然后尝试写入它,它会尝试写入一个 nil 映射,从而导致 segfault:

package main

import "foo"

func main() {
  var b foo.Bar
  b.IncrementBaz("some_key") // write to nil map -> segfault
  // ...
}

为了防止这种情况,我想让其他包无法初始化一个空的foo.Bar

我不能简单地将其取消导出,因为我希望其他包中的函数能够将其声明为参数或返回类型。如果我将它包装在一个界面中,我会遇到类似的问题:

package "foo"

type Bar interface {
  IncrementBaz(string)
  // ...
}

type bar struct {
  baz map[string]int
  total int
}

func NewBar() Bar {
  return &bar{baz: map[string]int{}}
}

func (b *bar) IncrementBaz(key string) {
    f.baz[key] = f.baz[key] + 1
    f.total++
}

// ...

类似的问题:

package main

import "foo"

func main() {
  var b foo.Bar
  b.IncrementBaz("some_key") // method call on nil interface -> segfault
  // ...
}

有没有办法让导出的类型只有声明它的包才能初始化它?

【问题讨论】:

    标签: go null segmentation-fault initialization


    【解决方案1】:

    现在foo.Bar 只是一个接口类型。默认值为 nil 指针。你很亲密,初始化为b := foo.NewBar()

    【讨论】:

    • 接口类型可以是nil,这意味着任何采用该类型的函数都必须对其进行零检查,否则在尝试对其调用方法时可能会出现恐慌,这就是我我试图避免。
    猜你喜欢
    • 1970-01-01
    • 2021-07-18
    • 2012-01-01
    • 2011-08-28
    • 2015-12-05
    • 2015-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多