usar recorrer que enum ejemplo definicion como clase enums go genetics

enums - recorrer - que es un enum en java



¿Cuál es una forma idiomática de representar enumeraciones en Go? (6)

Estoy tratando de representar un cromosoma simplificado, que consiste en N bases, cada una de las cuales solo puede ser una de {A, C, T, G} .

Me gustaría formalizar las restricciones con una enumeración, pero me pregunto cuál es la forma más idiomática de emular una enumeración en Go.


A partir de Go 1.4, la herramienta de go generate se ha introducido junto con el comando de cadena que hace que su enumeración sea fácilmente depurable e imprimible.


Cotización de las especificaciones de idioma: Iota

Dentro de una declaración constante, el identificador predeclarado iota representa constantes enteras no tipificadas sucesivas. Se restablece a 0 siempre que la palabra reservada const aparezca en la fuente y se incremente después de cada ConstSpec. Se puede usar para construir un conjunto de constantes relacionadas:

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)

Dentro de una ExpressionList, el valor de cada iota es el mismo porque solo se incrementa después de cada 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 )

Este último ejemplo explota la repetición implícita de la última lista de expresiones no vacías.

Entonces tu código podría ser como

const ( A = iota C T G )

o

type Base int const ( A Base = iota C T G )

Si quieres que las bases sean un tipo separado de int.


Es cierto que los ejemplos anteriores de uso de const y iota son las formas más idiomáticas de representar enumeraciones primitivas en Go. Pero, ¿qué sucede si está buscando una forma de crear una enumeración más completa similar a la que vería en otro idioma como Java o Python?

Una forma muy sencilla de crear un objeto que comienza a verse y sentirse como una enumeración de cadena en Python sería:

package main import ( "fmt" ) var Colors = newColorRegistry() func newColorRegistry() *colorRegistry { return &colorRegistry{ Red: "red", Green: "green", Blue: "blue", } } type colorRegistry struct { Red string Green string Blue string } func main() { fmt.Println(Colors.Red) }

Supongamos que también desea algunos métodos de utilidad, como Colors.List() y Colors.Parse("red") . Y tus colores eran más complejos y necesitaban ser una estructura. Entonces podrías hacer algo como esto:

package main import ( "errors" "fmt" ) var Colors = newColorRegistry() type Color struct { StringRepresentation string Hex string } func (c *Color) String() string { return c.StringRepresentation } func newColorRegistry() *colorRegistry { red := &Color{"red", "F00"} green := &Color{"green", "0F0"} blue := &Color{"blue", "00F"} return &colorRegistry{ Red: red, Green: green, Blue: blue, colors: []*Color{red, green, blue}, } } type colorRegistry struct { Red *Color Green *Color Blue *Color colors []*Color } func (c *colorRegistry) List() []*Color { return c.colors } func (c *colorRegistry) Parse(s string) (*Color, error) { for _, color := range c.List() { if color.String() == s { return color, nil } } return nil, errors.New("couldn''t find it") } func main() { fmt.Printf("%s/n", Colors.List()) }

En ese momento, seguro que funciona, pero es posible que no te guste cómo debes definir los colores repetitivamente. Si en este punto desea eliminar eso, puede usar etiquetas en su estructura y hacer un poco de reflexión para configurarlo, pero espero que esto sea suficiente para cubrir a la mayoría de las personas.


Estoy seguro de que tenemos muchas buenas respuestas aquí. Pero, solo pensé en agregar la forma en que he usado los tipos enumerados

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()) }

Esta es, de lejos, una de las formas idiomáticas en que podríamos crear tipos enumerados y usarlos en Go.

Editar:

Agregando otra forma de usar constantes para enumerar

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) }


Puedes hacerlo así:

type MessageType int32 const ( TEXT MessageType = 0 BINARY MessageType = 1 )

Con este código el compilador debería comprobar el tipo de enumeración.


Refiriéndose a la respuesta de jnml, podría evitar nuevas instancias del tipo Base al no exportar el tipo Base en absoluto (es decir, escribirlo en minúscula). Si es necesario, puede crear una interfaz exportable que tenga un método que devuelva un tipo base. Esta interfaz podría usarse en funciones externas que se ocupan de Bases, es decir,

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 }

Dentro del paquete principal a.Baser es efectivamente como una enumeración ahora. Solo dentro del paquete puede definir nuevas instancias.