I'm trying to represent a simplified chromosome, which consists of N bases, each of which can only be one of {A, C, T, G}.
I'd like to formalize the constraints with an enum, but I'm wondering what the most idiomatic way of emulating an enum is in Go.
Quoting from the language specs:Iota
Within a constant declaration, the predeclared identifier iota represents successive untyped integer constants. It is reset to 0 whenever the reserved word const appears in the source and increments after each ConstSpec. It can be used to construct a set of related constants:
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)
Within an ExpressionList, the value of each iota is the same because it is only incremented after each 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
)
This last example exploits the implicit repetition of the last non-empty expression list.
So your code might be like
const (
A = iota
C
T
G
)
or
type Base int
const (
A Base = iota
C
T
G
)
if you want bases to be a separate type from int.
Referring to the answer of jnml, you could prevent new instances of Base type by not exporting the Base type at all (i.e. write it lowercase). If needed, you may make an exportable interface that has a method that returns a base type. This interface could be used in functions from the outside that deal with Bases, i.e.
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
}
Inside the main package a.Baser is effectively like an enum now.
Only inside the a package you may define new instances.
You can make it so:
type MessageType int32
const (
TEXT MessageType = 0
BINARY MessageType = 1
)
With this code compiler should check type of enum
It's true that the above examples of using const and iota are the most idiomatic ways of representing primitive enums in Go. But what if you're looking for a way to create a more fully-featured enum similar to the type you'd see in another language like Java or Python?
A very simple way to create an object that starts to look and feel like a string enum in Python would be:
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)
}
Suppose you also wanted some utility methods, like Colors.List(), and Colors.Parse("red"). And your colors were more complex and needed to be a struct. Then you might do something a bit like this:
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())
}
At that point, sure it works, but you might not like how you have to repetitively define colors. If at this point you'd like to eliminate that, you could use tags on your struct and do some fancy reflecting to set it up, but hopefully this is enough to cover most people.
There is a way with struct namespace.
The benefit is all enum variables are under a specific namespace to avoid pollution.
The issue is that we could only use var not const
type OrderStatusType string
var OrderStatus = struct {
APPROVED OrderStatusType
APPROVAL_PENDING OrderStatusType
REJECTED OrderStatusType
REVISION_PENDING OrderStatusType
}{
APPROVED: "approved",
APPROVAL_PENDING: "approval pending",
REJECTED: "rejected",
REVISION_PENDING: "revision pending",
}
As of Go 1.4, the go generate tool has been introduced together with the stringer command that makes your enum easily debuggable and printable.
I am sure we have a lot of good answers here. But, I just thought of adding the way I have used enumerated types
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())
}
This is by far one of the idiomatic ways we could create Enumerated types and use in Go.
Edit:
Adding another way of using constants to enumerate
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)
}
For a use case like this, it may be useful to use a string constant so it can be marshaled into a JSON string. In the following example, []Base{A,C,G,T} would get marshaled to ["adenine","cytosine","guanine","thymine"].
type Base string
const (
A Base = "adenine"
C = "cytosine"
G = "guanine"
T = "thymine"
)
When using iota, the values get marshaled into integers. In the following example, []Base{A,C,G,T} would get marshaled to [0,1,2,3].
type Base int
const (
A Base = iota
C
G
T
)
Here's an example comparing both approaches:
https://play.golang.org/p/VvkcWvv-Tvj
Here is an example that will prove useful when there are many enumerations. It uses structures in Golang, and draws upon Object Oriented Principles to tie them all together in a neat little bundle. None of the underlying code will change when a new enumeration is added or deleted. The process is:
Define an enumeration structure for enumeration items: EnumItem. It has an integer and string type.
Define the enumeration as a list of enumeration items: Enum
Build methods for the enumeration. A few have been included:
enum.Name(index int): returns the name for the given index.
enum.Index(name string): returns the name for the given index.
enum.Last(): returns the index and name of the last enumeration
Add your enumeration definitions.
Here is some code:
type EnumItem struct {
index int
name string
}
type Enum struct {
items []EnumItem
}
func (enum Enum) Name(findIndex int) string {
for _, item := range enum.items {
if item.index == findIndex {
return item.name
}
}
return "ID not found"
}
func (enum Enum) Index(findName string) int {
for idx, item := range enum.items {
if findName == item.name {
return idx
}
}
return -1
}
func (enum Enum) Last() (int, string) {
n := len(enum.items)
return n - 1, enum.items[n-1].name
}
var AgentTypes = Enum{[]EnumItem{{0, "StaffMember"}, {1, "Organization"}, {1, "Automated"}}}
var AccountTypes = Enum{[]EnumItem{{0, "Basic"}, {1, "Advanced"}}}
var FlagTypes = Enum{[]EnumItem{{0, "Custom"}, {1, "System"}}}
Refactored https://stackoverflow.com/a/17989915/863651 to make it a bit more readable:
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
}
This is a safe way to implement enum in golang:
package main
import (
"fmt"
)
const (
MALE = _gender(1)
FEMALE = _gender(2)
RED = _color("RED")
GREEN = _color("GREEN")
BLUE = _color("BLUE")
)
type Gender interface {
_isGender()
Value() int
}
type _gender int
func (_gender) _isGender() {}
func (_g _gender) Value() int {
return int(_g)
}
type Color interface {
_isColor()
Value() string
}
type _color string
func (_color) _isColor() {}
func (_c _color) Value() string {
return string(_c)
}
func main() {
genders := []Gender{MALE, FEMALE}
colors := []Color{RED, GREEN, BLUE}
fmt.Println("Colors =", colors)
fmt.Println("Genders =", genders)
}
The output:
Colors = [RED GREEN BLUE]
Genders = [1 2]
Also, this is a pretty effective way to store different roles in one location in a byte, where the first value is set to 1, bit shifted by an iota.
package main
import "fmt"
const (
isCaptain = 1 << iota
isTrooper
isMedic
canFlyMars
canFlyJupiter
canFlyMoon
)
func main() {
var roles byte = isCaptain | isMedic | canFlyJupiter
//Prints a binary representation.
fmt.Printf("%b\n", roles)
fmt.Printf("%b\n", isCaptain)
fmt.Printf("%b\n", isTrooper)
fmt.Printf("%b\n", isMedic)
fmt.Printf("Is Captain? %v\n", isCaptain&roles == isCaptain)
fmt.Printf("Is Trooper? %v", isTrooper&roles == isTrooper)
}
I created the enum this way. Suppose we need an enum representing gender. Possible values are Male, Female, Others
package gender
import (
"fmt"
"strings"
)
type Gender struct {
g string
}
var (
Unknown = Gender{}
Male = Gender{g: "male"}
Female = Gender{g: "female"}
Other = Gender{g: "other"}
)
var genders = []Gender{
Unknown,
Male,
Female,
Other,
}
func Parse(code string) (parsed Gender, err error) {
for _, g := range genders {
if g.g == strings.ToLower(code) {
if g == Unknown {
err = fmt.Errorf("unknown gender")
}
parsed = g
return
}
}
parsed = Unknown
err = fmt.Errorf("unknown gender", code)
return
}
func (g Gender) Gender() string {
return g.g
}
A simpler way I have found to work.
const (
Stake TX = iota
Withdraw)
type TX int
func (t TX) String() string {
return [...]string{"STAKE", "WITHDRAW"}[t]}
log.Println(Stake.String()) --> STAKE
Related
Bit stuck.
I'm trying to work out how to get the bitmask values from a const with go enumeration. For example, if key is 5, which is 0101 bits, it would be dog and fish. What is the easiest way to get the bit values (1,2,4,8,16, 32, 64 etc) so I can select the string values and return the set of animals?
type Key int
const (
Dog Key = 1 << iota
Cat
Fish
Horse
Snake
Rabbit
Lion
Rino
Hedgehog
)
Been reading but I can't work this out.
Declare a slice of strings where the strings correspond to the constant names:
var animalNames = []string{
"Dog",
"Cat",
"Fish",
"Horse",
"Snake",
"Rabbit",
"Lion",
"Rino",
"Hedgehog",
}
To get the names for the bits, loop through the names. If the corresponding bit is set, add the name to the result:
func Names(k Key) []string {
var result []string
for i := 0; i < len(animalNames); i++ {
if k&(1<<uint(i)) != 0 {
result = append(result, animalNames[i])
}
}
return result
}
Run it on the playground.
If you change the the constants to be bit indexes instead of bit values, then you can use the stringer utility to create a func (k Key) String() string. Here's the code for this change:
type Key uint
const (
Dog Key = iota
Cat
Fish
Horse
Snake
Rabbit
Lion
Rino
Hedgehog
)
//go:generate stringer -type=Key
func Names(k Key) []string {
var result []string
for animal := Dog; animal <= Hedgehog; animal++ {
if k&(1<<animal) != 0 {
result = append(result, animal.String())
}
}
return result
}
Creating bitmask values with iota
Iota can be very useful when creating a bitmask. For instance, to represent the state of a network connection which may be secure, authenticated, and/or ready, we might create a bitmask like the following:
package main
import "fmt"
const (
Secure = 1 << iota // 0b001
Authn // 0b010
Ready // 0b100
)
// 0b011: Connection is secure and authenticated, but not yet Ready
func main() {
ConnState := Secure | Authn
fmt.Printf(` Secure: 0x%x (0b%03b)
Authn: 0x%x (0b%03b)
ConnState: 0x%x (0b%03b)
`, Secure, Secure, Authn, Authn, ConnState, ConnState)
}
This question already has an answer here:
golang how can I use struct name as map key
(1 answer)
Closed 9 months ago.
We have a following function:
func (h *Handler) Handle(message interface{}) error {
//here there is a switch for different messages
switch m := message.(type) {
}
}
This signature is given and can't be changed. There are around 20 different message types the handler processes.
Now, there are some of these messages (around 4) which need special post-processing. In a different package.
Thus, I am thinking to do this like this:
func (h *Handler) Handle(message interface{}) error {
//here there is a switch for different messages
switch m := message.(type) {
}
//only post-process if original message processing succeeds
postProcessorPkg.Process(message)
}
Now, in the Process function, I want to quickly lookup if the message type is indeed of the ones we need postprocessing for. I don't want to do a switch again here. There are many handlers, in different packages, with varying amount of message types, and it should be generic.
So I was thinking of registering the message type in the postprocessor and then just do a lookup:
func (p *Postprocessor) Register(msgtype interface{}) {
registeredTypes[msgtype] = msgtype
}
and then
func (p *Postprocessor) Process(msgtype interface{}) error {
if ok := registeredTypes[msgtype]; !ok {
return errors.New("Unsupported message type")
}
prop := GetProp(registeredTypes[msgtype])
doSmthWithProp(prop)
}
This will all not work now because I can only "register" instances of the message, not the message type itself, as far as I know. Thus the map would only match a specific instance of a message, not its type, which is what I need.
So I guess this needs redesign. I can completely ditch the registering and the map lookup, but
I can't change the Handle function to a specific type (signature will need to remain message interface{}
I would like to avoid to have to use reflect, just because I will have a hard time defending such a solution with some colleagues.
As there is no possibility to set a type as the map key, I finally decided to implement the following solution, which is based on #Chrono Kitsune 's solution:
type Postprocess interface {
NeedsPostprocess() bool
}
type MsgWithPostProcess struct {}
func (p *MsgWithPostProcess) NeedsPostprocess() bool {
return true
}
type Msg1 struct {
MsgWithPostProcess
//other stuff
}
type Msg2 struct {
MsgWithPostProcess
//other stuff
}
type Msg3 struct {
//no postprocessing needed
}
func (p *Postprocessor) Process(msgtype interface{}) error {
if _, ok := msgtype.(Postprocess); ok {
//do postprocessing
}
}
As of my simple test I did, only Msg1 and Msg2 will be postprocessed, but not Msg3, which is what I wanted.
This question was the first hit I found on Google but the title is somewhat misleading. So I'll leave this here to add some food for thought with the title of the question in mind.
First, the issue with maps is that its key must be a comparable value. This is why for example a slice cannot be used is a map key. A slice is not comparable and is therefore not allowed. You can use an array (fixed sized slice) but not a slice for the same reason.
Second, you have in the reflect.TypeOf(...).String()a way to get a canonical string representation for types. Though it is not unambiguous unless you include the package path, as you can see here.
package main
import (
"fmt"
s2 "go/scanner"
"reflect"
s1 "text/scanner"
)
type X struct{}
func main() {
fmt.Println(reflect.TypeOf(1).String())
fmt.Println(reflect.TypeOf(X{}).String())
fmt.Println(reflect.TypeOf(&X{}).String())
fmt.Println(reflect.TypeOf(s1.Scanner{}).String())
fmt.Println(reflect.TypeOf(s2.Scanner{}).String())
fmt.Println(reflect.TypeOf(s1.Scanner{}).PkgPath(), reflect.TypeOf(s1.Scanner{}).String())
fmt.Println(reflect.TypeOf(s2.Scanner{}).PkgPath(), reflect.TypeOf(s2.Scanner{}).String())
}
int
main.X
*main.X
scanner.Scanner
scanner.Scanner
text/scanner scanner.Scanner
go/scanner scanner.Scanner
https://play.golang.org/p/NLODZNdik6r
With this information, you can (if you feel so inclined) create a map which let's go from a reflect.Type to a key and back again, like this.
package main
import (
"fmt"
s2 "go/scanner"
"reflect"
s1 "text/scanner"
)
type TypeMap struct {
m []reflect.Type
}
func (m *TypeMap) Get(t reflect.Type) int {
for i, x := range m.m {
if x == t {
return i
}
}
m.m = append(m.m, t)
return len(m.m) - 1
}
func (m *TypeMap) Reverse(t int) reflect.Type {
return m.m[t]
}
type X struct{}
func main() {
var m TypeMap
fmt.Println(m.Get(reflect.TypeOf(1)))
fmt.Println(m.Reverse(0))
fmt.Println(m.Get(reflect.TypeOf(1)))
fmt.Println(m.Reverse(0))
fmt.Println(m.Get(reflect.TypeOf(1)))
fmt.Println(m.Reverse(0))
fmt.Println(m.Get(reflect.TypeOf(X{})))
fmt.Println(m.Reverse(1))
fmt.Println(m.Get(reflect.TypeOf(&X{})))
fmt.Println(m.Reverse(2))
fmt.Println(m.Get(reflect.TypeOf(s1.Scanner{})))
fmt.Println(m.Reverse(3).PkgPath(), m.Reverse(3))
fmt.Println(m.Get(reflect.TypeOf(s2.Scanner{})))
fmt.Println(m.Reverse(4).PkgPath(), m.Reverse(4))
}
0
int
0
int
0
int
1
main.X
2
*main.X
3
text/scanner scanner.Scanner
4
go/scanner scanner.Scanner
In the above case I'm assuming that N is small. Also note the use of the identity of reflect.TypeOf, it will return the same pointer for the same type on subsequent calls.
If N is not small, you may want to do something a bit more complex.
package main
import (
"fmt"
s2 "go/scanner"
"reflect"
s1 "text/scanner"
)
type PkgPathNum struct {
PkgPath string
Num int
}
type TypeMap struct {
m map[string][]PkgPathNum
r []reflect.Type
}
func (m *TypeMap) Get(t reflect.Type) int {
k := t.String()
xs := m.m[k]
pkgPath := t.PkgPath()
for _, x := range xs {
if x.PkgPath == pkgPath {
return x.Num
}
}
n := len(m.r)
m.r = append(m.r, t)
xs = append(xs, PkgPathNum{pkgPath, n})
if m.m == nil {
m.m = make(map[string][]PkgPathNum)
}
m.m[k] = xs
return n
}
func (m *TypeMap) Reverse(t int) reflect.Type {
return m.r[t]
}
type X struct{}
func main() {
var m TypeMap
fmt.Println(m.Get(reflect.TypeOf(1)))
fmt.Println(m.Reverse(0))
fmt.Println(m.Get(reflect.TypeOf(X{})))
fmt.Println(m.Reverse(1))
fmt.Println(m.Get(reflect.TypeOf(&X{})))
fmt.Println(m.Reverse(2))
fmt.Println(m.Get(reflect.TypeOf(s1.Scanner{})))
fmt.Println(m.Reverse(3).PkgPath(), m.Reverse(3))
fmt.Println(m.Get(reflect.TypeOf(s2.Scanner{})))
fmt.Println(m.Reverse(4).PkgPath(), m.Reverse(4))
}
0
int
1
main.X
2
*main.X
3
text/scanner scanner.Scanner
4
go/scanner scanner.Scanner
https://play.golang.org/p/2fiMZ8qCQtY
Note the subtitles of pointer to type, that, X and *X actually are different types.
I am trying to compare these two interfaces together as a function. It is working as far as I am concerned. I am sending a struct in A interface{} and map[string]interface{} in B, having the same values but when being compared with reflect they are not resulting to be the same. I would like to be able to convert the map[string]interface{} into a struct interface inside this function so that my tests can get shorter. I have tried using https://github.com/mitchellh/copystructure, but does not work inside this function.(from outside it works though:
var m map[string]interface{}
var something StructType
err := mapstructure.Decode(m, &something)
if err....
and then i send the something in the B interface)
below is the function to compare the interfaces. You can copy and paste and see how it works for yourself
package main
import (
"log"
"reflect"
)
type Something struct {
Name string
Age int
Male bool
Cars []string
}
func main() {
var s Something
s.Name = "joe"
s.Male = true
s.Age = 20
s.Cars = []string{"Fordd", "Chevy", "Mazda"}
m := make(map[string]interface{})
m["Name"] = "joe"
m["Male"] = true
m["Age"] = 20
m["Cars"] = []string{"Fordd", "Chevy", "Mazda"}
//with map[string]interface{} although the same values it does not work
log.Println("Are these the same: ", CompareData(s, m))
//with struct of same type it works
var s2 Something
s2.Name = "joe"
s2.Male = true
s2.Age = 20
s2.Cars = []string{"Fordd", "Chevy", "Mazda"}
log.Println("Are these the same: ", CompareData(s, s2))
}
func CompareData(A interface{}, B interface{}) bool {
a := reflect.ValueOf(A)
b := reflect.ValueOf(B)
akind := a.Kind().String()
bkind := a.Kind().String()
if akind == "slice" && bkind == "slice" {
for i := 0; i < a.Len(); i++ {
// log.Println("they are sliced")
CompareData(a.Index(i).Interface(), b.Index(i).Interface())
// log.Println("\n", a.Index(i).Interface(), "\n", b.Index(i).Interface())
}
// t.Fatal("this is a slice you need to iterate over the values")
} else {
// log.Println("\n\n", A, "\n", B)
if !reflect.DeepEqual(a.Interface(), b.Interface()) {
log.Println("These should be equal\nSuccessData:\t", a.Interface(), "\nData:\t\t", b.Interface())
return false
}
// log.Println("\nA:\t", A, "\nB:\t", B)
}
return true
}
I am new to Golang and would like to model physical devices for measuring quantities such as light intensity, mass, electric current and so forth. So as a starting point I will define a device struct as follows:
const (
// Light can be measured in the form of luminosity
Light = 1<< iota
Mass
ElectricalCurrent
)
type PhysicalDevice struct{
Owner string
ID string
Description string
}
I am a confused now on how to express the device's capabilities (what it can measure) and the units of measurement. For example I would like to express that a physical device can measure electrical currents in amperes. However, I also want to express that a PhysicalDevice can measure more than one quantity. For example it could measure electrical current and temperature.
The PhysicalDevice's capabilities are not known in advance and can contain an arbitrary combination of capabilities.
I was thinking of using something equivalent to a C++ bitset for expressing the physical quantities a device can measure (would this be the right approach in the first place?).
I did not find the Go bitset type and not sure how to express that. I also need to map the measured physical quantity to a corresponding unit.
You should understand that trying to replicate another language's features in Go is generally regarded as a bad idea. There is a 'go' way of doing things.
You might want to consider iota and bitmask operations like this example on the Go playground. I have included the code here as well (in all its plagiarized glory):
package main
import "fmt"
func main() {
TestAddFlag()
TestHasFlag()
TestClearFlag()
TestToggleFlag()
fmt.Println("all tests passed")
}
type Bitmask uint32
func (f Bitmask) HasFlag(flag Bitmask) bool { return f&flag != 0 }
func (f *Bitmask) AddFlag(flag Bitmask) { *f |= flag }
func (f *Bitmask) ClearFlag(flag Bitmask) { *f &= ^flag }
func (f *Bitmask) ToggleFlag(flag Bitmask) { *f ^= flag }
const (
TESTFLAG_ONE Bitmask = 1 << iota
TESTFLAG_TWO
TESTFLAG_THREE
)
func TestAddFlag() {
var mainFlag Bitmask = TESTFLAG_TWO
mainFlag.AddFlag(TESTFLAG_THREE)
if mainFlag&(1<<TESTFLAG_THREE) != 0 {
panic("failed")
}
}
func TestClearFlag() {
var mainFlag Bitmask = TESTFLAG_ONE | TESTFLAG_THREE
mainFlag.ClearFlag(TESTFLAG_THREE)
if mainFlag&(1<<TESTFLAG_ONE) != 0 {
panic("failed")
}
}
func TestHasFlag() {
var mainFlag Bitmask = TESTFLAG_ONE | TESTFLAG_THREE
if !mainFlag.HasFlag(TESTFLAG_THREE) {
panic("failed")
}
}
func TestToggleFlag() {
flag := TESTFLAG_ONE | TESTFLAG_THREE
flag.ToggleFlag(TESTFLAG_ONE)
if flag.HasFlag(TESTFLAG_ONE) {
panic("failed")
}
flag.ToggleFlag(TESTFLAG_ONE)
if !flag.HasFlag(TESTFLAG_ONE) {
panic("failed")
}
}
This approach is commonly used in the standard library.
Define the capabilities using = 1 << iota:
const (
Light Capability = 1 << iota
Mass
ElectricalCurrent
Energy
)
Notice that the expression is only needed on the first constant. The same expression (but with an updated value of iota) will be used on the consecutive lines in the same group.
Here's a complete working example:
package main
import (
"fmt"
"strings"
)
type Capability int
const (
// Light can be measured in the form of luminosity
Light Capability = 1 << iota
Mass
ElectricalCurrent
Energy
)
func (c Capability) String() string {
var caps []string
if c&Light > 0 {
caps = append(caps, "Light")
}
if c&Mass > 0 {
caps = append(caps, "Mass")
}
if c&ElectricalCurrent > 0 {
caps = append(caps, "ElectricalCurrent")
}
if c&Energy > 0 {
caps = append(caps, "Energy")
}
return strings.Join(caps, "|")
}
type PhysicalDevice struct {
Owner string
ID string
Description string
Capability Capability
}
func (pd PhysicalDevice) String() string {
return "Owner: " + pd.Owner + "\n" +
"ID: " + pd.ID + "\n" +
"Description: " + pd.Description + "\n" +
"Capability: " + pd.Capability.String() + "\n"
}
func main() {
dev := PhysicalDevice{
Owner: "Albert Einstein",
ID: "E=mc^2",
Description: "My well-known formula as a device",
Capability: Energy | Mass | Light,
}
fmt.Println(dev)
}
The code can be found on The Go Playground.
I have a struct like this
import (
"fmt"
)
type Node struct {
m []string
o []string
}
func main() {
var mm = []string{"abc", "def"}
var oo = []string{"111", "222"}
var v = Node{m: mm, o: oo}
for _, d := range []interface{}{v.m, v.o} {
fmt.Println(d)
}
}
The output I get is,
[abc def]
[111 222]
My desired output is,
abc,111
def,222
I don't want to use reflect package because, I want to use native go built-ins as much as possible. If it becomes too burdensome I will fall back on reflect package.
Edit: I just realized my output doesn't match yours, do you want the letters paired with the numbers? If so then you'll need to re-work what you have.
You can use strings.Join and a type switch statement to accomplish this:
https://play.golang.org/p/ygtdxv02uK
package main
import (
"fmt"
"strings"
)
type Node struct {
m []string
o []string
p []int
}
func main() {
var mm = []string{"abc", "def"}
var oo = []string{"111", "222"}
var pp = []int{1, 2, 3}
var v = Node{m: mm, o: oo, p: pp}
for _, d := range []interface{}{v.m, v.o, v.p} {
switch d.(type) {
case []string:
fmt.Println(strings.Join(d.([]string), ","))
default:
fmt.Println(d)
}
}
}
The output is:
abc,def
111,222
[1 2 3]
Is there a reason you don't want to use the reflect package? like Iterate through a struct in Go and Iterate Over String Fields in Struct ?
From the former question, it seems like, yeah you can iterate without reflect by iterating through an interface of the fields, https://play.golang.org/p/bPWUII_D7q
package main
import (
"fmt"
)
type Foo struct {
num int
str string
}
func main() {
foo := &Foo{42, "Hello"} // struct with fields of many types...
for _, data := range []interface{}{foo.num, foo.str} {
fmt.Println(data)
}
}
Here is what I did,
package main
import (
"fmt"
)
type Node struct {
m []string
o []string
}
func main() {
var mm = []string{"abc", "def"}
var oo = []string{"111", "222"}
var v = Node{m: mm, o: oo}
for i := range v.m {
fmt.Println(v.m[i],v.o[i])
}
}
This gives me my desired output. Just one thing is I have to write v.m so I suppose I should still use reflect package.