Der Datentyp int ist in Go ein zentraler Bestandteil für die Arbeit mit Ganzzahlen. Er repräsentiert ganze Zahlen ohne Nachkommastellen und wird häufig für Zählvorgänge, Indizes und mathematische Berechnungen verwendet. Die Größe von int ist plattformabhängig und richtet sich nach der Architektur des Systems. In diesem Artikel werden die Eigenschaften, Einsatzmöglichkeiten und Besonderheiten des int-Typs in Go erläutert und durch praxisnahe Beispiele veranschaulicht.

Einführung

Integer-Datentypen repräsentieren in Go ganze Zahlen. Go bietet eine reichhaltige Palette von Integer-Typen, die sich in ihrer Größe (Anzahl der Bits) und ihrem Wertebereich unterscheiden. Diese Vielfalt ermöglicht es, den optimalen Typ für spezifische Anwendungsfälle zu wählen und dabei sowohl Speichereffizienz als auch Performance zu berücksichtigen.

Go unterscheidet zwischen signed (vorzeichenbehafteten) und unsigned (vorzeichenlosen) Integer-Typen. Signed Integers können sowohl positive als auch negative Werte speichern, während unsigned Integers nur positive Werte (einschließlich Null) aufnehmen können.

Hier ein kleines Beispiel.

Go Beispiel - Vorzeichen
package main

import "fmt"

func main() {
    var signedInt int = -42
    var unsignedInt uint = 42
}

Signed Integer Typ

Signed Integer-Typen verwenden das Zweierkomplement-System zur Darstellung negativer Zahlen. Das höchstwertige Bit (MSB) fungiert als Vorzeichen-Bit, wodurch sich der verfügbare Wertebereich halbiert, aber negative Zahlen dargestellt werden können.

int8 - 8-Bit Signed Integer

Der int8 Typ verwendet 8 Bits zur Speicherung und kann Werte von -128 bis 127 darstellen. Dieser Typ ist besonders nützlich für Anwendungen, wo Speicherplatz kritisch ist und der Wertebereich ausreicht.

Ein kleines Beispiel dazu.

Go Beispiel
package main

import (
    "fmt"
    "math"
)

func main() {
    var small int8 = 127
    var negative int8 = -128

    fmt.Println(small, negative)

    // Grenzbereiche
    fmt.Printf("int8 range: %d bis %d\n", math.MinInt8, math.MaxInt8)
}
Output
127 -128
int8 range: -128 bis 127

int16 - 16-Bit Signed Integer

Der int16 Typ bietet einen Wertebereich von -32.768 bis 32.767 und ist ideal für Anwendungen, die größere Werte als int8 benötigen, aber noch speichersparend bleiben möchten.

Hier ein kleines Beispiel.

Go Beispiel
package main

import (
    "fmt"
    "math"
)

func main() {
    var year int16 = 2025
    var altitude int16 = -400

    fmt.Printf("Jahr: %d\n", year)
    fmt.Printf("Höhe: %d Meter\n", altitude)
    fmt.Printf("int16 range: %d bis %d\n", math.MinInt16, math.MaxInt16)

    // Array von Koordinaten
    coords := [][2]int16{
        {100, 200},
        {-150, 300},
        {0, -50},
    }
    for i, coord := range coords {
        fmt.Printf("Punkt %d: x=%d, y=%d\n", i+1, coord[0], coord[1])
    }
}
Output
Jahr: 2025
Höhe: -400 Meter
int16 range: -32768 bis 32767
Punkt 1: x=100, y=200
Punkt 2: x=-150, y=300
Punkt 3: x=0, y=-50

int32 - 32-Bit Signed Integer

Der int32 Typ (auch als rune bekannt) hat einen Wertebereich von -2.147.483.648 bis 2.147.483.647. Dieser Typ wird häufig für Unicode-Codepoints verwendet und bietet einen ausgewogenen Kompromiss zwischen Speicherverbrauch und Wertebereich.

Ein kleines Beispiel zu diesem Typ.

Go Beispiel
package main

import (
    "fmt"
    "math"
)

