Я новичок на Голанге и хотел бы моделировать физические устройства для измерения таких величин, как сила света, масса, электрический ток и т. Д. Итак, в качестве отправной точки я определю структуру устройства следующим образом:

const (
    // Light can be measured in the form of luminosity
    Light             = 1<< iota
    Mass             
    ElectricalCurrent 
)

type PhysicalDevice struct{
   Owner       string
   ID          string
   Description string
}

Я сейчас не понимаю, как выразить возможности устройства (что оно может измерять) и единицы измерения. Например, я хотел бы сказать, что физическое устройство может измерять электрические токи в амперах. Однако я также хочу сказать, что PhysicalDevice может измерять более одной величины. Например, он может измерять электрический ток и температуру.

Возможности PhysicalDevice не известны заранее и могут содержать произвольную комбинацию возможностей.

Я думал об использовании чего-то эквивалентного битовому набору C ++ для выражения физических величин, которые может измерить устройство (будет ли это вообще правильный подход?).

Я не нашел битового типа Go и не знал, как это выразить. Мне также нужно сопоставить измеренную физическую величину с соответствующей единицей.

go
0
BigONotation 1 Янв 2018 в 17:34

2 ответа

Лучший ответ

Вы должны понимать, что попытка воспроизвести возможности другого языка в Go обычно считается плохой идеей. Есть простой способ делать что-то.

Возможно, вы захотите рассмотреть iota и операции с битовой маской, такие как этот пример на игровой площадке Go . Я также включил сюда код (во всей красе плагиата):

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

Этот подход обычно используется в стандартной библиотеке.

1
Dan Esparza 1 Янв 2018 в 15:51

Определите возможности, используя = 1 << iota:

const (
  Light Capability = 1 << iota
  Mass
  ElectricalCurrent
  Energy
)

Обратите внимание, что выражение необходимо только для первой константы. То же выражение (но с обновленным значением iota) будет использоваться в следующих друг за другом строках одной и той же группы.

Вот полный рабочий пример:

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

Код можно найти на игровой площадке Go.

2
md2perpe 1 Янв 2018 в 15:47