2

我目前正在通过解决rosalind 问题(基本上是一堆与生物信息学相关的代码 katas)来学习 Go。

我目前正在代表具有以下类型的 DNA 链:

type DNAStrand struct {
    dna byte[]
}

我最初的原因是封装字节切片,所以我知道它只包含代表核苷酸的字节:'A', 'C', 'G', 'T'。我意识到这显然没有保证,因为我可以简单地做:

DNAStrand{[]byte("foo bar")}

并且不再保证我的 dna 链包含一个字节数组,其中仅包含这四个字节中的元素。

由于我的结构仅包含一个字节数组,这样做是否更好/更符合思想:

type DNAStrand []byte

还是让类型包含 dna 链更好?对于何时使用这两种方法中的任何一种,是否有任何经验法则?

4

3 回答 3

11

以你的具体例子,我可能会做这样的事情:

type neucleotide char // unexported type users can't construct their own.

type DNAStrand []neucleotide // because users can't construct their own
                             // nucleotides they also can't construct their
                             // own DNAStrands.

const (
  // These are exported values so they can use these nucleotides to construct a
  // DNAStrand with.
  A nucleotide = 'A'
  C nucleotide = 'C'
  G nudleotide = 'G'
  T nucleotide = 'T'
)

// This function allows them to actually construct a DNAstrand with a list of
//  nucleotides from the constants above.
func New(nts ...nucleotide) DNAStrand {
    return nts
}

由于核苷酸类型未导出,用户无法自己构建。您在导出的 const 中提供了它们唯一允许的实例,因此没有用户可以提供他们自己的新核苷酸。

于 2013-01-09T19:05:07.910 回答
2

零字段的结构很方便。具有许多字段的结构更加方便。仅具有一个字段的结构有点特殊,我想不出一个合理的“好”情况来使用它们——即使它们经常“在野外”看到。我,一方面,不使用它们。

无论如何,如果您真的需要关于DNAStrand切片内容的更严格/防弹的安全性 - 那么可以使用单字段结构并为此/此类命名类型定义参数检查设置方法。

在这种情况下,如果稍​​后从其他包中使用该定义,则无法以使用package unsafe为模来规避检查并获得与您的DNAStrand{[]byte("foo bar")}示例等效的结果。

于 2013-01-09T13:39:06.230 回答
1

我会使用type DNAStrand []byte它,因为它很简单,而且我可以在上面使用正则表达式。我可能会使用一个初始化函数来检查每个字节是否都在 ACGT 中。

var validDNAStrandPat = regexp.MustCompile("[ACTG]*")

func DNAStrandForString(s string) DNAStrand {
    if !validDNAStrandPat.Match(s) {
        panic("Invalid DNA Strand.")
    }
    return DNAStrand([]byte(s))
}
于 2013-01-09T22:47:48.767 回答