tags:

views:

158

answers:

2

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

+1  A: 

The short answer is, you can't properly initialize the BitSet object when a user calls new().

The idiomatic way to do this is to create a function that returns a new BitSet object. For example, look at the list package. To create a new List, you'd call list.New() and that call would return a new List object. Because there are unexported fields in the list structure, there's not much use in creating a List with new(), as you'd be unable to initialize some fields.

Evan Shaw
Then I can call List.New() and not new(List)?For a new package, how can I know how to create a new object?
Stephen Hsu
I think that's right, although I might be remembering wrong. You wouldn't want to call new(List) even if it's allowed since you won't be able to properly initialize the object. You can figure out how to create a new object the same way you'd figure out how to do anything else within a package: read the documentation. Usually these constructor-like functions will have the word "New" in them, at least.
Evan Shaw
It turns out you can create an object with unexported fields via new(). It just doesn't seem very useful, unless that object has some kind of initialization function you can call on it.
Evan Shaw
+3  A: 

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.

Ivan Krasin
I don't fully agree with this solution. I think a bitset is too specific to be an interface. It allows you to have different bitsets that implement the same interface, but do you really need such a thing? It seems to me that you can probably come up with a bitset implementation that will work well for pretty much any use and just always use that. Multiple implementations will likely just confuse people.
Evan Shaw
There are a lot of cases when you need another implementation: large spare bitSet, distributed/transactional bitSet, virtual bitSet (setting/clearing a bit corresponds to some action) and so on.
Ivan Krasin
I feel there are no uniform ways to initialize object in Go. :(new(BitSet), BitSet.New(), NewBitSet(),... How are they related?
Stephen Hsu
BitSet.New() and NewBitSet() are really the same thing with different names, since NewBitSet will necessarily be part of the BitSet package. It might be more correct to say BitSet.NewBitSet(), which seems redundant and is why Go prefers to simply say "New" when a package has the same name as an object type. I think it's safe to say that for packages, you'll usually be using some kind of constructor-like function. It's often the case that there are unexported members of a struct or (like in Ivan's example) there is a completely unexported type that implements an interface.
Evan Shaw
Thanks! Since now I provides BitSet.New() to properly initialize objects, is it possible to disable the new(BitSet) invocation?And if I want to initialize a object by different parameters, I have to define several functions with different names like NewA(), NewB(), NewC()?
Stephen Hsu
I don't think there's any way to disable new(BitSet), aside from doing what Ivan did in not exporting the type. Also, since Go unfortunately does not have overloaded functions or optional function arguments, you will have to create differently named functions for different parameter combinations. I'd recommend making as few such functions as possible.
Evan Shaw
Effective Go (http://golang.org/doc/effective_go.html#generality) explains this technique.
Stephen Hsu
Yes, it's certainly a good technique in the right situation. I just don't believe this is one of those situations, and on that I'll simply agree to disagree.
Evan Shaw