Go 구조체에서 기본값을 설정하는 방법


143

아래 질문에 대한 답변 / 기술은 여러 가지가 있습니다.

  1. golang 구조체에 기본값을 설정하는 방법은 무엇입니까?
  2. golang에서 구조체를 초기화하는 방법

몇 가지 답변이 있지만 추가 토론이 필요합니다.



@icza 당신이 대답 할 수있는 방법을 제공하지만 질문 제목으로가는 것은 매우 구체적인 질문이므로 유사하거나 검색 할 수는 없습니다. 그래도 답변에 링크를 추가 할 것입니다.
Prateek

여기에 두 가지 질문이 있습니다. 하나를 선택하십시오. 첫 번째 질문을 선택한다고 가정하면 (질문 제목 별) 이전 연구와 다른 답변에 더 많은 논의가 필요한 위치에 대해 더 구체적으로 설명하십시오.
던컨 존스

답변:


96

하나의 가능한 아이디어는 별도의 생성자 함수를 작성하는 것입니다

//Something is the structure we work with
type Something struct {
     Text string 
     DefaultText string 
} 
// NewSomething create new instance of Something
func NewSomething(text string) Something {
   something := Something{}
   something.Text = text
   something.DefaultText = "default text"
   return something
}

6
그렇습니다. 이것은 내 대답에서 언급 한 방법 중 하나이지만 다른 사람 이이 기능 만 사용하도록 강요 할 수있는 방법은 없습니다.
Prateek

@Prateek 이것은 이것이거나 인터페이스를 사용하며, 추악하고 지나치게 복잡합니다.
OneOfOne

31
@Prateek 예, 단순히 유형 자체를 내 보내지 않으면 사람들 이이 생성자를 사용하도록 할 수 있습니다. 당신은 함수를 내보낼 수 있습니다 NewSomething, 심지어 필드 TextDefaultText 있었으나 결국 구조체 유형을 내 보내지 않습니다 something.
쿠마 굽타를

1
문제는 더 나쁘다 ... 예를 들어 제 3 자 (예 : 라이브러리)를 사용하여 구조체를 인스턴스화 reflect.New()하면 특별히 명명 된 팩토리 기능에 대해 알 수 없었습니다. 이 경우 언어 자체가 부족 하여 인터페이스 (라이브러리가 확인할 수있는 인터페이스 ) 수행됩니다.
에담

1
기본값을 설정하는 것이 좋지만 때로는 기본값을 무시하고 싶을 수도 있습니다. 이 경우 기본값이 아닌 값으로 구조체를 초기화 할 수 없습니다. 나를 위해 조금 성가신
Juliatzin

68
  1. 메소드가 구조체를 생성하도록합니다 (생성자 방식).

    좋은 디자인은 타입을 익스포트하지 않지만 NewMyType ()과 같은 익스포트 된 생성자 함수를 제공하여 구조체 / 타입을 적절히 초기화하는 것입니다. 또한 구체적인 유형이 아닌 인터페이스 유형을 반환하십시오. 인터페이스에는 다른 사용자가 원하는 모든 것을 포함해야합니다. 그리고 구체적인 유형은 물론 해당 인터페이스를 구현해야합니다.

    단순히 형식 자체를 내 보내지 않음으로써 수행 할 수 있습니다. NewSomething 함수와 Text 및 DefaultText 필드를 내보낼 수 있지만 구조체 유형을 내 보내지 마십시오.

  2. 자신의 모듈에 맞게 모듈을 사용자 정의하는 또 다른 방법은 구성 구조체를 사용하여 기본값을 설정 하는 것입니다 (링크의 옵션 5).



3
웨이 백 머신 에서 사용할 수 있습니다 .
n8henrie

FWIW, 나는 그것이 적어도 옵션 시스템이라고 생각합니다. ( '옵션 5'는 없습니다).
decimus phostle

