8

Опциональные параметры в Go?

18

Можно ли в Go использовать необязательные параметры? Или мне просто нужно определить две разные функции с одинаковым именем, но с разным количеством аргументов?

5 ответ(ов)

3

Для достижения чего-то подобного опциональным параметрам в Go можно использовать вариадические аргументы. Функция фактически принимает срез значений любого заданного вами типа.

Вот пример:

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

func main() {
    foo()          // Выводит: 0
    foo(1)        // Выводит: 1
    foo(1, 2, 3)  // Выводит: 3
}

В этом примере функция foo принимает произвольное количество целых чисел. Внутри функции вы можете работать с параметрами, как со срезом, что позволяет вам легко манипулировать переданными аргументами. Это удобный способ добавления гибкости в вашу функцию, не требуя создания множества перегруженных версий.

2

Вы можете использовать структуру, которая включает параметры:

type Params struct {
  a, b, c int
}

func doIt(p Params) int {
  return p.a + p.b + p.c 
}

// Вы можете вызвать функцию, не указывая все параметры
doIt(Params{a: 1, c: 9})

Главным преимуществом по сравнению с параметрами переменной длины (params ...SomeType) является то, что вы можете использовать эту структурированную переменную с параметрами разных типов.

0

Вы можете передавать произвольные именованные параметры с помощью карты. Учтите, что если параметры имеют неоднородные типы, вам нужно будет использовать утверждение типов в формате aType = map[key].(*foo.type).

Вот пример кода:

type varArgs map[string]interface{}

func myFunc(args varArgs) {

    arg1 := "default"
    if val, ok := args["arg1"]; ok {
        arg1 = val.(string)
    }

    arg2 := 123
    if val, ok := args["arg2"]; ok {
        arg2 = val.(int)
    }

    fmt.Println(arg1, arg2)
}

func Test_test() {
    myFunc(varArgs{"arg1": "value", "arg2": 1234})
}

В этом примере функция myFunc принимает переменное количество аргументов в виде карты, где ключи — это названия параметров, а значения — это любые типы, представленные как interface{}. Мы используем утверждения типов для получения значений аргументов с их предполагаемыми типами.

0

Кажется, я сильно запоздал с этой темой, но я искал способ сделать это лучше, чем тот, что я уже использую. Предложенное решение частично отвечает вашим требованиям, а также вводит концепцию необязательных аргументов.

package main

import "fmt"

type FooOpts struct {
    // необязательные аргументы
    Value string
}

func NewFoo(mandatory string) {
    NewFooWithOpts(mandatory, &FooOpts{})
}

func NewFooWithOpts(mandatory string, opts *FooOpts) {
    if opts != nil {
        fmt.Println("Hello " + opts.Value)
    } else {
        fmt.Println("Hello")
    }
}

func main() {
    NewFoo("пожалуйста, заставьте это работать")

    NewFooWithOpts("Пожалуйста, заставьте это работать", &FooOpts{Value: " Мир"})
}

Обновление 1:

Добавил функциональный пример, чтобы показать, как это работает.

0

Вы можете использовать указатели и оставлять их nil, если не хотите их использовать:

func getPosts(limit *int) {
    if limit != nil {
        // получить посты с ограничением
    } else {
        // получить все посты
    }
}

func main() {
    // получить посты, ограничивая до 2
    limit := 2
    getPosts(&limit)

    // получить все посты
    getPosts(nil)
}

Такой подход позволяет вам передавать nil, когда ограничение не требуется, и использовать указатели, чтобы избежать передачи "магических" значений.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь