『Tucker의 Go 언어 프로그래밍』 스터디 요약 노트입니다.
13장. 구조체
구조체의 Go 언어에서의 특징만 확인해보자.
class
가 없이,struct
만 존재한다.- 상속의
is-a
관계가 아닌has-a
관계로만 구조체 관계를 정의한다. - 구조체 속의 구조체 사용에서, 내부 구조체 필드 이름을 제외하면 구조체 확장과 비슷하게 사용할 수 있다.
- 메서드의 선언, 정의는 구조체 밖에서 이루어진다.
이 중 메서드 관련 내용은 추후 책에서 다루므로 여기에선 간단하게 무슨 의미인지 언급만 하고 지나가도록 하겠다.
구조체의 선언
책에서는 무조건적으로 struct
타입 선언 시, 타입 명을 같이 선언해야 하는 것 처럼 표현되어있지만, 타입 이름이 없는 익명 구조체 타입을 선언할 수 있다. (물론 활용도가 이름 있는 타입에 비해 떨어지기 때문에 없다고 생각해도 무방할 것으로 보인다.)
|
|
$ ./go_anonymous_struct
{ 0 }
{John Doe 1 1 234-567-890}
{Jane Doe 2 1 234-567-890}
구조체를 포함하는 구조체
먼저 다른 구조체를 일반 타입처럼 포함하는 방식으로 실험해보자. 추가로 내부 구조체를 변수로 선언한 뒤, 바로 복사가 가능한지, 구조체 내부 필드 중 일부만 초기화하는 것도 확인해보자.
|
|
$ ./go_struct_in_struct
{{John Doe 1 30} 1 0001-01-01 00:00:00 +0000 UTC}
{{Jane Doe 2 32} 2 2021-05-31 13:06:28.78326 +0900 KST m=+0.000120543}
VIP user Jane Doe became VIP since 2021-05-31 13:06:28.78326 +0900 KST m=+0.000120543
이제 포함된 필드(Embedded field) 방식으로 다시 실험해보자.
|
|
$ ./go_embedded_struct
{{John Doe 1 30} 1 0001-01-01 00:00:00 +0000 UTC}
{{Jane Doe 2 32} 2 2021-05-31 13:13:14.075062 +0900 KST m=+0.000131959}
VIP user Jane Doe became VIP since 2021-05-31 13:13:14.075062 +0900 KST m=+0.000131959
구조체 패딩
go에서도 구조체 내 멤버 접근 속도를 빠르게 하기 위해 메모리 패딩을 수행한다. 확실한 비교를 위해 책에 나온 예제에서 주소 값까지 찍어보자.
|
|
$ ./go_struct_padding
sizeof Unoptimized: 40, Optimized: 24
Unoptimized
A: 0x140000b2030
B: 0x140000b2038
C: 0x140000b2040
D: 0x140000b2048
E: 0x140000b2050
Optimized
A: 0x140000ba000
B: 0x140000ba008
C: 0x140000ba001
D: 0x140000ba010
E: 0x140000ba002
구조체의 메서드
비슷하게 struct
만 사용할 수 있는 C언어와 비교해보자.
// struct 선언
struct MyStr {
uint capacity;
uint length;
char *storage;
// method 목록 선언 (함수 포인터)
int (*GetLength)(struct MyStr *ms);
void (*Append)(struct MyStr *ms, struct MyStr *follow);
};
// method 구현 (함수 정의)
int _getLength(struct MyStr *ms) {
// Implemenation...
};
void _append(struct MyStr *ms, struct MyStr *follow) {
// Implemenation...
};
// struct 변수 초기화
struct MyStr str1 = {0, 0, NULL};
str1.GetLength = _getLength; // 함수 포인터 매핑
str1.Append = _append; // 함수 포인터 매핑
// struct method 사용
int length = str1.GetLength(&str1);
str1.Append(&str1, &str2);
// struct 선언
type MyStr struct {
capacity uint
length uint
storage *byte;
}
// method 선언, 정의
func (ms *MyStr) Length() int {
// Implementation...
}
func (ms *MyStr) Append(MyStr *follow) {
// Implementation...
}
// struct 변수 초기화
var str1 MyStr = MyStr {0, 0, nil}
// struct method 사용
length := str1.GetLength();
str1.Append(&str2);
위 예시에서 보듯 method
목록 선언이 구조체 밖에서 이루어진다. 더 자세한 부분은 추후 메서드를 다루는 장에서 자세히 보도록 하겠다.