Domanda

Può Andare avere parametri opzionali? O posso solo definire due funzioni con lo stesso nome e un diverso numero di argomenti?

È stato utile?

Soluzione

Go non ha parametri opzionali né supporta il metodo sovraccarico :

  

Metodo spedizione è semplificata se   non ha bisogno di fare il tipo di corrispondenza come   bene. L'esperienza con altre lingue   ci ha detto che avere una varietà di   metodi con lo stesso nome, ma   firme diverse era tanto in tanto   utile ma che potrebbe anche essere   confusa e fragile nella pratica.   Corrispondenza solo per nome e che richiedono   coerenza nei tipi era un importante   semplificando decisione tipo di Go   sistema.

Altri suggerimenti

Un bel modo per ottenere qualcosa come parametri opzionali è quello di utilizzare args variadic. La funzione riceve effettivamente una fetta di qualunque tipo specificato.

func foo(params ...int) {
    fmt.Println(len(params))
}

func main() {
    foo()
    foo(1)
    foo(1,2,3)
}

È possibile utilizzare una struttura che comprende i parametri:

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})

Per arbitraria, numero potenzialmente elevato di parametri opzionali, un bel linguaggio è quello di utilizzare Opzioni funzionali .

Per il tipo di Foobar, primo scrivere solo un costruttore:

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
}

dove ogni opzione è una funzione che muta la Foobar. Quindi fornire modi convenienti per l'utente di utilizzare o creare opzioni standard, ad esempio:

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
  }
}

giochi

Per brevità, si può dare un nome al tipo di opzioni ( Playground ):

type OptionFoobar func(*Foobar) error

Se avete bisogno di parametri obbligatori, aggiungerli come primi argomenti del costruttore prima della options variadic.

I principali vantaggi del Opzioni funzionali idioma sono:

  • la tua API può crescere nel tempo senza rompere il codice esistente, perché la firma constuctor rimane lo stesso quando sono necessarie nuove opzioni.
  • permette il caso d'uso di default di essere la sua più semplice: nessun argomento a tutti
  • fornisce un controllo preciso l'inizializzazione di valori complessi.

Questa tecnica è stato coniato da Rob Pike e anche dimostrato da Dave Cheney .

Né parametri opzionali né l'overloading di funzioni sono supportate in Go. Go supporta un numero variabile di parametri: Passaggio di argomenti a ... parametri

No - nessuno dei due. Per il Andare per programmatori C ++ docs,

  

Go non supporta la funzione   sovraccarichi e non supporta utenti   operatori definiti.

Non riesco a trovare una dichiarazione altrettanto chiaro che i parametri opzionali non sono supportati, ma non sono supportate sia.

È possibile incapsulare questo abbastanza bene in un func simile a ciò che è al di sotto.

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
}

In questo esempio, il prompt di default ha due punti e uno spazio di fronte ad essa. . .

: 

. . . tuttavia è possibile ignorare che fornendo un parametro alla funzione pronta.

prompt("Input here -> ")

Questo si tradurrà in un prompt come qui di seguito.

Input here ->

Ho finito per usare una combinazione di una struttura di params e args variadic. In questo modo, io non ha dovuto modificare l'interfaccia esistente che è stato consumato da diversi servizi e il mio servizio è stato in grado di passare params aggiuntivi, se necessario. codice di esempio in un parco giochi golang: https://play.golang.org/p/G668FA97Nu

Io sono un po 'in ritardo, ma se vi piace l'interfaccia fluente si potrebbe progettare le setter per le chiamate concatenate in questo modo:

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
}

E poi chiamare in questo modo:

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)
  }
}

Questo è simile alla Opzioni funzionali idioma presentato in risposta @Ripounet e gode degli stessi benefici, ma ha alcuni svantaggi:

  1. Se si verifica un errore non interrompe immediatamente, in tal modo, sarebbe un po 'meno efficiente se vi aspettate il vostro costruttore di segnalare gli errori spesso.
  2. Dovrete passare una linea di dichiarare una variabile err e l'azzeramento di esso.

V'è, tuttavia, un eventuale piccolo vantaggio, questo tipo di chiamate di funzione dovrebbe essere più facile per il compilatore inline ma io non sono davvero uno specialista.

Vai linguaggio non supporta overloading dei metodi, ma è possibile utilizzare args variadic proprio come parametri opzionali, inoltre è possibile usare l'interfaccia {} come parametro, ma non è una buona scelta.

È possibile passare arbitrari parametri denominati con una mappa.

type varArgs map[string]interface{}

func myFunc(args varArgs) {

    arg1 := "default" // optional default value
    if val, ok := args["arg1"]; ok {
        // value override or other action
        arg1 = val.(string) // runtime panic if wrong type
    }

    arg2 := 123 // optional default value
    if val, ok := args["arg2"]; ok {
        // value override or other action
        arg2 = val.(int) // runtime panic if wrong type
    }

    fmt.Println(arg1, arg2)
}

func Test_test() {
    myFunc(varArgs{"arg1": "value", "arg2": 1234})
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top