ZetCode

Golang uint16 type

last modified May 8, 2025

This tutorial explains how to use the uint16 built-in type in Go. We'll cover basic concepts with practical examples of working with 16-bit unsigned integers.

The uint16 type represents 16-bit unsigned integers in Go. It can store values from 0 to 65535. This type is useful when memory efficiency is important and the value range is known.

In Go, uint16 is part of the family of unsigned integer types. It's commonly used in binary protocols, network programming, and embedded systems where exact size matters.

Basic uint16 declaration and usage

The simplest use of uint16 involves variable declaration and basic arithmetic operations. This example shows fundamental uint16 usage.

basic_uint16.go
package main

import "fmt"

func main() {

    var a uint16 = 1000
    var b uint16 = 2000
    sum := a + b
    
    fmt.Printf("a: %d, b: %d, sum: %d\n", a, b, sum)
    fmt.Printf("Type of sum: %T\n", sum)
    
    // Division example
    quotient := b / a
    fmt.Printf("2000 / 1000 = %d\n", quotient)
}

The example demonstrates basic arithmetic with uint16 values. Note that all operations stay within the uint16 type unless explicitly converted.

Handling uint16 overflow

Since uint16 has a fixed range, overflow can occur. This example shows how Go handles uint16 overflow situations.

overflow_uint16.go
package main

import "fmt"

func main() {

    max := uint16(65535)
    fmt.Println("Max uint16:", max)
    
    // This would overflow
    // next := max + 1 // Compile-time error if uncommented
    
    // Runtime overflow wraps around
    next := max
    next++
    fmt.Println("After overflow:", next)
    
    // Underflow example
    zero := uint16(0)
    zero--
    fmt.Println("After underflow:", zero)
}

Go handles uint16 overflow by wrapping around. The value 65535 + 1 becomes 0, and 0 - 1 becomes 65535. This is standard behavior for unsigned integers.

Using uint16 in binary operations

The uint16 type is particularly useful for bitwise operations. This example demonstrates common bit manipulation patterns with uint16.

bitwise_uint16.go
package main

import "fmt"

func main() {

    flags := uint16(0b1010101010101010)
    fmt.Printf("Initial flags: %016b\n", flags)
    
    // Set bit 3
    flags |= 1 << 3
    fmt.Printf("After setting bit 3: %016b\n", flags)
    
    // Clear bit 5
    flags &^= 1 << 5
    fmt.Printf("After clearing bit 5: %016b\n", flags)
    
    // Toggle bit 7
    flags ^= 1 << 7
    fmt.Printf("After toggling bit 7: %016b\n", flags)
    
    // Check bit 10
    if flags&(1<<10) != 0 {
        fmt.Println("Bit 10 is set")
    } else {
        fmt.Println("Bit 10 is not set")
    }
}

Bitwise operations are efficient with uint16. The example shows setting, clearing, toggling, and checking individual bits in a uint16 value.

uint16 in network programming

The uint16 type is commonly used in network programming for port numbers and protocol fields. This example demonstrates uint16 in a network context.

network_uint16.go
package main

import (
    "encoding/binary"
    "fmt"
    "net"
)

func main() {

    // Representing a port number
    port := uint16(8080)
    fmt.Printf("Port number: %d\n", port)
    
    // Converting to network byte order (big-endian)
    buf := make([]byte, 2)
    binary.BigEndian.PutUint16(buf, port)
    fmt.Printf("Network byte order: % x\n", buf)
    
    // Parsing back from network byte order
    restoredPort := binary.BigEndian.Uint16(buf)
    fmt.Printf("Restored port: %d\n", restoredPort)
    
    // Common network constants
    fmt.Printf("HTTP port: %d, HTTPS port: %d\n", 80, 443)
}

Network protocols often use uint16 for port numbers and similar fields. The binary package helps with byte order conversions.

uint16 in arrays and slices

Working with collections of uint16 values demonstrates memory efficiency. This example shows uint16 arrays and slices.

array_uint16.go
package main

import (
    "fmt"
    "unsafe"
)

func main() {

    // Array of uint16 values
    data := [5]uint16{10, 20, 30, 40, 50}
    fmt.Println("Array:", data)
    
    // Slice of uint16 values
    slice := data[1:4]
    fmt.Println("Slice:", slice)
    
    // Memory usage comparison
    var ui16 uint16
    var ui32 uint32
    fmt.Printf("Size of uint16: %d bytes\n", unsafe.Sizeof(ui16))
    fmt.Printf("Size of uint32: %d bytes\n", unsafe.Sizeof(ui32))
    
    // Processing slice elements
    sum := uint16(0)
    for _, v := range slice {
        sum += v
    }
    fmt.Println("Sum of slice elements:", sum)
}

Using uint16 in arrays and slices can save memory compared to larger integer types. The example shows declaration, slicing, and iteration.

Source

Go language specification

This tutorial covered the uint16 type in Go with practical examples of its usage in various programming contexts.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Golang tutorials.