Every integer is stored in binary. Bitwise operations compare or move those bits one by one, without going through regular arithmetic.
Example with a = 12 (1100) and b = 10 (1010):
| Operation | Go | Java | Rule | Result |
|---|---|---|---|---|
| AND | a & b | a & b | 1 if both bits are 1 | 1000 = 8 |
| OR | a | b | a | b | 1 if at least one is 1 | 1110 = 14 |
| XOR | a ^ b | a ^ b | 1 if the bits differ | 0110 = 6 |
| NOT | ^a | ~a | flips every bit | -13 |
| AND NOT | a &^ b | a & ~b | clears in a the bits set in b | 0100 = 4 |
| Left shift | a << 1 | a << 1 | multiplies by 2 | 11000 = 24 |
| Right shift | a >> 1 | a >> 1 | divides by 2 | 0110 = 6 |
Java also has >>>, which shifts right filling with zeros even for negative numbers. In Go the same effect comes from using unsigned types (uint).
Where it shows up in practice
Flags and permissions: several yes/no values stored in a single number. Unix permissions work this way: chmod 755 is 111 101 101 (owner reads, writes, executes; group and others read and execute).
const ( Read = 1 << iota // 001 Write // 010 Exec // 100)
perm := Read | Write // turns on read and write: 011canWrite := perm&Write != 0 // tests a bit: trueperm &^= Write // turns off write: 001static final int READ = 1, WRITE = 1 << 1, EXEC = 1 << 2;
int perm = READ | WRITE;boolean canWrite = (perm & WRITE) != 0;perm &= ~WRITE;Quick tricks: n & 1 tells whether a number is odd; n & (n - 1) == 0 tells whether it is a power of 2 (for n > 0).
Masks: extracting part of a value, like the red channel of a 0xRRGGBB color with (color >> 16) & 0xFF.
See also: Data types.