> 백엔드 개발 > Golang > Go Struct에 대해 자세히 알아보기

Go Struct에 대해 자세히 알아보기

Linda Hamilton
풀어 주다: 2025-01-04 05:02:40
원래의
425명이 탐색했습니다.

Go에서 구조체는 데이터를 정의하고 캡슐화하는 데 사용되는 집계 유형입니다. 다양한 유형의 필드를 결합할 수 있습니다. 구조체는 다른 언어의 클래스와 유사한 사용자 정의 데이터 유형으로 볼 수 있지만 상속을 지원하지 않습니다. 메소드는 특정 유형(주로 구조체)과 연관된 함수이며 해당 유형의 인스턴스를 사용하여 호출할 수 있습니다.

구조체 정의 및 초기화

구조체 정의

구조체는 type 및 struct 키워드를 사용하여 정의됩니다. 다음은 간단한 구조체 정의의 예입니다.

type User struct {
  Username    string
  Email       string
  SignInCount int
  IsActive    bool
}
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사

구조체 초기화

구조체는 다양한 방법으로 초기화할 수 있습니다.

필드 이름으로 초기화

user1 := User{
  Username:    "alice",
  Email:       "alice@example.com",
  SignInCount: 1,
  IsActive:    true,
}
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사

기본값으로 초기화

일부 필드를 지정하지 않으면 해당 유형에 대해 0 값으로 초기화됩니다.

user2 := User{
  Username: "bob",
}
로그인 후 복사
로그인 후 복사
로그인 후 복사

이 예에서 이메일은 빈 문자열("")로, SignInCount는 0으로, IsActive는 false로 초기화됩니다.

포인터로 초기화

포인터를 사용하여 구조체를 초기화할 수도 있습니다.

user3 := &User{
  Username: "charlie",
  Email:    "charlie@example.com",
}
로그인 후 복사
로그인 후 복사

구조체의 방법과 동작

Go에서 구조체는 데이터를 저장하는 용도일 뿐만 아니라 구조체에 대해 정의된 메서드도 가질 수 있습니다. 이를 통해 구조체는 데이터와 관련된 동작을 캡슐화할 수 있습니다. 다음은 구조체 메소드 및 동작에 대한 자세한 설명입니다.

구조체에 대한 메서드 정의

메소드는 메소드의 첫 번째 매개변수인 수신자를 사용하여 정의되며 메소드가 속한 유형을 지정합니다. 수신자는 값 수신자 또는 포인터 수신자가 될 수 있습니다.

가치수신자

메서드가 호출될 때 값 수신자는 구조체의 복사본을 생성하므로 필드를 수정해도 원래 구조체에는 영향을 미치지 않습니다.

type User struct {
  Username string
  Email    string
}

func (u User) PrintInfo() {
  fmt.Printf("Username: %s, Email: %s\n", u.Username, u.Email)
}
로그인 후 복사
로그인 후 복사

포인터 수신기

포인터 수신기를 사용하면 메서드가 원래 구조체 필드를 직접 수정할 수 있습니다.

func (u *User) UpdateEmail(newEmail string) {
  u.Email = newEmail
}
로그인 후 복사

방법 세트

Go에서는 구조체의 모든 메소드가 메소드 세트를 구성합니다. 값 수신기에 설정된 메서드에는 값 수신기가 있는 모든 메서드가 포함되는 반면, 포인터 수신기에 설정된 메서드에는 포인터와 값 수신기가 모두 포함된 모든 메서드가 포함됩니다.

인터페이스 및 구조체 메서드

다형성을 달성하기 위해 구조체 메서드가 인터페이스와 함께 사용되는 경우가 많습니다. 인터페이스를 정의할 때 구조체가 구현해야 하는 메서드를 지정합니다.

type UserInfo interface {
  PrintInfo()
}

// User implements the UserInfo interface
func (u User) PrintInfo() {
  fmt.Printf("Username: %s, Email: %s\n", u.Username, u.Email)
}

func ShowInfo(ui UserInfo) {
  ui.PrintInfo()
}
로그인 후 복사

구조체의 메모리 정렬

Go에서는 구조체의 메모리 정렬이 액세스 효율성을 향상시키도록 설계되었습니다. 다양한 데이터 유형에는 특정한 정렬 요구 사항이 있으며, 컴파일러는 이러한 요구 사항을 충족하기 위해 구조체 필드 사이에 패딩 바이트를 삽입할 수 있습니다.

메모리 정렬이란 무엇입니까?

메모리 정렬은 메모리의 데이터가 특정 값의 배수인 주소에 위치해야 함을 의미합니다. 데이터 유형의 크기에 따라 정렬 요구 사항이 결정됩니다. 예를 들어 int32는 4바이트로 정렬이 필요하고 int64는 8바이트로 정렬이 필요합니다.

