Valor predeterminado en el método de Go

99

¿Hay alguna forma de especificar el valor predeterminado en la función de Go? Estoy tratando de encontrar esto en la documentación, pero no puedo encontrar nada que especifique que esto es posible.

func SaySomething(i string = "Hello")(string){
...
}
Denniss
fuente

Respuestas:

117

NO, pero hay otras opciones para implementar el valor predeterminado. Hay algunas buenas publicaciones de blog sobre el tema, pero aquí hay algunos ejemplos específicos.


** Opción 1: ** La persona que llama elige usar valores predeterminados
// Both parameters are optional, use empty string for default value
func Concat1(a string, b int) string {
  if a == "" {
    a = "default-a"
  }
  if b == 0 {
    b = 5
  }

  return fmt.Sprintf("%s%d", a, b)
}

** Opción 2: ** Un solo parámetro opcional al final
// a is required, b is optional.
// Only the first value in b_optional will be used.
func Concat2(a string, b_optional ...int) string {
  b := 5
  if len(b_optional) > 0 {
    b = b_optional[0]
  }

  return fmt.Sprintf("%s%d", a, b)
}

** Opción 3: ** Una estructura de configuración
// A declarative default value syntax
// Empty values will be replaced with defaults
type Parameters struct {
  A string `default:"default-a"` // this only works with strings
  B string // default is 5
}

func Concat3(prm Parameters) string {
  typ := reflect.TypeOf(prm)

  if prm.A == "" {
    f, _ := typ.FieldByName("A")
    prm.A = f.Tag.Get("default")
  }

  if prm.B == 0 {
    prm.B = 5
  }

  return fmt.Sprintf("%s%d", prm.A, prm.B)
}

** Opción 4: ** Análisis completo de argumentos variadic (estilo javascript)
func Concat4(args ...interface{}) string {
  a := "default-a"
  b := 5

  for _, arg := range args {
    switch t := arg.(type) {
      case string:
        a = t
      case int:
        b = t
      default:
        panic("Unknown argument")
    }
  }

  return fmt.Sprintf("%s%d", a, b)
}
director de escuela
fuente
90
Que dolor. Ojalá lo fuera: func Concat1(a string = 'foo', b int = 10) string {como en la mayoría de los otros lenguajes modernos ... Reduciría cualquiera de los ejemplos dados prácticamente a una línea de código.
Rotareti
¿Tenemos la opción de escribir dos funciones diferentes y dejar que la persona que llama sea explícita sobre lo que espera?
ProgramCpp
@ProgramCpp no, golang no permite la sobrecarga de funciones ¿Tiene el lenguaje Go una sobrecarga de funciones / métodos?
Vusal
9

No, no hay forma de especificar valores predeterminados. Creo que esto se hace a propósito para mejorar la legibilidad, a costa de un poco más de tiempo (y, con suerte, de pensamiento) por parte del escritor.

Creo que el enfoque adecuado para tener un "predeterminado" es tener una nueva función que proporcione ese valor predeterminado a la función más genérica. Teniendo esto, su código se vuelve más claro en su intención. Por ejemplo:

func SaySomething(say string) {
    // All the complicated bits involved in saying something
}

func SayHello() {
    SaySomething("Hello")
}

Con muy poco esfuerzo, hice una función que hace algo común y reutilicé la función genérica. Puede ver esto en muchas bibliotecas, fmt.Printlnpor ejemplo, simplemente agrega una nueva línea a lo fmt.Printque de otro modo haría. Sin embargo, al leer el código de alguien, queda claro qué pretenden hacer con la función que llaman. Con los valores predeterminados, no sabré qué se supone que debe suceder sin ir también a la función para hacer referencia a cuál es realmente el valor predeterminado.

Dave
fuente
Me gusta y estoy de acuerdo con esta respuesta, pero maldita sea, todavía desearía que al menos tuvieran una forma obtusa pero idiomática de hacerlo.
Sam Gomena
12
El argumento "simplemente agregar otra función" puede resultar en una explosión de métodos requeridos para lidiar con múltiples permutaciones, requiere la carga de decidir sobre nombres significativos, detectables y recordables para esos métodos, y agrega carga para aprender los paquetes que usan más métodos vs. . Menos. #jmtcw
MikeSchinkel