go - template - Parámetros opcionales?
url django parameter (10)
El lenguaje Go no admite la sobrecarga de métodos, pero puede usar argumentos variables como parámetros opcionales, también puede usar la interfaz {} como parámetro, pero no es una buena opción.
¿Puede Go tener parámetros opcionales? ¿O simplemente puedo definir dos funciones con el mismo nombre y un número diferente de argumentos?
Go no tiene parámetros opcionales ni admite la sobrecarga de métodos :
El envío de métodos se simplifica si no es necesario realizar la coincidencia de tipos también. La experiencia con otros idiomas nos dijo que en ocasiones era útil tener una variedad de métodos con el mismo nombre pero diferentes firmas, pero que también podría ser confuso y frágil en la práctica. La coincidencia solo por nombre y la exigencia de coherencia en los tipos fue una importante decisión simplificadora en el sistema de tipos de Go.
Llego un poco tarde, pero si te gusta la interfaz fluida, puedes diseñar tus setters para llamadas en cadena como esta:
type myType struct {
s string
a, b int
}
func New(s string, err *error) *myType {
if s == "" {
*err = errors.New(
"Mandatory argument `s` must not be empty!")
}
return &myType{s: s}
}
func (this *myType) setA (a int, err *error) *myType {
if *err == nil {
if a == 42 {
*err = errors.New("42 is not the answer!")
} else {
this.a = a
}
}
return this
}
func (this *myType) setB (b int, _ *error) *myType {
this.b = b
return this
}
Y luego llámalo así:
func main() {
var err error = nil
instance :=
New("hello", &err).
setA(1, &err).
setB(2, &err)
if err != nil {
fmt.Println("Failed: ", err)
} else {
fmt.Println(instance)
}
}
Esto es similar al lenguaje de opciones funcionales presentado en @Ripounet answer y disfruta de los mismos beneficios pero tiene algunos inconvenientes:
- Si ocurre un error, no abortará de inmediato, por lo tanto, sería un poco menos eficiente si espera que su constructor informe los errores con frecuencia.
- Tendrás que gastar una línea declarando una variable de
err
y poniéndola a cero.
Sin embargo, existe una posible pequeña ventaja, este tipo de llamadas de función debería ser más fácil para el compilador en línea, pero realmente no soy un especialista.
No - tampoco. Por la documentación de Go for C ++ programs,
Go no admite la sobrecarga de funciones y no admite operadores definidos por el usuario.
No puedo encontrar una declaración igualmente clara de que los parámetros opcionales no son compatibles, pero tampoco son compatibles.
No se admiten parámetros opcionales ni sobrecarga de funciones en Go. Go admite un número variable de parámetros: Pasar argumentos a ... parámetros
Para un número arbitrario, potencialmente grande de parámetros opcionales, una buena expresión es usar las opciones funcionales .
Para su tipo Foobar
, primero escriba solo un constructor:
func NewFoobar(options ...func(*Foobar) error) (*Foobar, error){
fb := &Foobar{}
// ... (write initializations with default values)...
for _, op := range options{
err := op(fb)
if err != nil {
return nil, err
}
}
return fb, nil
}
donde cada opción es una función que muta el Foobar. Luego, proporcione formas convenientes para que su usuario use o cree opciones estándar, por ejemplo:
func OptionReadonlyFlag(fb *Foobar) error {
fb.mutable = false
return nil
}
func OptionTemperature(t Celsius) func(*Foobar) error {
return func(fb *Foobar) error {
fb.temperature = t
return nil
}
}
Para mayor precisión, puede asignar un nombre al tipo de opciones ( Playground ):
type OptionFoobar func(*Foobar) error
Si necesita parámetros obligatorios, agréguelos como primeros argumentos del constructor antes de las options
variadic.
Los principales beneficios del lenguaje de opciones funcionales son:
- su API puede crecer con el tiempo sin romper el código existente, porque la firma del conductor permanece igual cuando se necesitan nuevas opciones.
- permite que el caso de uso predeterminado sea el más simple: ¡sin argumentos en absoluto!
- proporciona un control fino sobre la inicialización de valores complejos.
Esta técnica fue acuñada por Rob Pike y también demostrada por Dave Cheney .
Puedes resumir esto bastante bien en una función similar a la que se muestra a continuación.
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
fmt.Println(prompt())
}
func prompt(params ...string) string {
prompt := ": "
if len(params) > 0 {
prompt = params[0]
}
reader := bufio.NewReader(os.Stdin)
fmt.Print(prompt)
text, _ := reader.ReadString(''/n'')
return text
}
En este ejemplo, la solicitud de forma predeterminada tiene dos puntos y un espacio delante. . .
:
. . . sin embargo, puede anularlo proporcionando un parámetro a la función de solicitud.
prompt("Input here -> ")
Esto dará lugar a un mensaje como el siguiente.
Input here ->
Puedes usar una estructura que incluye los parámetros:
type Params struct {
a, b, c int
}
func doIt(p Params) int {
return p.a + p.b + p.c
}
// you can call it without specifying all parameters
doIt(Params{a: 1, c: 9})
Terminé usando una combinación de una estructura de params y variadic args. De esta manera, no tuve que cambiar la interfaz existente que consumían varios servicios y mi servicio pudo pasar parámetros adicionales según fue necesario. Código de muestra en el área de juegos de Golang: https://play.golang.org/p/G668FA97Nu
Una buena manera de lograr algo como los parámetros opcionales es usar variadic args. La función realmente recibe una porción del tipo que especifique.
func foo(params ...int) {
fmt.Println(len(params))
}
func main() {
foo()
foo(1)
foo(1,2,3)
}