¿Cuál es la diferencia de funciones y métodos en Go?

Estoy tratando de comenzar con Go y la documentación es muy buena. Lo que no encontré en la documentación es la diferencia entre funciones y métodos.

Por lo que entiendo en este momento: las funciones son “globales”, lo que significa que no tengo que importar un paquete para usar funciones, siempre están ahí. Los métodos están vinculados a paquetes. ¿Es esto correcto?

Por lo que entiendo en este momento: las funciones son “globales”, lo que significa que no tengo que importar un paquete para usar funciones, siempre están ahí. Los métodos están vinculados a paquetes. ¿Es esto correcto?

No, eso no es correcto. Solo hay un par de funciones del paquete integrado que están siempre disponibles. Todo lo demás necesita ser importado.

El término “método” surgió con progtwigción orientada a objetos. En un lenguaje OOP (como C ++ por ejemplo) puede definir una “clase” que encapsula datos y funciones que pertenecen juntas. Esas funciones dentro de una clase se llaman “métodos” y se necesita una instancia de esa clase para llamar a dicho método.

En Go, la terminología es básicamente la misma, aunque Go no es un lenguaje OOP en el significado clásico. En Go, una función que toma un receptor generalmente se llama método (probablemente solo porque las personas todavía están acostumbradas a la terminología de OOP).

Así por ejemplo:

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

pero

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

La respuesta de Tux es genial, pero quiero boostla con el uso de los métodos de Go con struct s (porque aquí es donde lo usé a menudo). Asummos que quieres construir algo para calcular varios métodos en triangularjs. Comienzas con una struct :

 type Triangle struct { a, b, c float64 } 

y luego le gustaría agregar algunas funciones para calcular el perímetro y el cuadrado:

 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 } 

Y ahora tienes tu progtwig de trabajo Go Playground . En este caso, su función toma un parámetro (puntero a un triángulo) y hace algo. En la palabra OOP las personas pueden haber creado una clase y luego agregar métodos. Podemos ver nuestra estructura como clase de clase con campos y ahora agregamos métodos:

 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 } 

y tenemos un ejemplo completamente funcional .

Tenga en cuenta que realmente se parece a un método para objetos.

Se explican en detalle aquí – https://anil.cloud/2017/01/26/golang-functions-methods-simplified/

Una función en Go sigue la syntax:

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

Ejemplo:

 func add(x int, y int) int 

Ejecutar:

  add(2,3) 

Un método es como una función, pero unido a un tipo (llamado como receptor). La guía oficial establece “Un método es una función con un argumento de receptor especial”. El receptor aparece entre la palabra clave func y el nombre del método. La syntax de un método es:

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

Ejemplo:

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

Ejecutar:

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

Ahora vamos a traer punteros a la mesa. Go lang es pasar por valor, significa que se pasan nuevas copias de los parámetros a cada llamada de función / método. Para pasarlos por referencia, puede usar punteros.

Sintaxis de la función con puntero en argumento / lista de parámetros.

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

Ejemplo

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

Ejecutar:

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

De forma similar para los métodos, el tipo de receptor puede ser un puntero. Sintaxis del método con puntero (como receptor)

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

Ejemplo

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

Ejecutar:

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

Tenga en cuenta que aún podemos escribir t1.add () para ejecutar el método con un receptor de puntero (incluso aunque ‘t1’ no sea un puntero) y Go lo interpretará como (& t1) .add (). De forma similar, un método con un receptor de valores también se puede llamar usando el puntero, Go interpretará p.add () como as (* p) .add () en ese caso (donde ‘p’ es un puntero). Esto es aplicable solo para métodos y no para funciones.

Los métodos con receptor de puntero son muy útiles para obtener un comportamiento similar al de “Java” en el que el método realmente está modificando el valor al que apunta el receptor y no en una copia del mismo.