메모리 정렬이 필요한 이유는 무엇입니까?

CPU 성능을 위해서는 효율적인 메모리 액세스가 중요합니다. 변수가 제대로 정렬되지 않으면 CPU에서 데이터를 읽거나 쓰기 위해 여러 메모리에 액세스해야 하므로 성능이 저하될 수 있습니다. 컴파일러는 데이터를 정렬함으로써 효율적인 메모리 액세스를 보장합니다.

구조체 메모리 정렬 규칙

  • 필드 정렬: 각 필드의 주소는 해당 유형의 정렬 요구 사항을 충족해야 합니다. 컴파일러는 올바른 정렬을 보장하기 위해 필드 사이에 패딩 바이트를 삽입할 수 있습니다.
  • 구조체 정렬: 구조체의 크기는 해당 필드 중 가장 큰 정렬 요구 사항의 배수여야 합니다.

예:

type User struct {
  Username    string
  Email       string
  SignInCount int
  IsActive    bool
}
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사

출력: 12

분석:

  • a는 int8이며 1바이트를 차지하고 1로 정렬됩니다.
  • b는 int32이며 4바이트로 정렬해야 합니다. 컴파일러는 b의 주소를 4로 정렬하기 위해 a와 b 사이에 3개의 패딩 바이트를 삽입합니다.
  • c는 int8이며 1바이트가 필요하지만 구조체의 전체 크기는 4의 배수(가장 큰 정렬 요구 사항)여야 합니다. 컴파일러는 끝에 3개의 패딩 바이트를 추가합니다.

메모리 정렬 최적화

구조체 필드를 재정렬하여 패딩을 최소화하고 메모리 사용량을 줄일 수 있습니다.

user1 := User{
  Username:    "alice",
  Email:       "alice@example.com",
  SignInCount: 1,
  IsActive:    true,
}
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사

출력: 8

이 최적화 버전에서는 b가 먼저 배치되어 4바이트로 정렬됩니다. a와 c가 연속적으로 배치되어 전체 크기가 8바이트로 최적화되지 않은 버전보다 컴팩트해졌습니다.

요약

  • Go의 구조체 필드는 잠재적인 패딩 바이트와 함께 정렬 요구 사항에 따라 메모리가 할당됩니다.
  • 필드 순서를 조정하면 패딩을 최소화하고 메모리 사용량을 최적화할 수 있습니다.
  • unsafe.Sizeof를 사용하여 구조체의 실제 메모리 크기를 확인하세요.

중첩된 구조체 및 구성

Go에서 중첩된 구조체와 구성은 코드 재사용과 복잡한 데이터 구성을 위한 강력한 도구입니다. 중첩된 구조체를 사용하면 구조체가 다른 구조체를 필드로 포함하여 복잡한 데이터 모델을 생성할 수 있습니다. 반면에 컴포지션은 다른 구조체를 포함하여 새로운 구조체를 생성하여 코드 재사용을 촉진합니다.

중첩된 구조체

중첩 구조체를 사용하면 하나의 구조체가 다른 구조체를 필드로 포함할 수 있습니다. 이는 데이터 구조를 더욱 유연하고 체계적으로 만듭니다. 다음은 중첩된 구조체의 예입니다.

type User struct {
  Username    string
  Email       string
  SignInCount int
  IsActive    bool
}
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사

구조체 구성

컴포지션을 사용하면 여러 구조체를 새 구조체로 결합하여 코드 재사용이 가능합니다. 구성에서 구조체는 여러 다른 구조체를 필드로 포함할 수 있습니다. 이는 보다 복잡한 모델을 구축하고 공통 필드 또는 방법을 공유하는 데 도움이 됩니다. 다음은 구조체 구성의 예입니다.

user1 := User{
  Username:    "alice",
  Email:       "alice@example.com",
  SignInCount: 1,
  IsActive:    true,
}
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사

중첩 구조체와 구성의 차이점

  • 중첩 구조체: 한 구조체의 필드 유형이 다른 구조체인 경우 구조체를 결합하는 데 사용됩니다. 이 접근 방식은 계층적 관계가 있는 데이터 모델을 설명하는 데 종종 사용됩니다.
  • 구성: 구조체가 여러 다른 구조체의 필드를 포함할 수 있습니다. 이 방법은 코드 재사용을 달성하여 구조체가 더 복잡한 동작과 속성을 가질 수 있도록 하는 데 사용됩니다.

요약

