00
:
00
:
00
:
00
Corso SEO AI - Usa SEOEMAIL al checkout per il 30% di sconto

Stringhe

Le stringhe in Go

In Go, una stringa e una sequenza immutabile di byte. Le stringhe sono uno dei tipi piu utilizzati e Go offre strumenti potenti per la loro manipolazione attraverso la libreria standard.

Letterali stringa

Go supporta due tipi di letterali stringa:

Stringhe interpretate (double quotes)

Le stringhe tra virgolette doppie supportano le sequenze di escape:

package main

import "fmt"

func main() {
    saluto := "Ciao, mondo!"
    riga := "Prima riga\nSeconda riga"
    tab := "Colonna1\tColonna2"
    percorso := "C:\\Utenti\\Mario"
    citazione := "Ha detto: \"ciao\""

    fmt.Println(saluto)
    fmt.Println(riga)
    fmt.Println(tab)
    fmt.Println(percorso)
    fmt.Println(citazione)
}

Stringhe raw (backtick)

Le stringhe tra backtick (accento grave) non interpretano le sequenze di escape e possono estendersi su piu righe:

package main

import "fmt"

func main() {
    // Ideale per espressioni regolari
    regex := `\d{3}-\d{4}`

    // Ideale per testo multilinea
    html := `
    <html>
        <body>
            <h1>Ciao</h1>
        </body>
    </html>`

    // I backslash non vengono interpretati
    percorso := `C:\Utenti\Mario\Documenti`

    fmt.Println(regex)
    fmt.Println(html)
    fmt.Println(percorso)
}

Immutabilita delle stringhe

Le stringhe in Go sono immutabili: non puoi modificare un singolo carattere direttamente. Per modificare una stringa, devi crearne una nuova:

package main

import "fmt"

func main() {
    testo := "ciao"
    // testo[0] = 'C' // ERRORE: cannot assign to testo[0]

    // Per modificare, converti in slice di byte o rune
    rune := []rune(testo)
    rune[0] = 'C'
    nuovoTesto := string(rune)

    fmt.Println(nuovoTesto) // Ciao
}

Concatenazione di stringhe

Ci sono diversi modi per concatenare stringhe in Go:

package main

import (
    "fmt"
    "strings"
)

func main() {
    // Operatore +
    nome := "Mario" + " " + "Rossi"
    fmt.Println(nome)

    // fmt.Sprintf per formattazione
    saluto := fmt.Sprintf("Ciao, %s!", nome)
    fmt.Println(saluto)

    // strings.Join per slice di stringhe
    parole := []string{"Go", "e", "fantastico"}
    frase := strings.Join(parole, " ")
    fmt.Println(frase) // Go e fantastico

    // strings.Builder per concatenazioni multiple (efficiente)
    var builder strings.Builder
    for i := 0; i < 5; i++ {
        builder.WriteString(fmt.Sprintf("Riga %d\n", i))
    }
    fmt.Println(builder.String())
}

Per concatenazioni ripetute in un ciclo, strings.Builder e molto piu efficiente dell’operatore + perche evita di creare stringhe intermedie.

Lunghezza delle stringhe

La funzione len() restituisce il numero di byte nella stringa, non il numero di caratteri:

package main

import (
    "fmt"
    "unicode/utf8"
)

func main() {
    testo := "Ciao"
    emoji := "Ciao!"

    // len() conta i byte
    fmt.Println(len(testo)) // 4
    fmt.Println(len(emoji)) // potrebbe essere > 5 per emoji multi-byte

    // Per contare i caratteri Unicode, usa utf8.RuneCountInString
    fmt.Println(utf8.RuneCountInString(testo)) // 4

    // Oppure converti in []rune
    caratteri := []rune(testo)
    fmt.Println(len(caratteri)) // 4
}

Accesso ai caratteri

Puoi accedere ai singoli byte con l’indicizzazione, o iterare sui caratteri Unicode con range:

package main

import "fmt"

func main() {
    testo := "Ciao"

    // Accesso per byte (indice)
    fmt.Printf("Primo byte: %c\n", testo[0]) // C

    // Iterazione per byte
    for i := 0; i < len(testo); i++ {
        fmt.Printf("Byte %d: %c\n", i, testo[i])
    }

    fmt.Println("---")

    // Iterazione per rune (caratteri Unicode) con range
    for indice, carattere := range testo {
        fmt.Printf("Indice %d: %c\n", indice, carattere)
    }

    // Slicing (estrae una sottostringa)
    sotto := testo[0:4]
    fmt.Println(sotto) // Ciao
}

