658

私は単純化された染色体を表現しようとしています。これは N 個の塩基で構成され、それぞれが の 1 つにしかなりません{A, C, T, G}

列挙型を使用して制約を形式化したいと思いますが、Go で列挙型をエミュレートする最も慣用的な方法は何だろうと思っています。

4

12 に答える 12

794

言語仕様からの引用: Iota

定数宣言内で、事前に宣言された識別子 iota は、連続する型なし整数定数を表します。予約語 const がソースに現れるたびに 0 にリセットされ、各 ConstSpec の後にインクリメントされます。関連する定数のセットを構築するために使用できます。

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)

ExpressionList 内では、各 Iota の値は、各 ConstSpec の後でのみインクリメントされるため、同じです。

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
)

この最後の例では、最後の空でない式リストの暗黙的な繰り返しを利用しています。


だからあなたのコードは次のようになるかもしれません

const (
        A = iota
        C
        T
        G
)

また

type Base int

const (
        A Base = iota
        C
        T
        G
)

ベースをintとは別の型にしたい場合。

于 2013-01-20T16:15:09.460 に答える
101

jnml の回答を参照すると、Base タイプをまったくエクスポートしない (つまり、小文字で書く) ことで、Base タイプの新しいインスタンスを防ぐことができます。必要に応じて、基本型を返すメソッドを持つエクスポート可能なインターフェイスを作成できます。このインターフェイスは、ベースを扱う外部からの関数で使用できます。つまり、

package a

type base int

const (
    A base = iota
    C
    T
    G
)


type Baser interface {
    Base() base
}

// every base must fulfill 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事実上列挙型のようになりました。パッケージ内でのみ、新しいインスタンスを定義できます。

于 2013-08-01T09:17:48.550 に答える
15

ここには多くの良い答えがあると確信しています。しかし、私は列挙型を使用した方法を追加することを考えました

package main

import "fmt"

type Enum interface {
    name() string
    ordinal() int
    values() *[]string
}

type GenderType uint

const (
    MALE = iota
    FEMALE
)

var genderTypeStrings = []string{
    "MALE",
    "FEMALE",
}

func (gt GenderType) name() string {
    return genderTypeStrings[gt]
}

func (gt GenderType) ordinal() int {
    return int(gt)
}

func (gt GenderType) values() *[]string {
    return &genderTypeStrings
}

func main() {
    var ds GenderType = MALE
    fmt.Printf("The Gender is %s\n", ds.name())
}

これは、列挙型を作成して Go で使用する慣用的な方法の 1 つです。

編集:

定数を使用して列挙する別の方法を追加する

package main

import (
    "fmt"
)

const (
    // UNSPECIFIED logs nothing
    UNSPECIFIED Level = iota // 0 :
    // TRACE logs everything
    TRACE // 1
    // INFO logs Info, Warnings and Errors
    INFO // 2
    // WARNING logs Warning and Errors
    WARNING // 3
    // ERROR just logs Errors
    ERROR // 4
)

// Level holds the log level.
type Level int

func SetLogLevel(level Level) {
    switch level {
    case TRACE:
        fmt.Println("trace")
        return

    case INFO:
        fmt.Println("info")
        return

    case WARNING:
        fmt.Println("warning")
        return
    case ERROR:
        fmt.Println("error")
        return

    default:
        fmt.Println("default")
        return

    }
}

func main() {

    SetLogLevel(INFO)

}
于 2018-08-30T04:28:12.870 に答える
12

このような使用例では、JSON 文字列にマーシャリングできるように文字列定数を使用すると便利な場合があります。次の例で[]Base{A,C,G,T}は、 にマーシャリングされ["adenine","cytosine","guanine","thymine"]ます。

type Base string

const (
    A Base = "adenine"
    C      = "cytosine"
    G      = "guanine"
    T      = "thymine"
)

を使用するiotaと、値は整数にマーシャリングされます。次の例で[]Base{A,C,G,T}は、 にマーシャリングされ[0,1,2,3]ます。

type Base int

const (
    A Base = iota
    C
    G
    T
)

両方のアプローチを比較する例を次に示します。

https://play.golang.org/p/VvkcWvv-Tvj

于 2021-02-05T03:33:14.727 に答える
2

https://stackoverflow.com/a/17989915/863651をリファクタリングして、もう少し読みやすくしました。

package SampleEnum

type EFoo int

const (
    A EFoo = iota
    C
    T
    G
)

type IEFoo interface {
    Get() EFoo
}

func(e EFoo) Get() EFoo { // every EFoo must fulfill the IEFoo interface
    return e
}

func(e EFoo) otherMethod()  { // "private"
    //some logic
}
于 2021-03-24T09:07:51.447 に答える