I didn't find a BitSet package in Go, so I tried to implement it. I'd like to use a array of uint64 to store the bits.
I need the number of bits to allocate the uint64 array. With Java, I can define a constructor that takes an integer. While Go doesn't provide constructor, how can I properly initialize the BitSet 'object' when user call new()?
If you use a []uint64 slice to store your data, then the zero slice could function as the empty BitSet. In fact appending to a nil slice allocates a new array for you, although the Language Specification doesn't appear to guarantee that. With that kind of setup, new(BitSet) would be immediately usable. Example:
bitset.go:
package bitset
const size = 64
type bits uint64
// BitSet is a set of bits that can be set, cleared and queried.
type BitSet []bits
// Set ensures that the given bit is set in the BitSet.
func (s *BitSet) Set(i uint) {
if len(*s) < int(i/size+1) {
r := make([]bits, i/size+1)
copy(r, *s)
*s = r
}
(*s)[i/size] |= 1 << (i % size)
}
// Clear ensures that the given bit is cleared (not set) in the BitSet.
func (s *BitSet) Clear(i uint) {
if len(*s) >= int(i/size+1) {
(*s)[i/size] &^= 1 << (i % size)
}
}
// IsSet returns true if the given bit is set, false if it is cleared.
func (s *BitSet) IsSet(i uint) bool {
return (*s)[i/size]&(1<<(i%size)) != 0
}
bitset_test.go:
package bitset
import "fmt"
func ExampleBitSet() {
s := new(BitSet)
s.Set(13)
s.Set(45)
s.Clear(13)
fmt.Printf("s.IsSet(13) = %t; s.IsSet(45) = %t; s.IsSet(30) = %t\n",
s.IsSet(13), s.IsSet(45), s.IsSet(30))
// Output: s.IsSet(13) = false; s.IsSet(45) = true; s.IsSet(30) = false
}
Declare bitSet as a private struct:
type bitSet struct {
len int
array []uint64
}
Expose the interface BitSet:
type BitSet interface {
Has(pos int) bool
Add(pos int) bool
Len() int
}
Also expose a function NewBitSet:
func NewBitSet(len int) BitSet {
return &bitSet{len, make(uint64, (len+7) / 8) }
}
This is a Go way for encapsulation: share an interface, not the implementation.
The short answer is, you can't properly initialize the BitSet
object when a client calls new
().
The best thing you can do is make it so that your BitSet
's zero value is valid. This is what types like list.List
, sync.Mutex
, and big.Int
do. This way you know that it's impossible for a client to get an invalid value.
The next best thing you can do is create a constuctor-like function (named NewBitSet
in this case) and expect clients to call it.
Go's standard big.Int
can be used as a bit set:
package main
import (
"fmt"
"math/big"
)
func main() {
var bits big.Int
for i := 1000; i < 2000; i++ {
bits.SetBit(&bits, i, 1)
}
for i := 0; i < 10000; i++ {
if bits.Bit(i) != 0 {
fmt.Println(i)
}
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.