sort.Interface
Fa parte della sezione Programmazione orientata agli oggetti del percorso GO di Coddy. Lezione 74 di 107.
Il pacchetto sort offre un altro ottimo esempio di progettazione basata sulle interfacce. Per ordinare una raccolta personalizzata, il tuo tipo deve implementare sort.Interface:
type Interface interface {
Len() int
Less(i, j int) bool
Swap(i, j int)
}Questi tre metodi forniscono all’algoritmo di ordinamento tutto ciò di cui ha bisogno: la lunghezza della collezione, un modo per confrontare gli elementi e un modo per scambiarli. Ecco come rendere ordinabile una slice di struct personalizzate:
type Person struct {
Name string
Age int
}
type ByAge []Person
func (a ByAge) Len() int { return len(a) }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
func (a ByAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func main() {
people := []Person{
{"Alice", 30},
{"Bob", 25},
{"Carol", 35},
}
sort.Sort(ByAge(people))
fmt.Println(people)
// [{Bob 25} {Alice 30} {Carol 35}]
}L'intuizione chiave consiste nel creare un tipo denominato (ByAge) basato sulla tua slice. Questo ti permette di definire comportamenti di ordinamento diversi per gli stessi dati. Potresti creare ByName con un'implementazione diversa di Less per ordinare alfabeticamente.
Una volta che il tuo tipo soddisfa sort.Interface, funziona automaticamente con sort.Sort(), sort.Reverse() e sort.IsSorted().
Sfida
FacileCostruiamo un sistema di inventario dei prodotti ordinabile che dimostri la potenza di sort.Interface di Go! Creerai un tipo Product e implementerai diverse strategie di ordinamento, così da poter ordinare la stessa raccolta in modi diversi.
Organizzerai il codice in due file:
product.go: definisci il tipo di prodotto e le implementazioni dell'ordinamento.Crea una struct
Productcon tre campi:Name(string),Price(float64) eQuantity(int).Crea due tipi con nome basati su
[]Product:ByPrice- per ordinare i prodotti per prezzo in ordine crescenteByQuantity- per ordinare i prodotti per quantità in ordine decrescente (prima la quantità maggiore)
Ogni tipo deve implementare i tre metodi richiesti da
sort.Interface:Len(),Less(i, j int)eSwap(i, j int). Il metodoLessdetermina l'ordine di ordinamento per ciascun tipo.main.go: crea e ordina l'inventario dei prodotti.Leggi una modalità di ordinamento (
priceoquantity), poi leggi un numero seguito dai dettagli dei prodotti. Ogni prodotto è fornito su tre righe: nome, prezzo e quantità.Crea una slice di prodotti, ordinali usando il tipo di ordinamento appropriato in base alla modalità, quindi stampa ogni prodotto in questo formato:
[Name]: $[Price] (x[Quantity])Visualizza i prezzi con due cifre decimali.
Verranno forniti i seguenti input:
- Riga 1: modalità di ordinamento (
priceoquantity) - Riga 2: numero di prodotti
- Righe successive: dettagli dei prodotti (nome, prezzo, quantità - tre righe per prodotto)
Ad esempio, dato:
price
3
Laptop
999.99
5
Mouse
29.99
50
Keyboard
79.99
25L'output dovrebbe essere:
Mouse: $29.99 (x50)
Keyboard: $79.99 (x25)
Laptop: $999.99 (x5)E dato:
quantity
3
Laptop
999.99
5
Mouse
29.99
50
Keyboard
79.99
25L'output dovrebbe essere:
Mouse: $29.99 (x50)
Keyboard: $79.99 (x25)
Laptop: $999.99 (x5)Nota come gli stessi dati dei prodotti possano essere ordinati in modo diverso semplicemente usando un diverso tipo con nome. Una volta che i tuoi tipi soddisfano sort.Interface, funzionano senza problemi con sort.Sort() della libreria standard.
Provalo tu
package main
import (
"bufio"
"fmt"
"os"
"sort"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Leggi la modalità di ordinamento
var mode string
fmt.Fscanln(reader, &mode)
// Leggi il numero di prodotti
var count int
fmt.Fscanln(reader, &count)
// Leggi i prodotti
products := make([]Product, count)
for i := 0; i < count; i++ {
name, _ := reader.ReadString('\n')
name = strings.TrimSpace(name)
priceStr, _ := reader.ReadString('\n')
priceStr = strings.TrimSpace(priceStr)
price, _ := strconv.ParseFloat(priceStr, 64)
qtyStr, _ := reader.ReadString('\n')
qtyStr = strings.TrimSpace(qtyStr)
quantity, _ := strconv.Atoi(qtyStr)
products[i] = Product{Name: name, Price: price, Quantity: quantity}
}
// TODO: Ordina i prodotti in base a mode
// Se mode è "price", usa il tipo ByPrice
// Se mode è "quantity", usa il tipo ByQuantity
// Usa sort.Sort() con il tipo appropriato
// TODO: Stampa ogni prodotto nel formato:
// [Name]: $[Price] (x[Quantity])
// Usa fmt.Printf con %.2f per formattare il prezzo
}
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