@ 공용 인터페이스 유형을 반환로 함수를 선언 할 수 있습니다 침묵 golint에 M90
토마스 그레인저을

@ThomasGrainger 내 의견은이 답변의 이전 개정을 언급하는 것 같습니다. 더 이상 이런 말이되지 않습니다 :) 그냥 삭제합니다.
m90

32

Victor Zamanian의 답변 1 옵션의 한 가지 문제는 유형을 내 보내지 않으면 패키지 사용자가 함수 매개 변수 등의 유형으로 선언 할 수 없다는 것입니다. 구조체 예

package candidate
// Exporting interface instead of struct
type Candidate interface {}
// Struct is not exported
type candidate struct {
    Name string
    Votes uint32 // Defaults to 0
}
// We are forced to call the constructor to get an instance of candidate
func New(name string) Candidate {
    return candidate{name, 0}  // enforce the default value here
}

내 보낸 Candidate 인터페이스를 사용하여 함수 매개 변수 유형을 선언 할 수 있습니다. 이 솔루션에서 볼 수있는 유일한 단점은 인터페이스 정의에서 모든 메소드를 선언해야하지만 어쨌든 좋은 습관이라고 주장 할 수 있습니다.


새 함수 호출 후 이름 및 투표 변수를 변경할 수 있습니까?
morteza khadem

좋은 간단한 예입니다.

작은 오타 : Votes unit32아마해야합니다Votes uint32
PartyLich

@PartyLich는 잘 발견되었습니다. 수정해야합니다.
wolfson109

13

여러 기본값을 허용하는 태그를 사용하여이를 수행하는 방법이 있습니다.

기본 태그가 default0default1 인 다음과 같은 구조체가 있다고 가정합니다 .

type A struct {
   I int    `default0:"3" default1:"42"`
   S string `default0:"Some String..." default1:"Some Other String..."`
}

이제 기본값을 설정할 수 있습니다.

func main() {

ptr := &A{}

Set(ptr, "default0")
fmt.Printf("ptr.I=%d ptr.S=%s\n", ptr.I, ptr.S)
// ptr.I=3 ptr.S=Some String...

Set(ptr, "default1")
fmt.Printf("ptr.I=%d ptr.S=%s\n", ptr.I, ptr.S)
// ptr.I=42 ptr.S=Some Other String...
}

놀이터에서 완성 된 프로그램은 다음과 같습니다. .

더 복잡한 예제에 관심이 있다면 슬라이스와 맵으로 말하면 잔인 함 / 기본값을 살펴보십시오.


고마워요! 나는 도서관이 제안한 것과 같은 코드를 작성하기 시작 했고이 게시물을 보았습니다. 정확히 원하는 것을 수행합니다 ( github.com/creasty/defaults ). 값이 없으면 기본값을 설정하지만 변수에 값을 할당하면 기본값이 할당되지 않습니다. yaml.v2 라이브러리와 잘 작동합니다.
Nordes

3

에서 https://golang.org/doc/effective_go.html#composite_literals :

이 예제에서 os 패키지에서 파생 된 것처럼 0 값이 충분하지 않고 초기화 생성자가 필요한 경우가 있습니다.

    func NewFile(fd int, name string) *File {
      if fd < 0 {
        return nil
      }
      f := new(File)
      f.fd = fd
      f.name = name
      f.dirinfo = nil
      f.nepipe = 0
      return f
}

-3
type Config struct {
    AWSRegion                               string `default:"us-west-2"`
}

1
이것은 올바르지 않습니다. 기껏해야 해당 필드에 태그 값을 설정 한 다음 리플렉션을 사용하여 해당 값을 얻을 수 있지만이 경우에도 구문이 잘못되어 (틱이 누락 됨) 문자열 유형의 기본값 만 설정할 수 있습니다. 이 예에서 구체적으로 언급 한 내용에 대한 통찰력이있는 경우 참조 할 링크를 추가하십시오.
markeissler
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.