Types 什么时候一个类型应该是包含另一个类型的结构,什么时候它应该只是;扩展;(?)那种类型?

Types 什么时候一个类型应该是包含另一个类型的结构,什么时候它应该只是;扩展;(?)那种类型?,types,struct,go,Types,Struct,Go,我目前正在学习通过做(基本上是一堆与生物信息学相关的代码) 我目前正在用以下类型表示一条DNA链: type DNAStrand struct { dna byte[] } 我最初的原因是封装字节片,这样我就知道它只包含代表核苷酸的字节:'A',C',G',T'。我意识到这显然是没有保障的,因为我可以简单地做到: DNAStrand{[]byte("foo bar")} 现在也不能保证我的dna链包含一个字节数组,其中只有这四个字节中的元素 由于my struct只包含一个字节数组,

我目前正在学习通过做(基本上是一堆与生物信息学相关的代码)

我目前正在用以下类型表示一条DNA链:

type DNAStrand struct {
    dna byte[]
}
我最初的原因是封装字节片,这样我就知道它只包含代表核苷酸的字节:
'A',C',G',T'
。我意识到这显然是没有保障的,因为我可以简单地做到:

DNAStrand{[]byte("foo bar")}
现在也不能保证我的dna链包含一个字节数组,其中只有这四个字节中的元素

由于my struct只包含一个字节数组,这样做是否更好/更具表意性:

type DNAStrand []byte

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

带有零字段的Struct非常方便。具有许多字段的结构更加方便。只有一个字段的结构有点特殊,我想不出一个合理的“好”例子来使用它们——即使它们经常在“野外”看到。一、 首先,不要使用它们

无论如何,如果您真的需要对
DNAStrand
切片内容进行更严格/防弹的安全保护,那么可以使用单字段结构并为此/此类命名类型定义参数检查setter方法


在这种情况下,如果该定义后来从其他包中使用,则无法使用模运算绕过检查并获得与您的
DNAStrand{[]byte(“foo bar”)}
示例等效的结果。

以您的特定示例为例,我可能会这样做:

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
}

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

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

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

func DNAStrandForString(s string) DNAStrand {
    if !validDNAStrandPat.Match(s) {
        panic("Invalid DNA Strand.")
    }
    return DNAStrand([]byte(s))
}

但是,从另一个包中执行
DNAStrand{[]byte(“foo-bar”)}
难道还不可能吗?或者我不能从它所驻留的包外部创建具有非导出字段(如
DNAStrand
)的结构?是的,这是可能的。我应该更准确地说:。。。那么就不会有意外的方法来规避事情了。。。至少对我来说,
v:=DNAStrand{[]byte(“foo-bar”)}
是一种将该值分配给实例的情况。与之相反,比方说
v.Set(foo())
foo
中的一个bug返回一个“非法”值。@jnml我现在无法测试,但我认为尝试直接从不同的源向未报告的字段赋值是一个错误(除了编译器bug或技巧)package@PaoloFalabella当前位置现在我很困惑。这个例子让我想到了我在上面的第一条评论中写的内容,但这些字段实际上并不是未报告的。真丢脸,我现在无法从我的头顶判断什么是正确的,所以我应该用代码检查它:-(现在尝试了一个简单的例子,得到了以下错误:
隐式分配a中未报告的字段“a”。a literal
。因此,本质上,在结构中有一个未报告的字段可以保护它不被从该包外部创建……我最初是这样做的,但当我想要一个核苷酸能够提供给我时,我被卡住了这是一种恭维(
at,cg
)。现在我对未报告的类型有了更多的了解,我想我可以让核苷酸成为未报告的接口,并为每个核苷酸创建未报告的类型……然后,正如您演示的那样,将它们作为常量公开。可能有些过分,但我喜欢所有类型:)太好了!更进一步,如果dnastrand的#很大,并且会造成内存问题,那么您可以使用哈夫曼编码,而不是用ASCII格式对它们进行编码,而是用压缩格式对它们进行编码——我这样做是为了小手类型(在纸牌游戏中跟踪手中的牌)-