Pergunta

pode ir ter parâmetros opcionais? Ou posso apenas definir duas funções com o mesmo nome e um número diferente de argumentos?

Foi útil?

Solução

Go não tem opcional parâmetros nem suporta a sobrecarga de método :

Método envio é simplificado se não precisa fazer tipo correspondência como bem. Experiência com outros idiomas disse-nos que ter uma variedade de métodos com o mesmo nome, mas diferentes assinaturas foi ocasionalmente mas útil, que também poderia ser confuso e frágil na prática. Correspondiam apenas pelo nome e exigindo consistência nos tipos era um dos principais simplificando decisão no tipo de Go sistema.

Outras dicas

Uma boa maneira de conseguir algo como parâmetros opcionais é usar args variádicos. A função realmente recebe uma fatia de qualquer tipo que você especificar.

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

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

Você pode usar uma estrutura que inclui os 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})

Para arbitrária, potencialmente grande número de parâmetros opcionais, uma boa expressão idiomática é usar opções funcionais .

Para o seu tipo Foobar, primeira gravação apenas um construtor:

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
}

onde cada opção é uma função que transforma o Foobar. Em seguida, fornecer formas convenientes para o seu usuário para uso ou criar opções padrão, por exemplo:

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

Parque

Para concisão, você pode dar um nome ao tipo das opções ( Parque ):

type OptionFoobar func(*Foobar) error

Se precisar de parâmetros obrigatórios, adicioná-los como os primeiros argumentos do construtor antes do options variádica.

Os principais benefícios do opções funcionais idioma são:

  • seu API pode crescer ao longo do tempo sem quebrar o código existente, porque as estadias de assinatura constuctor o mesmo quando são necessárias novas opções.
  • permite que o caso de uso padrão para ser sua forma mais simples: sem argumentos em tudo
  • fornece um bom controle sobre a inicialização de valores complexos.

Esta técnica foi inventada por Rob Pike e também demonstrado por Dave Cheney .

Nem os parâmetros opcionais nem sobrecarga de funções são suportadas em Go. Go suporta um número variável de parâmetros: Passando argumentos para ... parâmetros

Não - nenhum dos dois. Por Ir para programadores C ++ docs,

Go não suporta a função sobrecarregando e não suporta usuário operadores definidos.

Não consigo encontrar uma declaração igualmente claro que os parâmetros opcionais são suportados, mas eles não são suportados também.

Você pode encapsular este muito bem em uma func semelhante ao que está abaixo.

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
}

Neste exemplo, o aviso por padrão tem dois pontos e um espaço na frente dele. . .

: 

. . . no entanto, você pode substituir essa, fornecendo um parâmetro para a função alerta.

prompt("Input here -> ")

Isto irá resultar em um prompt como abaixo.

Input here ->

Acabei usando uma combinação de uma estrutura de parâmetros e argumentos variádicos. Desta forma, eu não tenho que mudar a interface existente que foi consumido por vários serviços e meu serviço era capaz de passar parâmetros adicionais, conforme necessário. código de exemplo no playground golang: https://play.golang.org/p/G668FA97Nu

Eu sou um pouco tarde, mas se você gosta de interface fluente que você pode projetar seus setters para chamadas encadeadas como este:

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, em seguida, chamá-lo assim:

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

Este é semelhante ao opções funcionais idioma apresentado em resposta @Ripounet e goza dos mesmos benefícios, mas tem alguns inconvenientes:

  1. Se ocorrer um erro não vai abortar imediatamente, assim, seria um pouco menos eficiente se você espera que o seu construtor para relatar erros frequentemente.
  2. Você vai ter que gastar uma linha de declarar uma variável err e zerar-lo.

Há, no entanto, uma possível vantagem pequena, este tipo de chamadas de função deve ser mais fácil para o compilador linha, mas eu não sou realmente um especialista.

linguagem

Go não suporta a sobrecarga de método, mas você pode usar argumentos variádicos apenas como parâmetros opcionais, você também pode usar a interface {} como parâmetro, mas não é uma boa escolha.

Você pode passar arbitrários parâmetros nomeados com um mapa.

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})
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top