func main() {
    var population int32 = 1500000
    var bankBalance int32 = -25000

    fmt.Printf("Stadtbevölkerung: %d\n", population)
    fmt.Printf("Kontostand: %d\n", bankBalance)
    fmt.Printf("int32 range: %d bis %d\n", math.MinInt32, math.MaxInt32)

    // Unicode-Zeichen (rune ist Alias für int32)
    var unicodeChar rune = '🚀'
    fmt.Printf("Unicode-Zeichen: %c (Code: %d)\n", unicodeChar, unicodeChar)

    // Große Zahlen in wissenschaftlichen Berechnungen
    distances := []int32{384400, 149597870, 1367000000}
    bodies := []string{"Mond", "Sonne", "nächster Stern"}

    for i, distance := range distances {
        fmt.Printf("Entfernung zu %s: %d km\n", bodies[i], distance)
    }
}
Output
Stadtbevölkerung: 1500000
Kontostand: -25000
int32 range: -2147483648 bis 2147483647
Unicode-Zeichen: 🚀 (Code: 128640)
Entfernung zu Mond: 384400 km
Entfernung zu Sonne: 149597870 km
Entfernung zu nächster Stern: 1367000000 km

int64 - 64-Bit Signed Integer

Der int64 Typ bietet den größten Wertebereich für signed Integer. -9.223.372.036.854.775.808 bis 9.223.372.036.854.775.807. Dieser Typ ist ideal für sehr große Zahlen, Zeitstempel oder finanzielle Berechnungen mit hoher Präzision.

Auch hier ein kleines Beispiel.

Go Beispiel
package main

import (
    "fmt"
    "math"
    "time"
)

func main() {
    var worldPopulation int64 = 8000000000
    var nanoseconds int64 = time.Now().UnixNano()

    fmt.Printf("Weltbevölkerung: %d\n", worldPopulation)
    fmt.Printf("Aktuelle Zeit in ns: %d\n", nanoseconds)
    fmt.Printf("int64 range: %d bis %d\n", math.MinInt64, math.MaxInt64)

    // Finanzberechnungen in Cents
    prices := []int64{199, 2999, 50000}
    items := []string{"Kaffee", "Laptop", "Auto-Anzahlung"}

    for i, price := range prices {
        euros := float64(price) / 100
        fmt.Printf("%s: %.2f EUR (%d Cents)\n", items[i], euros, price)
    }
}
Output
Kaffee: 1.99 EUR (199 Cents)
Laptop: 29.99 EUR (2999 Cents)
Auto-Anzahlung: 500.00 EUR (50000 Cents)

Unsigned Integer-Typen

Unsigned Integer-Typen können nur positive Werte (einschließlich Null) speichern, haben aber dadurch doppelt so großen positiven Wertebereich wie ihre signed Gegenstücke. Sie sind ideal für Zähler, Indizes, Größenangaben oder andere Werte, die definitionsgemäß nicht negativ sein können.

uint8 - 8-Bit Unsigned Integer

Der uint8 Typ (auch als byte bekannt) kann Werte von 0 bis 255 speichern. Dieser Typ wird sehr häufig für die Darstellung von Bytes, Farb-RGB-Werten oder anderen 8-Bit-Daten verwendet.

Go Beispiel - uint8
package main

import (
    "fmt"
)

func main() {
    var age uint8 = 25
    var redValue uint8 = 255

    fmt.Printf("Alter: %d Jahre\n", age)
    fmt.Printf("Rot-Wert: %d\n", redValue)

    type RGB struct {
        Red uint8
        Green uint8
        Blue uint8
    }

    colors := []RGB{
        {255, 0, 0},
        {0, 255, 0},
        {0, 0, 255},
        {255, 255, 0},
        {128, 128, 128},
    }

    colorNames := []string{
        "Rot",
        "Grün",
        "Blau",
        "Gelb",
        "Grau",
    }

    for i, color := range colors {
        fmt.Printf("%s: RGB(%d, %d, %d)\n", colorNames[i], color.Red, color.Green, color.Blue)
    }
}
Output
Alter: 25 Jahre
Rot-Wert: 255
Rot: RGB(255, 0, 0)
Grün: RGB(0, 255, 0)
Blau: RGB(0, 0, 255)
Gelb: RGB(255, 255, 0)
Grau: RGB(128, 128, 128)

uint16 - 16-Bit Unsigned Integer

Der uint16 Typ speichert Werte von 0 bis 65.535 und wird oft für Port-Nummern, kleinere IDs oder Audio-Samples verwendet.

Go Beispiel - uint8
package main

import (
    "fmt"
)

