我試圖表示一個簡化的染色體,它由N個鹼基組成,每個鹼基只能是{A, C, T, G}
之一。什麼是在Go中表示枚舉的習慣用法?
我想用enum正式確定約束條件,但是我想知道在Go中模擬枚舉最常用的方法是什麼。
我試圖表示一個簡化的染色體,它由N個鹼基組成,每個鹼基只能是{A, C, T, G}
之一。什麼是在Go中表示枚舉的習慣用法?
我想用enum正式確定約束條件,但是我想知道在Go中模擬枚舉最常用的方法是什麼。
從語言規範引用:Iota
內的恆定聲明中,預聲明標識符IOTA表示連續無類型整數常數。只要保留字const在源中出現並在每個ConstSpec後遞增,它就被重置爲0。它可用於構建一組相關的常量:
const ( // iota is reset to 0
c0 = iota // c0 == 0
c1 = iota // c1 == 1
c2 = iota // c2 == 2
)
const (
a = 1 << iota // a == 1 (iota has been reset)
b = 1 << iota // b == 2
c = 1 << iota // c == 4
)
const (
u = iota * 42 // u == 0 (untyped integer constant)
v float64 = iota * 42 // v == 42.0 (float64 constant)
w = iota * 42 // w == 84 (untyped integer constant)
)
const x = iota // x == 0 (iota has been reset)
const y = iota // y == 0 (iota has been reset)
在一個表達式列表,每個絲毫的值是相同的,因爲它是每個常量實現後僅遞增:
const (
bit0, mask0 = 1 << iota, 1<<iota - 1 // bit0 == 1, mask0 == 0
bit1, mask1 // bit1 == 2, mask1 == 1
_, _ // skips iota == 2
bit3, mask3 // bit3 == 8, mask3 == 7
)
這最後一個例子利用了最後一個非空表達式列表的隱式重複。
所以,如果你想要基地,以從int單獨類型的代碼可能會像
const (
A = iota
C
T
G
)
或
type Base int
const (
A Base = iota
C
T
G
)
。
很好的例子(我沒有記得確切的iota行爲 - 當它增加時 - 來自規範)。我個人喜歡給一個枚舉類型,所以它可以作爲參數,字段等進行類型檢查。 – mna
非常有趣@jnml。但我有點失望,靜態類型檢查似乎是鬆散的,例如沒有任何東西阻止我使用從未存在的Base n°42:http://play.golang.org/p/oH7eiXBxhR – Deleplace
Go沒有概念數字子範圍類型,例如Pascal's有,所以'Ord(Base)'不限於'0..3',但是它的底層數字類型有相同的限制。這是一種語言設計選擇,在安全性和性能之間妥協。每次觸摸「Base」類型的值時,請考慮「安全」運行時間限制檢查。或者應該如何爲算術和'++'和'--'定義'Base'值的'溢出'行爲?等 – zzzz
參考jnml的答案,您可以根本不導出Base類型(即將其寫成小寫字母)來阻止Base類型的新實例。如果需要的話,你可能會做出有返回一個基本類型,所以該接口可以從與基地應對外部函數中使用的方法可輸出接口,即
package a
type base int
const (
A base = iota
C
T
G
)
type Baser interface {
Base() base
}
// every base must fullfill the Baser interface
func(b base) Base() base {
return b
}
func(b base) OtherMethod() {
}
package main
import "a"
// func from the outside that handles a.base via a.Baser
// since a.base is not exported, only exported bases that are created within package a may be used, like a.A, a.C, a.T. and a.G
func HandleBasers(b a.Baser) {
base := b.Base()
base.OtherMethod()
}
// func from the outside that returns a.A or a.C, depending of condition
func AorC(condition bool) a.Baser {
if condition {
return a.A
}
return a.C
}
主包裏面的a.Baser
實際上就像一個枚舉。 只有在包中可以定義新的實例。
您的方法似乎適用於「base」僅用作方法接收器的情況。如果你的'a'包暴露了一個帶'base'類型參數的函數,那麼它就會變得危險。事實上,用戶可以用字面值42來調用它,因爲函數可以被轉換爲int,所以函數將接受它作爲「base」。爲了防止出現這種情況,請將'base'設爲'struct':'type base struct {value:int}'。問題:你不能將base聲明爲常量,只能聲明模塊變量。但是42永遠不會被轉換爲這種類型的「基礎」。 – Niriel
@metakeule我試圖理解你的例子,但你在變量名中的選擇使它變得非常困難。 – anon58192932
從Go 1.4開始,go generate
工具與stringer
命令一起引入,使您的枚舉變得易於調試和打印。
你可以把它這樣:
type MessageType int32
const (
TEXT MessageType = 0
BINARY MessageType = 1
)
有了這個代碼編譯器應該檢查枚舉
常量通常以正常駝峯書寫,並非全部大寫。最初的大寫字母意味着變量被導出,這可能是也可能不是你想要的。 – 425nesp
我注意到在Go源代碼中有一個混合,有時常量都是大寫,有時它們是camelcase。你有參考規格嗎? –
@JeremyGailor我認爲425nesp只是指出,開發人員使用它們作爲_unexported_常量,所以使用camelcase。如果開發人員確定它應該導出,那麼可以隨意使用全部大寫或大寫字母,因爲沒有確定的偏好。 請參閱[Golang代碼審查建議](https://github.com/golang/go/wiki/CodeReviewComments#mixed-caps)和 [有效的常量部分](https://golang.org/doc/) effective_go.html#constants) – waynethec
的類型在他們表示爲常量走標準封裝。請參閱http://golang.org/pkg/os/#pkg-constants –
相關:http:// stackoverflow。com/questions/14236263/when-should-a-type-be-a-struct-containing-another-type-and-when-should-it- – lbonn
[Golang:Creating a Constant Type and Restricting (類型的值](http://stackoverflow.com/questions/37385007/golang-creating-a-constant-type-and-restricting-the-types-values) – icza