在golang中使用bitsets来表示功能

问题描述 投票:0回答:2

我是Golang的新手,希望为物理设备建模,以测量光强度,质量,电流等数量。因此,作为一个起点,我将定义一个设备结构如下:

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 ++ bitset相当的东西来表示设备可以测量的物理量(这首先是正确的方法吗?)。

我没有找到Go bitset类型,也不确定如何表达。我还需要将测量的物理量映射到相应的单位。

go
2个回答
1
投票

你应该明白,试图在Go中复制另一种语言的功能通常被认为是一个坏主意。有一种“去”的做事方式。

你可能想要考虑iota和像this example on the Go playground这样的位掩码操作。我也在这里包含了代码(在所有剽窃的荣耀中):

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

这种方法是commonly used in the standard library


2
投票

使用= 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)
}

代码可以在The Go Playground上找到。

© www.soinside.com 2019 - 2024. All rights reserved.