func main() {
    var port uint16 = 8080
    var studentId uint16 = 12345

    fmt.Printf("Server-Port: %d\n", port)
    fmt.Printf("Studenten-ID: %d\n", studentId)

    // Netzwerk-Ports
    standardPorts := map[string]uint16{
        "HTTP": 80,
        "HTTPS": 443,
        "FTP": 21,
        "SSH": 22,
        "DNS": 53,
    }

    fmt.Println("Standard-Ports")
    for service, port := range standardPorts {
        fmt.Printf("\t%s: %d\n", service, port)
    }

    // Audio-Sample Werte (16-bit Audio)
    audioSamples := []uint16{0, 16384, 32768, 49152, 65535}
    fmt.Println("Audio-Samples (16-bit:)")
    for i, sample := range audioSamples {
        percentage := float64(sample) / 65535 * 100
        fmt.Printf("\tSample %d: %d (%.1f%%)\n", i, sample, percentage)
    }
}
Output
Server-Port: 8080
Studenten-ID: 12345
Standard-Ports
    HTTP: 80
    HTTPS: 443
    FTP: 21
    SSH: 22
    DNS: 53
Audio-Samples (16-bit:)
    Sample 0: 0 (0.0%)
    Sample 1: 16384 (25.0%)
    Sample 2: 32768 (50.0%)
    Sample 3: 49152 (75.0%)
    Sample 4: 65535 (100.0%)

uint32 - 32-Bit Unsigned Integer

Der uint32 Typ kann Werte von 0 bis 4.294.967.295 speichern und wird häufig für IP-Adressen, große IDs oder Zeitstempel verwendet.

Go Beispiel - uint32
package main

import (
    "fmt"
    "net"
    "time"
)

func main() {
    var timestamp uint32 = uint32(time.Now().Unix())
    var userId uint32 = 1000000

    fmt.Printf("Unix-Timestamp: %d\n", timestamp)
    fmt.Printf("Benutzer-ID: %d\n", userId)

    // IP-Adresse als uint32 (IPv4)
    ip := net.ParseIP("192.168.1.1").To4()
    if ip != nil {
        ipAsUint32 := uint32(ip[0])<<24 + uint32(ip[1])<<16 + uint32(ip[2])<<8 + uint32(ip[3])
        fmt.Printf("IP %s als uint32: %d\n", ip, ipAsUint32)

        // Zurück zur IP
        a := byte(ipAsUint32 >> 24)
        b := byte(ipAsUint32 >> 16)
        c := byte(ipAsUint32 >> 8)
        d := byte(ipAsUint32)

        fmt.Printf("uint32 %d als IP: %d.%d.%d.%d\n", ipAsUint32, a, b, c, d)
    }
}
Output
Unix-Timestamp: 1758555404
Benutzer-ID: 1000000
IP 192.168.1.1 als uint32: 3232235777
uint32 3232235777 als IP: 192.168.1.1

uint64 - 64-Bit Unsigned Integer

Der uint64 Typ bietet den größten Wertebereich: 0 bis 18.446.744.073.709.551.615. Er wird für sehr große Zähler, Dateigrößen oder präzise Zeitberechnungen verwendet.

Go Beispiel - uint32
package main

import (
    "fmt"
    "math"
    "time"
)

func main() {
    var fileSize uint64 = 5368709120 // 5 GB
    var microTimestamp uint64 = uint64(time.Now().UnixMicro())

    fmt.Printf("Dateigröße: %d Bytes\n", fileSize)
    fmt.Printf("Mikrosekunden-Timestamp: %d\n", microTimestamp)

    fmt.Printf("uint64 Maximum: %d\n", uint64(math.MaxUint64))

    // Dateigrößen in verschiedenen Einheiten
    fileSizes := []uint64{
        1024,           // 1 KB
        1048576,        // 1 MB
        1073741824,     // 1 GB
        1099511627776,  // 1 TB
    }

    units := []string{"KB", "MB", "GB", "TB"}

    fmt.Println("Dateigrößen")
    for i, size := range fileSizes {
        fmt.Printf("\t1 %s = %d Bytes\n", units[i], size)
    }
}
Output
Dateigröße: 5368709120 Bytes
Mikrosekunden-Timestamp: 1758556086872419
uint64 Maximum: 18446744073709551615
Dateigrößen
    1 KB = 1024 Bytes
    1 MB = 1048576 Bytes
    1 GB = 1073741824 Bytes
    1 TB = 1099511627776 Bytes

Plattformspezifische Typen

Go bietet plattformspezifische Integer-Typen, deren Größe von der Zielarchitektur abhängt. Diese Typen passen sich automatisch an die optimale Wortbreite der jeweiligen Plattform an.

int und uint - Plattformabhängige Integer

Die Typen int und uint haben eine plattformabhängige Größe: 32 Bit auf 32-Bit-Systemen und 64 Bit auf 64-Bit-Systemen. Diese Typen sind die Standardwahl für die meisten Integer-Operationen, da sie optimal zur Architektur des Zielsystems passen.

Go Beispiel
package main

