Concetti base dei puntatori in Go
Fa parte della sezione Programmazione orientata agli oggetti del percorso GO di Coddy. Lezione 19 di 107.
Un puntatore è una variabile che memorizza l’indirizzo di memoria di un’altra variabile. Invece di contenere direttamente un valore, contiene la posizione in cui quel valore si trova in memoria. I puntatori sono fondamentali in Go ed essenziali per manipolare i dati in modo efficiente.
Per creare un puntatore, usa l'operatore & per ottenere l'indirizzo di una variabile e l'operatore * per dichiarare un tipo puntatore o accedere al valore a quell'indirizzo.
x := 42
p := &x // p contiene l'indirizzo di memoria di x
fmt.Println(p) // 0xc000018030 (indirizzo di memoria)
fmt.Println(*p) // 42 (valore a quell'indirizzo)L'operatore & significa «indirizzo di» e restituisce un puntatore. L'operatore *, quando viene usato su un puntatore, significa «valore in» ed è chiamato dereferenziazione. Puoi anche modificare il valore originale tramite il puntatore.
x := 10
p := &x
*p = 25 // cambia el valor mediante el puntero
fmt.Println(x) // 25 (la variable original cambió)Il tipo puntatore si scrive come *T, dove T è il tipo a cui punta. Un puntatore a un int ha tipo *int.
var p *int // dichiara un puntatore a int
x := 100
p = &x // p ora punta a xIl valore zero di un puntatore è nil, ovvero non punta a nulla. Il tentativo di dereferenziare un puntatore nil causa un panic in fase di esecuzione, quindi assicurati sempre che i puntatori siano inizializzati prima di usarli.
Sfida
FacileCostruiamo una semplice funzione per scambiare valori, che dimostra la potenza dei puntatori nel modificare le variabili tramite i loro indirizzi di memoria.
Organizzerai il codice in due file:
swap.go: Crea una funzione chiamataSwapValuesche accetta due puntatori*intcome parametri. Questa funzione deve scambiare i valori a cui puntano questi puntatori; dopo averla chiamata, ciascuna variabile deve contenere il valore originale dell'altra. La funzione non restituisce nulla; modifica direttamente i valori tramite i puntatori.main.go: Leggi due numeri interi dall'input, memorizzali in variabili, quindi usa la tua funzioneSwapValuesper scambiarne i valori. Stampa entrambi i valori prima e dopo lo scambio per mostrare il cambiamento.
Verranno forniti i seguenti input:
- Riga 1: Primo numero intero
- Riga 2: Secondo numero intero
Formato dell'output:
Before: a=[first] b=[second]
After: a=[first] b=[second]Ad esempio, dati 10 e 25, il tuo output dovrebbe essere:
Before: a=10 b=25
After: a=25 b=10Ricorda di usare l'operatore & quando passi le variabili alla funzione e l'operatore * all'interno della funzione per accedere ai valori effettivi e modificarli.
Provalo tu
package main
import "fmt"
func main() {
// Leggi due numeri interi dall'input
var a, b int
fmt.Scanln(&a)
fmt.Scanln(&b)
// Stampa i valori prima dello scambio
fmt.Printf("Before: a=%d b=%d\n", a, b)
// TODO: Chiama la funzione SwapValues con puntatori a a e b
// Ricorda di usare l'operatore & per passare gli indirizzi
// Stampa i valori dopo lo scambio
fmt.Printf("After: a=%d b=%d\n", a, b)
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Fondamenti di OOP in Go
File esterniWorkspace e moduli GoPacchetti e importazioniNomi esportati e non esportatiIntroduzione all’OOP in GoGli struct come classiDefinire metodi sugli structReceiver con puntatore vs receiver con valoreInizializzazione degli structFunzioni costruttriciRiepilogo - Calcolatrice semplice4Interfacce
Introduzione alle interfacceImplementazione implicitaL’interfaccia come contrattoInterfaccia vuota (any)Asserzione di tipoSwitch sul tipoComposizione di interfacceInterfacce Stringer ed ErrorRipasso - Calcolatore di forme7Incapsulamento
Campi esportati e non esportatiIncapsulamento a livello di packageMetodi Getter e SetterNascondimento delle informazioni in GoRiepilogo - Registri degli studenti10Tipi generici (Go 1.18+)
Introduzione ai tipi genericiParametri di tipoVincoli di tipoStruct genericheSoluzione alternativa per i metodi genericiRiepilogo - Collezione generica13Modelli di progettazione Parte 1
Introduzione ai modelli di progettazioneModello SingletonModello FactoryModello Abstract FactoryModello ObserverModello Strategy2Approfondimento su tipi e struct
Tipi di base e compostiDefinizioni di tipi personalizzatiTag delle structStruct anonimeStruct annidateValori zero e predefinitiRipasso - Rubrica5Composizione invece dell'ereditarietà
Perché Go non ha l'ereditarietàFondamenti dell'embedding delle structPromozione dei metodiEmbedding di più structEmbedding e aggregazione a confrontoMascheramento dei metodi embeddedRiepilogo: gerarchia dei dipendenti8Gestione degli errori e OOP
L'interfaccia errorTipi di errore personalizzatiWrapping degli errori (fmt.Errorf)Errori sentinellaerrors.Is() ed errors.As()Panic, Defer e RecoverRiepilogo - Parser di file11Libreria standard e OOP
io.Reader e io.Writersort.InterfaceInterfaccia fmt.Stringerencoding/json con le structInterfaccia http.HandlerRipasso - modelli REST API14Modelli di progettazione – Parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern CompositeMiddleware come Decorator3Puntatori e memoria
Concetti base dei puntatori in GoPuntatori a structPassaggio per valore vs per riferimentoLa funzione new()Garbage collection in GoRiepilogo - Costruttore di liste concatenate6Polimorfismo in Go
Polimorfismo tramite interfacceDuck typing in GoRegole di soddisfacimento delle interfacceCollezioni polimorficheIniezione delle dipendenzeRiepilogo - Elaboratore di pagamenti9Concorrenza e OOP
Basi delle goroutineCanali e comunicazioneCanali bufferizzati vs non bufferizzatiIstruzione selectsync.Mutex e sync.RWMutexsync.WaitGroupProgettazione di struct thread-safeRiepilogo: worker poolEsercitati da solo: Compilatore Go online