Amanda Ferrari
Amanda Ferrari

Reputation: 946

Using default value in golang func

I'm trying to implement a default value according to the option 1 of the post Golang and default values. But when I try to do go install the following error pops up in the terminal:

not enough arguments in call to test.Concat1
    have ()
    want (string)

Code:

package test

func Concat1(a string) string {
  if a == "" {
    a = "default-a"
  }
  return fmt.Sprintf("%s", a)
}

// other package

package main

func main() {
  test.Concat1()
}

Thanks in advance.

Upvotes: 3

Views: 20223

Answers (4)

K. Davis
K. Davis

Reputation: 46

Golang does not support default parameters. Accordingly, variadic arguments by themselves are not analogous. However, variadic functions with the use of error handling can 'resemble' the pattern. Try the following as a simple example:

package main

import (
    "errors"
    "log"
)

func createSeries(p ...int) ([]int, error) {
    usage := "Usage: createSeries(<length>, <optional starting value>), length should be > 0"
    
    if len(p) == 0 {
        return nil, errors.New(usage)
    } 
    n := p[0]
    
    if n <= 0 {
        return nil, errors.New(usage)   
    }
    
    var base int
    if len(p) == 2 {
        base = p[1]
    } else if len(p) > 2 {
        return nil, errors.New(usage)
    }
    
        vals := make([]int, n)
    for i := 0; i < n; i++ {
        vals[i] = base + i
    }
    return vals, nil
}

func main() {
    answer, err := createSeries(4, -9)
    if err != nil {
        log.Fatal(err)
    }
    log.Println(answer)
}

Upvotes: 0

kostix
kostix

Reputation: 55453

Go does not have optional defaults for function arguments.

You may emulate them to some extent by having a special type to contain the set of parameters for a function.

In your toy example that would be something like

type Concat1Args struct {
  a string
}

func Concat1(args Concat1Args) string {
  if args.a == "" {
    args.a = "default-a"
  }
  return fmt.Sprintf("%s", args.a)
}

The "trick" here is that in Go each type has its respective "zero value", and when producing a value of a composite type using the so-called literal, it's possible to initialize only some of the type's fields, so in our example that would be

s := Concat1(Concat1Args{})

vs

s := Concat1(Concat1Args{"whatever"})

I know that looks clumsy, and I have showed this mostly for demonstration purpose. In real production code, where a function might have a dozen of parameters or more, having them packed in a dedicate composite type is usually the only sensible way to go but for a case like yours it's better to just explicitly pass "" to the function.

Upvotes: 2

gonutz
gonutz

Reputation: 5582

Default parameters work differently in Go than they do in other languages. In a function there can be one ellipsis, always at the end, which will keep a slice of values of the same type so in your case this would be:

func Concat1(a ...string) string {

but that means that the caller may pass in any number of arguments >= 0. Also you need to check that the arguments in the slice are not empty and then assign them yourself. This means they do not get assigned a default value through any kind of special syntax in Go. This is not possible but you can do

if a[0] == "" {
    a[0] = "default value"
}

If you want to make sure that the user passes either zero or one strings, just create two functions in your API, e.g.

func Concat(a string) string { // ...

func ConcatDefault() string {
    Concat("default value")
}

Upvotes: -1

jwells131313
jwells131313

Reputation: 2394

I don't think what you are trying to do will work that way. You may want to opt for option #4 from the page you cited, which uses variadic variables. In your case looks to me like you want just a string, so it'd be something like this:

func Concat1(a ...string) string {
  if len(a) == 0 {
    return "a-default"
  }
  return a[0]
}

Upvotes: 6

Related Questions