Concatenamento dei metodi
Fa parte della sezione Programmazione orientata agli oggetti del percorso GO di Coddy. Lezione 81 di 107.
Concatenazione dei metodi è una tecnica in cui i metodi restituiscono il ricevente, consentendo di collegare più chiamate di metodo in un'unica istruzione. Hai già visto questo nel pattern Builder, ma è un concetto a sé stante, utile in molti contesti.
La chiave è restituire un puntatore alla struct da ciascun metodo:
type Query struct {
table string
columns []string
where string
limit int
}
func (q *Query) Select(cols ...string) *Query {
q.columns = cols
return q
}
func (q *Query) From(table string) *Query {
q.table = table
return q
}
func (q *Query) Where(condition string) *Query {
q.where = condition
return q
}
func (q *Query) Limit(n int) *Query {
q.limit = n
return q
}Ora puoi concatenare queste chiamate in modo fluido:
query := &Query{}
query.Select("name", "email").From("users").Where("active = true").Limit(10)Questo si legge quasi come linguaggio naturale rispetto a istruzioni separate. Il concatenamento dei metodi funziona meglio quando le operazioni configurano o modificano un oggetto senza dover restituire altri valori. È comunemente usato nei generatori di query, nelle API di configurazione e nelle librerie di asserzioni per i test.
Ricorda che ogni metodo deve usare un receiver puntatore e restituire *StructType affinché la catena funzioni correttamente.
Sfida
FacileCostruiamo un builder fluente di elementi HTML che usa il concatenamento dei metodi per creare tag HTML con attributi e contenuto! Questa è un’applicazione pratica del concatenamento dei metodi: creerai un’API che, durante la creazione di elementi HTML, si legge quasi come un linguaggio naturale.
Organizzerai il codice in due file:
element.go: definisci il builder degli elementi HTML con metodi concatenabili.Crea una struct
Elementche memorizza il nome del tag, una mappa di attributi (da stringa a stringa) e il contenuto interno. Crea questi metodi concatenabili, ciascuno dei quali restituisce*Element:NewElement(tag string)- costruttore che crea un nuovo Element con il nome di tag specificato e una mappa degli attributi inizializzata (vuota)Attr(key, value string)- aggiunge un attributo all’elementoID(id string)- metodo pratico che imposta l’attributo "id"Class(class string)- metodo pratico che imposta l’attributo "class"Content(text string)- imposta il contenuto interno dell’elemento
Aggiungi un metodo
Render()che restituisce la stringa HTML. Gli attributi devono apparire in ordine alfabetico in base alla chiave. Il formato è:<tag attr1="value1" attr2="value2">content</tag>Se non ci sono attributi, restituisci semplicemente
<tag>content</tag>. Se non c’è contenuto, restituisci<tag attr="value"></tag>.main.go: crea elementi HTML usando il concatenamento dei metodi.Leggi il nome del tag, poi leggi il numero di operazioni da eseguire. Ogni operazione è una delle seguenti:
idseguito dal valore dell’IDclassseguito dal valore della classeattrseguito dal nome e dal valore dell’attributo (due righe)contentseguito dal testo del contenuto
Concatena tutte le operazioni in modo fluido, quindi stampa l’HTML renderizzato.
Verranno forniti i seguenti input:
- Riga 1: nome del tag
- Riga 2: numero di operazioni
- Righe successive: tipo di operazione e valore/i
Ad esempio, dato:
div
3
id
container
class
main-content
content
Hello WorldL’output dovrebbe essere:
<div class="main-content" id="container">Hello World</div>E dato:
a
3
attr
href
https://example.com
attr
target
_blank
content
Click hereL’output dovrebbe essere:
<a href="https://example.com" target="_blank">Click here</a>E dato:
input
2
attr
type
text
attr
placeholder
Enter nameL’output dovrebbe essere:
<input placeholder="Enter name" type="text"></input>E dato:
p
1
content
Simple paragraphL’output dovrebbe essere:
<p>Simple paragraph</p>Nota come il concatenamento dei metodi ti permette di creare gli elementi passo dopo passo in modo leggibile. Ogni metodo modifica l’elemento e lo restituisce, consentendo di concatenare direttamente la chiamata al metodo successivo.
Provalo tu
package main
import (
"bufio"
"fmt"
"os"
"strconv"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// Leggi il nome del tag
scanner.Scan()
tagName := scanner.Text()
// Leggi il numero di operazioni
scanner.Scan()
numOps, _ := strconv.Atoi(scanner.Text())
// Crea l'elemento
element := NewElement(tagName)
// Elabora ogni operazione
for i := 0; i < numOps; i++ {
scanner.Scan()
operation := scanner.Text()
// TODO: In base al tipo di operazione, concatena il metodo appropriato
// Le operazioni possono essere: "id", "class", "attr" o "content"
// - Per "id": leggi la riga successiva come valore ID
// - Per "class": leggi la riga successiva come valore della classe
// - Per "attr": leggi le DUE righe successive (nome dell'attributo, poi valore)
// - Per "content": leggi la riga successiva come testo del contenuto
// Usa la concatenazione dei metodi per costruire l'elemento in modo fluido
_ = operation // Rimuovi questa riga durante l'implementazione
}
// Stampa l'HTML generato
fmt.Println(element.Render())
}
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 pool12Concetti avanzati di OOP
Pattern delle opzioni funzionaliPattern Builder in GoConcatenamento dei metodiAlias di tipo e definizioni a confrontoNozioni di base sulla reflectionPanoramica sulla generazione del codiceEsercitati da solo: Compilatore Go online