0

I am reading a piece of code like this (taken from fsnotify):

    type Op uint32

    const (
        Create Op = 1 << iota
        Write
        Remove
        Rename
        Chmod
    )

    ...

    func (op Op) String() string {

    var buffer bytes.Buffer

    if op&Create == Create {
        buffer.WriteString("|CREATE")
    }
    if op&Remove == Remove {
        buffer.WriteString("|REMOVE")
    }
    if op&Write == Write {
        buffer.WriteString("|WRITE")
    }
    if op&Rename == Rename {
        buffer.WriteString("|RENAME")
    }
    if op&Chmod == Chmod {
        buffer.WriteString("|CHMOD")
    }
    if buffer.Len() == 0 {
        return ""
    }
    return buffer.String()[1:] 
}

My newbie question is why someone would use a bitwise AND operation like op&Remove == Remove to actually make a comparison. Why not just compare the op and (Create|Remove|...) values?

trikelef
  • 2,192
  • 1
  • 22
  • 39
  • 5
    Because you can specify more than just one flag to be set. op is a bitpattern with lets say bit 4 signifying "rename" and bit 2 signifiying "write" if someone passes 0001010 this is not equal to Rename which is 0001000 and not equal to Write which is 00000010. To test if the Rename bit is set you have to AND it with Rename and test if the result is nonzero. Comparing to Rename, Write, etc is not important here and could be replaced by != 0. – Volker Sep 25 '18 at 14:25
  • 2
    Do you understand how `iota` works? Do you know what the values of `Create`, `Write`, `Remote`, etc. are? Why you want to use `&` rather than checking for equality might become clearer once you understand that... – jub0bs Sep 25 '18 at 14:25
  • 1
    This might be of some help to you: [Difference between some operators “|”, “^”, “&”, “&^”. Golang](https://stackoverflow.com/questions/28432398/difference-between-some-operators-golang/28433370#28433370). – icza Sep 25 '18 at 14:36
  • Thanks @Volker! Comparing `op&operation` with *not* zero is more straightforward. I though this piece of code `op&operation==operation` was some kind of idiomatism. – trikelef Sep 26 '18 at 07:35

1 Answers1

5

This is an example of bit masking. What they're doing is defining a series of masks (Create, Remove, Write) that are integers 1,2,4,8,16,32,etc. You pass in a single op value, which can have multiple operations, and it figures out which operation to perform based on which bit is flipped. This makes more sense if you think about these numbers in a bitwise pattern. 4 == 00000100, the value for Remove. If you pass in an op code of say, 6, when you compare 00000110 && 00000100 == 00000100 you get true, because the bit that is specific to Remove, the third least significant bit, is 1.

In a less jargony and specific way, this is basically a way to pass in multiple opcodes with one byte. The reason they're doing a bitwise AND and then comparing is because it allows them to check if that specific bit is flipped, while ignoring the rest of the bits.