Qual è la differenza di funzioni e metodi in Go?

Sto cercando di iniziare con Go e la documentazione è molto buona. Quello che non ho trovato nella documentazione è la differenza tra funzioni e metodi.

Per quanto ne so al momento: le funzioni sono “globali”, il che significa che non devo importare un pacchetto per usare le funzioni, sono sempre lì. I metodi sono legati ai pacchetti. È corretto?

Per quanto ne so al momento: le funzioni sono “globali”, il che significa che non devo importare un pacchetto per usare le funzioni, sono sempre lì. I metodi sono legati ai pacchetti. È corretto?

No, non è corretto. Ci sono solo un paio di funzioni del pacchetto integrato che sono sempre disponibili. Tutto il resto deve essere importato.

Il termine “metodo” ha prodotto una programmazione orientata agli oggetti. In un linguaggio OOP (come C ++ per esempio) è ansible definire una “class” che incapsula dati e funzioni che appartengono insieme. Quelle funzioni all’interno di una class sono chiamate “metodi” e hai bisogno di un’istanza di quella class per chiamare tale metodo.

In Go, la terminologia è fondamentalmente la stessa, sebbene Go non sia un linguaggio OOP nel significato classico. In Go, una funzione che accetta un ricevitore viene solitamente chiamata metodo (probabilmente solo perché le persone sono ancora abituate alla terminologia di OOP).

Quindi, ad esempio:

func MyFunction(a, b int) int { return a + b } // Usage: // MyFunction(1, 2) 

ma

 type MyInteger int func (a MyInteger) MyMethod(b int) int { return a + b } // Usage: // var x MyInteger = 1 // x.MyMethod(2) 

La risposta di Tux è ottima, ma voglio aumentarla con l’uso dei metodi di Go con struct s (perché è qui che l’ho usato spesso). Quindi supponiamo che tu voglia build qualcosa per calcolare vari metodi sui triangoli. Si inizia con una struct :

 type Triangle struct { a, b, c float64 } 

e poi vorresti aggiungere alcune funzioni per calcolare il perimetro e il quadrato:

 func valid(t *Triangle) error { if ta + tb > tc && ta + tc > tb && tb + tc > ta { return nil } return errors.New("Triangle is not valid") } func perimeter(t *Triangle) (float64, error) { err := valid(t) if err != nil { return -1, err } return ta + tb + tc, nil } func square(t *Triangle) (float64, error) { p, err := perimeter(t) if err != nil { return -1, err } p /= 2 s := p * (p - ta) * (p - tb) * (p - tc) return math.Sqrt(s), nil } 

E ora hai il tuo programma di lavoro Go Playground . In questo caso la tua funzione accetta un parametro (puntatore a un triangolo) e fa qualcosa. Nella parola OOP le persone avrebbero potuto creare una class e poi aggiungere metodi. Possiamo vedere la nostra struttura come tipo di class con i campi e ora aggiungiamo metodi:

 func (t *Triangle) valid() error { if ta + tb > tc && ta + tc > tb && tb + tc > ta { return nil } return errors.New("Triangle is not valid") } func (t *Triangle) perimeter() (float64, error) { err := t.valid() if err != nil { return -1, err } return ta + tb + tc, nil } func (t *Triangle) square() (float64, error) { p, err := t.perimeter() if err != nil { return -1, err } p /= 2 s := p * (p - ta) * (p - tb) * (p - tc) return math.Sqrt(s), nil } 

e abbiamo un esempio pienamente funzionante .

Si noti che sembra davvero un metodo per gli oggetti.

Sono spiegati in dettaglio qui – https://anil.cloud/2017/01/26/golang-functions-methods-simplified/

Una funzione in Go segue la syntax:

 func FunctionName(Parameters...) ReturnTypes... 

Esempio:

 func add(x int, y int) int 

Eseguire:

  add(2,3) 

Un metodo è come una funzione, ma è collegato a un tipo (chiamato come ricevitore). La guida ufficiale afferma “Un metodo è una funzione con un argomento ricevitore speciale”. Il ricevitore appare tra la parola chiave func e il nome del metodo. La syntax di un metodo è:

 func (t ReceiverType) FunctionName(Parameters...) ReturnTypes... 

Esempio:

 func (t MyType) add(int x, int y) int 

Eseguire:

 type MyType string t1 := MyType("sample") t1.add(1,2) 

Ora lascia portare puntatori nel tavolo. Go lang è passato per valore, significa che nuove copie dei parametri vengono passate a ogni chiamata di funzione / metodo. Per passarli per riferimento puoi usare i puntatori.

Sintassi della funzione con il puntatore nell’elenco argomento / parametro.

 func FunctionName(*Pointers...,Parameters...) ReturnTypes... 

Esempio

 func add(t *MyType, x int, y int) int 

Eseguire:

 type MyType string t1 := MyType("sample") add(&t1,4,5) 

Allo stesso modo per i metodi, il tipo di ricevitore può essere un puntatore. Sintassi del metodo con il puntatore (come ricevitore)

 func (*Pointer) FunctionName(Parameters...) ReturnTypes... 

Esempio

 func (t *MyType) add(x int, y int) int 

Eseguire:

 type MyType string t1 := MyType("sample") t1.add(2,3) 

Si noti che possiamo ancora scrivere t1.add () per eseguire il metodo con un ricevitore puntatore (anche se ‘t1’ non è un puntatore) e Go lo interpreterà come (& t1) .add (). Allo stesso modo un metodo con ricevitore di valore può essere chiamato usando il puntatore, Go interpreterà p.add () come (* p) .add () in quel caso (dove ‘p’ è un puntatore). Questo è applicabile solo per i metodi e non per le funzioni.

I metodi con il ricevitore pointer sono molto utili per ottenere un comportamento simile a “Java” in cui il metodo sta effettivamente modificando il valore a cui punta il ricevitore e non una sua copia.