import (
    "fmt"
    "math"
    "runtime"
    "unsafe"
)

func main() {
    var standardInt int = 42
    var standardUint uint = 42

    // Größe der plattformabhängigen Typen ermitteln
    intSize := unsafe.Sizeof(standardInt) * 8
    uintSize := unsafe.Sizeof(standardUint) * 8

    fmt.Printf("Aktuelle Plattform: %s/%s\n", runtime.GOOS, runtime.GOARCH)
    fmt.Printf("int Größe: %d Bit\n", intSize)
    fmt.Printf("uint Größe: %d Bit\n", uintSize)

    // Maximum ausgeben
    fmt.Printf("Maximaler int-Wert: %d\n", int(math.MaxInt))
    fmt.Printf("Maximaler uint-Wert: %d\n", uint(math.MaxUint))
}
Output
Aktuelle Plattform: darwin/arm64
int Größe: 64 Bit
uint Größe: 64 Bit
Maximaler int-Wert: 9223372036854775807
Maximaler uint-Wert: 18446744073709551615

uintptr - Pointer-Arithmetik

Der uintptr Typ ist groß genug, um jeden Pointer-Wert zu speichern. Er wird hauptsächlich für Pointer-Arithmetik und die Interaktion mit C-Code verwendet.

Go Beispiel - uintptr
package main

import (
    "fmt"
    "unsafe"
)

func main() {
    var x int = 42
    ptr := &x

    // Pointer zu uintptr konvertieren
    addr := uintptr(unsafe.Pointer(ptr))

    fmt.Printf("Variable x: %d\n", x)
    fmt.Printf("Adresse von x: %p\n", ptr)
    fmt.Printf("Adresse als uintptr: %d (0x%x)\n", addr, addr)

    // uintptr Größe
    fmt.Printf("uintptr Größe: %d Bit\n", unsafe.Sizeof(addr)*8)

}
Output
Variable x: 42
Adresse von x: 0x1400000e0c8
Adresse als uintptr: 1374389592264 (0x1400000e0c8)
uintptr Größe: 64 Bit

Häufige Stolperfallen

Im Umgang mit Integer-Typen gibt es einige typische Fehlerquellen, die selbst erfahrene Entwickler immer wieder treffen. Wer diese Fallstricke kennt, schreibt robusteren und portierbaren Code.

  • int ist plattformabhängig: int ist nicht zwingend 64 Bit. Auf 32-Bit-Architekturen ist int 32 Bit breit. Wer einen garantierten Wertebereich benötigt (etwa für Serialisierung, Protokolle oder Dateiformate), sollte explizit int32 oder int64 verwenden.
  • Overflow ist still und wickelt sich um: Go löst bei einem arithmetischen Overflow keine Panic aus. Stattdessen erfolgt ein Wrap-Around. Ein int8 mit Wert 127, dem 1 addiert wird, ergibt -128. Solche Fehler bleiben oft unbemerkt und sollten durch Bereichsprüfungen oder größere Typen vermieden werden.
  • Integer-Division verwirft den Rest: 5 / 2 ergibt in Go 2, nicht 2.5. Es gibt keine automatische Promotion zu float64. Wer ein Gleitkommaergebnis möchte, muss mindestens einen Operanden vorher konvertieren, etwa float64(5) / 2.
  • string(num) liefert einen Codepoint, keine Ziffern: string(65) ergibt "A", nicht "65". Für die Umwandlung einer Zahl in ihre Zifferndarstellung verwendet man strconv.Itoa oder strconv.FormatInt. Details dazu finden sich auch im String-Artikel.
  • Signed und unsigned mischen sich nicht implizit: int und uint sind verschiedene Typen. Auch eine Zuweisung von int32 an int erfordert eine explizite Konvertierung wie int(value). Go ist hier bewusst streng, um subtile Vorzeichenfehler zu vermeiden.
  • Konvertierung kann Werte abschneiden: int32(largeInt64) schneidet höhere Bits einfach ab, ohne Warnung. Vor einer schmaleren Konvertierung sollte gegen math.MaxInt32 und math.MinInt32 geprüft werden.
  • Untyped vs. typed Constants: Das Literal 123 ist eine untyped Konstante mit beliebiger Präzision und passt sich dem Kontext an. Sobald aber int(123) verwendet wird, ist die Konstante getypt und die flexible Konvertierbarkeit entfällt. Untyped Constants ermöglichen Ausdrücke wie var f float64 = 123, ohne explizite Konvertierung.

Weiterführende Ressourcen

Externe Quellen

/ Weiter

Zurück zu Datentypen

Zur Übersicht