Il pacchetto strings

Il pacchetto strings offre numerose funzioni per manipolare le stringhe:

Contains e ContainsAny

package main

import (
    "fmt"
    "strings"
)

func main() {
    testo := "Go e un linguaggio fantastico"

    fmt.Println(strings.Contains(testo, "linguaggio")) // true
    fmt.Println(strings.Contains(testo, "Python"))     // false
    fmt.Println(strings.ContainsAny(testo, "aeiou"))   // true
}

Replace e ReplaceAll

package main

import (
    "fmt"
    "strings"
)

func main() {
    testo := "ciao mondo ciao tutti"

    // Sostituisci la prima occorrenza
    fmt.Println(strings.Replace(testo, "ciao", "salve", 1))
    // salve mondo ciao tutti

    // Sostituisci tutte le occorrenze
    fmt.Println(strings.ReplaceAll(testo, "ciao", "salve"))
    // salve mondo salve tutti
}

Split e Join

package main

import (
    "fmt"
    "strings"
)

func main() {
    // Split: divide una stringa in uno slice
    csv := "Mario,Luigi,Peach,Toad"
    nomi := strings.Split(csv, ",")
    fmt.Println(nomi) // [Mario Luigi Peach Toad]

    // Join: unisce uno slice in una stringa
    risultato := strings.Join(nomi, " - ")
    fmt.Println(risultato) // Mario - Luigi - Peach - Toad
}

ToUpper, ToLower, TrimSpace

package main

import (
    "fmt"
    "strings"
)

func main() {
    testo := "  Ciao Mondo  "

    fmt.Println(strings.ToUpper(testo))    // "  CIAO MONDO  "
    fmt.Println(strings.ToLower(testo))    // "  ciao mondo  "
    fmt.Println(strings.TrimSpace(testo))  // "Ciao Mondo"
    fmt.Println(strings.Trim(testo, " "))  // "Ciao Mondo"

    // HasPrefix e HasSuffix
    file := "documento.pdf"
    fmt.Println(strings.HasPrefix(file, "doc"))  // true
    fmt.Println(strings.HasSuffix(file, ".pdf")) // true

    // Count
    ripetuto := "banana"
    fmt.Println(strings.Count(ripetuto, "an")) // 2

    // Index
    fmt.Println(strings.Index(ripetuto, "nan")) // 2
}

Formattazione con fmt.Sprintf

fmt.Sprintf restituisce una stringa formattata senza stamparla:

package main

import "fmt"

func main() {
    nome := "Mario"
    eta := 30
    altezza := 1.75

    // Verbi di formattazione comuni
    s1 := fmt.Sprintf("Nome: %s", nome)       // stringa
    s2 := fmt.Sprintf("Eta: %d anni", eta)     // intero decimale
    s3 := fmt.Sprintf("Altezza: %.2f m", altezza) // float con 2 decimali
    s4 := fmt.Sprintf("Tipo: %T", nome)        // tipo della variabile
    s5 := fmt.Sprintf("Valore: %v", eta)       // valore generico
    s6 := fmt.Sprintf("Binario: %b", 42)       // rappresentazione binaria
    s7 := fmt.Sprintf("Esadecimale: %x", 255)  // rappresentazione esadecimale
    s8 := fmt.Sprintf("Carattere: %c", 65)     // carattere Unicode
    s9 := fmt.Sprintf("Stringa quoted: %q", nome) // stringa con virgolette

    fmt.Println(s1) // Nome: Mario
    fmt.Println(s2) // Eta: 30 anni
    fmt.Println(s3) // Altezza: 1.75 m
    fmt.Println(s4) // Tipo: string
    fmt.Println(s5) // Valore: 30
    fmt.Println(s6) // Binario: 101010
    fmt.Println(s7) // Esadecimale: ff
    fmt.Println(s8) // Carattere: A
    fmt.Println(s9) // Stringa quoted: "Mario"
}

Conclusione

Le stringhe in Go sono sequenze immutabili di byte con un supporto eccellente per Unicode. La distinzione tra stringhe interpretate e raw, il ricco pacchetto strings e le potenti funzionalita di formattazione di fmt.Sprintf rendono la manipolazione delle stringhe in Go semplice e intuitiva. Per operazioni intensive sulle stringhe, strings.Builder offre prestazioni ottimali evitando allocazioni di memoria superflue.