중첩된 구조체와 구성은 복잡한 데이터 구조를 구성하고 관리하는 데 도움이 되는 Go의 강력한 기능입니다. 데이터 모델을 디자인할 때 중첩된 구조체와 구성을 적절하게 사용하면 코드를 더 명확하고 유지 관리하기 쉽게 만들 수 있습니다.

빈 구조체

Go에서 빈 구조체는 필드가 없는 구조체입니다.

크기 및 메모리 주소

빈 구조체는 0바이트의 메모리를 차지합니다. 그러나 메모리 주소는 상황에 따라 같을 수도 있고 같지 않을 수도 있습니다. 메모리 이스케이프가 발생하면 주소가 동일하여 런타임.제로베이스를 가리킵니다.

user2 := User{
  Username: "bob",
}
로그인 후 복사
로그인 후 복사
로그인 후 복사

출력에서 변수 a, b 및 zerobase는 동일한 주소를 공유하며 모두 전역 변수 Runtime.zerobase(runtime/malloc.go)를 가리킵니다.

탈출 시나리오 관련:

  • 변수 c와 d가 힙으로 탈출합니다. 해당 주소는 0x590d00이며 동일(true)으로 비교됩니다.
  • 변수 e와 f는 서로 다른 주소(0xc00008ef47)를 가지며 같지 않음(false)을 비교합니다.

이 동작은 Go에서 의도적인 것입니다. 빈 구조체 변수가 이스케이프되지 않으면 해당 포인터가 동일하지 않습니다. 탈출 후 포인터는 동일해집니다.

빈 구조체를 포함할 때 공간 계산

빈 구조체 자체는 공간을 차지하지 않지만 다른 구조체에 포함되면 위치에 따라 공간을 차지할 수 있습니다.

  • 구조체에 유일한 필드인 경우 구조체는 공간을 차지하지 않습니다.
  • 첫 번째 또는 중간 필드인 경우 공간을 차지하지 않습니다.
  • 마지막 필드인 경우 이전 필드와 동일한 공간을 차지합니다.
user3 := &User{
  Username: "charlie",
  Email:    "charlie@example.com",
}
로그인 후 복사
로그인 후 복사

빈 구조체가 배열 또는 슬라이스의 요소인 경우:

type User struct {
  Username string
  Email    string
}

func (u User) PrintInfo() {
  fmt.Printf("Username: %s, Email: %s\n", u.Username, u.Email)
}
로그인 후 복사
로그인 후 복사

응용

빈 구조체의 크기가 0인 속성을 사용하면 추가 메모리 오버헤드 없이 다양한 목적으로 사용할 수 있습니다.

키가 지정되지 않은 구조체 초기화 방지

type User struct {
  Username    string
  Email       string
  SignInCount int
  IsActive    bool
}
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사

집합 데이터 구조 구현

user1 := User{
  Username:    "alice",
  Email:       "alice@example.com",
  SignInCount: 1,
  IsActive:    true,
}
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사

채널을 통한 신호 전송

때때로 채널을 통해 전송되는 데이터의 내용은 신호로만 사용되어 관련이 없습니다. 예를 들어 세마포어 구현에서는 빈 구조체를 사용할 수 있습니다.

user2 := User{
  Username: "bob",
}
로그인 후 복사
로그인 후 복사
로그인 후 복사

Go 프로젝트를 클라우드에 배포하기 위한 최고의 선택, Leapcell입니다.

Deep Dive into Go Struct

Leapcell은 웹 호스팅, 비동기 작업 및 Redis를 위한 차세대 서버리스 플랫폼입니다.

  1. 다국어 지원
  • JavaScript, Python, Go 또는 Rust를 사용하여 개발하세요.
  1. 무제한 프로젝트를 무료로 배포
  • 사용한 만큼만 지불하세요. 요청이나 요금이 부과되지 않습니다.
  1. 탁월한 비용 효율성
  • 유휴 비용 없이 사용한 만큼만 지불하세요.
  • 예: $25는 평균 응답 시간 60ms에서 694만 개의 요청을 지원합니다.
  1. 간소화된 개발자 경험
  • 손쉬운 설정을 위한 직관적인 UI.
  • 완전 자동화된 CI/CD 파이프라인 및 GitOps 통합.
  • 실행 가능한 통찰력을 위한 실시간 측정항목 및 로깅.
  1. 손쉬운 확장성과 고성능
  • 자동 확장을 통해 높은 동시성을 쉽게 처리할 수 있습니다.
  • 운영 오버헤드가 전혀 없습니다. 구축에만 집중하세요.

문서에서 더 자세히 알아보세요!

X에서 우리를 팔로우하세요: @LeapcellHQ


저희 블로그에서 읽어보세요

위 내용은 Go Struct에 대해 자세히 알아보기의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:dev.to
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