문제

선택적 매개 변수를 가질 수 있습니까? 아니면 동일한 이름과 다른 수의 인수로 두 기능을 정의 할 수 있습니까?

도움이 되었습니까?

해결책

GO에는 선택적 매개 변수가 없습니다 또한 방법 과부하를 지원하지도 않습니다:

유형 일치를 수행 할 필요가 없으면 메소드 디스패치가 단순화됩니다. 다른 언어에 대한 경험은 동일한 이름을 가진 다양한 방법을 가지고 있지만 다른 서명이 때때로 유용하지만 실제로는 혼란스럽고 깨지기 쉬울 수 있다고 말했습니다. 이름 만 일치시키고 유형의 일관성이 필요한 것은 GO 유형 시스템에서 주요 단순화 결정이었습니다.

다른 팁

옵션 매개 변수와 같은 것을 달성하는 좋은 방법은 Variadic Args를 사용하는 것입니다. 이 기능은 실제로 지정한 유형의 슬라이스를 수신합니다.

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

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

매개 변수를 포함하는 구조물을 사용할 수 있습니다.

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

임의의 경우 잠재적으로 많은 수의 선택적 매개 변수를 사용하면 멋진 관용구가 사용하는 것입니다. 기능적 옵션.

당신의 유형을 위해 Foobar, 먼저 하나의 생성자 만 작성하십시오.

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
}

여기서 각 옵션은 foobar를 돌연변이하는 함수입니다. 그런 다음 사용자가 표준 옵션을 사용하거나 생성 할 수있는 편리한 방법을 제공합니다 (예 : 예 :

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

운동장

간결하게, 당신은 옵션 유형에 이름을 줄 수 있습니다 (운동장) :

type OptionFoobar func(*Foobar) error

필수 매개 변수가 필요한 경우 변수 이전에 생성자의 첫 번째 인수로 추가하십시오. options.

의 주요 이점 기능적 옵션 관용구는 다음과 같습니다.

  • 새로운 옵션이 필요할 때 Constuctor 서명이 동일하게 유지되기 때문에 기존 코드를 깨지 않고 시간이 지남에 따라 API가 증가 할 수 있습니다.
  • 기본 사용 사례가 가장 간단 할 수 있습니다. 전혀 논쟁이 없습니다!
  • 복잡한 값의 초기화를 잘 제어 할 수 있습니다.

이 기술은 만들어졌습니다 롭 파이크 또한 입증되었습니다 데이브 체니.

옵션 매개 변수 나 기능 과부하는 GO에 지원되지 않습니다. GO는 가변 수의 매개 변수를 지원합니다. 인수를 ... 매개 변수로 전달합니다

아니요 - 둘 다. 당 C ++ 프로그래머로 이동하십시오 문서,

GO는 기능 과부하를 지원하지 않으며 사용자 정의 연산자를 지원하지 않습니다.

선택적 매개 변수가 지원되지 않다는 똑같이 명확한 진술을 찾을 수는 없지만 지원되지 않습니다.

아래와 비슷한 기능으로 이것을 아주 멋지게 캡슐화 할 수 있습니다.

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
}

이 예에서는 기본적으로 프롬프트에는 결장과 그 앞에 공간이 있습니다. . .

: 

. . . 그러나 프롬프트 함수에 매개 변수를 제공하여이를 재정의 할 수 있습니다.

prompt("Input here -> ")

이로 인해 아래와 같은 프롬프트가 발생합니다.

Input here ->

나는 매개 변수의 구조와 변동성 args의 조합을 사용하게되었습니다. 이런 식으로 여러 서비스에서 소비 한 기존 인터페이스를 변경할 필요가 없었으며 내 서비스는 필요에 따라 추가 매개 변수를 전달할 수있었습니다. Golang Playground의 샘플 코드 : https://play.golang.org/p/g668fa97nu

나는 조금 늦었지만 유창한 인터페이스를 좋아한다면 이와 같이 묶인 전화를 위해 세터를 설계 할 수 있습니다.

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
}

그런 다음 다음과 같이 부릅니다.

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

이것은와 유사합니다 기능적 옵션 Idiom은 @ripounet 답변에 발표되었으며 동일한 혜택을 누리지 만 몇 가지 단점이 있습니다.

  1. 오류가 발생하면 즉시 중단되지 않으므로 생성자가 오류를 자주보고 할 것으로 예상하면 약간 덜 효율적입니다.
  2. 당신은 선언하는 줄을 보내야합니다 err 변수 및 제로화.

그러나 가능한 작은 이점이 있습니다. 이러한 유형의 기능 호출은 컴파일러가 인라인이 더 쉬워야하지만 실제로 전문가는 아닙니다.

Go Language는 메소드 오버로드를 지원하지 않지만 선택적 매개 변수와 마찬가지로 Variadic Args를 사용할 수 있으며 인터페이스 {}를 매개 변수로 사용할 수도 있지만 좋은 선택은 아닙니다.

맵을 사용하여 임의의 이름이라는 매개 변수를 전달할 수 있습니다.

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})
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top