HowtoGo
Home / Basics / Bitwise Operators
Basics

Bitwise Operators

Go's six bitwise operators, including &^, which clears bits, plus shifting, masks, flag sets built with iota, and the math/bits helpers.

1 See the bits inside an integer

Every integer is a row of bits. 12 is 1100, and 10 is 1010. A bitwise operator lines the two rows up and works down them a column at a time.

Print with %b to see the bits, and pad with a width so the rows line up.

a, b := 12, 10

fmt.Printf("%04b\n", a) // 1100
fmt.Printf("%04b\n", b) // 1010

2 Combine bits with AND, OR, and XOR

AND keeps a bit only where both sides have it. OR keeps it where either side does. XOR keeps it where exactly one side does.

a & b // 1000, the one column where both are 1
a | b // 1110, every column where either is 1
a ^ b // 0110, the columns where they disagree

3 Flip every bit with NOT

Go writes NOT with the same symbol as XOR. One operand means NOT, two means XOR.

On a signed type the result looks odd until you remember the sign bit flips too, which is why ^i equals -i-1.

var u uint8 = 12
fmt.Printf("%08b", ^u) // 11110011, which is 243

i := 12
fmt.Println(^i)      // -13

4 Clear bits with AND NOT

AND NOT keeps everything on the left except the bits the right has set. Elsewhere you would write a & ^b. In Go it is one operator.

a &^ b // 0100

// b is 1010, so bits 1 and 3 get cleared from a (1100),
// leaving only bit 2.

5 Shift bits left and right

Left by one doubles the value, right by one halves it. Shifting past the width of the type leaves zero rather than wrapping.

12 << 1 // 24, bits 1100 become 11000
12 >> 2 // 3,  bits 1100 become 0011

var x uint8 = 1
x << 9  // 0, shifted clean off the end

6 Watch the sign on a right shift

This is the one place the signedness of your type changes the answer. Signed values keep their sign, so a negative stays negative.

var neg int8 = -8
neg >> 1 // -4, the sign bit is copied in

var pos uint8 = 248
pos >> 1 // 124, zeros are shifted in

7 Build a flag set with iota

Shifting 1 by iota gives every constant its own bit, so one integer can carry a whole set of on-off options.

type Perm uint8

const (
    Read  Perm = 1 << iota // 001
    Write                    // 010
    Exec                     // 100
)

p := Read | Exec       // 101

p |= Write             // set:    111
p &^= Read             // clear:  110
p ^= Exec              // toggle: 010

if p&Write != 0 {   // test
    fmt.Println("writable")
}

8 Pull out bits with a mask

AND against a mask keeps only the columns the mask has set. Testing the lowest bit is the usual even-or-odd check.

0xAB & 0x0F   // 0xB, the low four bits
(0xAB >> 4) & 0x0F // 0xA, the high four

n & 1 == 0   // true when n is even
Result

Six operators over one integer: & keeps, | adds, ^ differs or flips, &^ clears, and the two shifts move everything along.

Operator reference

Operators
VerbPrintsExample
&AND. A bit survives only where both sides have it set.
1100 & 1010 1000
|OR. A bit is set where either side has it set.
1100 | 1010 1110
^XOR, between two values. A bit is set where the sides differ.
1100 ^ 1010 0110
^xNOT, with one operand. Flips every bit.
^uint8(12) 243
&^AND NOT, or bit clear. Keeps the left bits, drops any the right has set.
1100 &^ 1010 0100
&lt;&lt;Shift left. Every bit moves up, zeros fill in behind.
1100 << 1 11000
&gt;&gt;Shift right. Every bit moves down.
1100 >> 2 0011
Assignment forms
VerbPrintsExample
&=Keep only the bits also set in the mask.
p &= mask p = p & mask
|=Turn a flag on.
p |= Write p = p | Write
^=Toggle a flag.
p ^= Exec p = p ^ Exec
&^=Turn a flag off.
p &^= Read p = p &^ Read
&lt;&lt;=Shift left in place.
x <<= 3 x = x << 3
&gt;&gt;=Shift right in place.
x >>= 3 x = x >> 3

The math/bits package

Counting and rearranging bits by hand is fiddly, so the standard library does it. Each function comes in 8, 16, 32, and 64-bit versions, plus a plain uint one.

FunctionDescription
OnesCount8(x uint8) int
bits.OnesCount8(12) // 2
How many bits are set.
LeadingZeros8(x uint8) int
bits.LeadingZeros8(12) // 4
Zero bits above the highest set bit.
TrailingZeros8(x uint8) int
bits.TrailingZeros8(12) // 2
Zero bits below the lowest set bit.
Len8(x uint8) int
bits.Len8(12) // 4
Bits needed to hold the value.
Reverse8(x uint8) uint8
bits.Reverse8(12) // 48
Reverses the bit order.
RotateLeft8(x uint8, k int) uint8
bits.RotateLeft8(12, 1) // 24
Rotates left, wrapping bits round the end.
UintSize
bits.UintSize // 64
Bits in a uint on this platform, 32 or 64.