Go에서 제공하는 표준 타입만 잘 써도 충분히 유연하고 빠르게 처리할 수 있다. 하지만 Go로 구현하는 코드에 필요한 모든 종류의 데이터를 직접 표현하기에는 한계가 있다. 그래서 Go 언어는 프로그래머가 원하는 타입을 정의할 수 있도록 struct
를 제공한다.
다양한 타입의 변수를 묶어서 새로운 타입으로 정의하고 싶다면 구조체를 사용해야 한다. 이렇게 구조체를 구성하는 요소를 fields of the structure
라 부른다.
구조체의 field는 주로 대문자
로 시작한다. 소문자로 시작하면 외부에서 사용할 수 없다.
type user struct {
UserName string
Age int
}
// case 1
user := user{"chris", 10}
// case 2
user := user{UserName: "chris", Age: 10}
// case 3
user := user {
UserName: "chris",
Age: 10,
}
,
로 끝나야 한다.Go에서는 구조체를 익명 타입으로 구성할 수 있다. 두 익명 타입 구조체가 동일한 field를 가지고 있어서 두 구조체의 field의 순서가 다르면 서로 대입할 수 없다.
u := struct {
name string
age int
}{
name: "chris",
age: 10,
}
Go 언어는 new
keyword를 이용해 새로운 object를 할당하는 기능을 지원한다. new
는 포인터를 리턴한다.
type user struct {
name string
age int
}
u := new(user)
fmt.Printf("%p: %v\n", u, u)
// 0x1400011a018: &{ 0}
Go 언어에서 type method
란 특수한 receiver
인수를 받는 함수다. Type method는 일반 함수처럼 선언하되 함수 이름 앞에 특수한 매개변수가 더 나온다. 이 매개변수는 함수와 여기에 추가한 매개변수의 타입을 연결한다. 따라서 이러한 매개변수를 reciver of the method
라 부른다.
type user struct {
name string
age int
}
u := user{"chris", 10}
// 일반 함수
func PrintUserAge(u user) {
u.age++
fmt.Println(u.age)
}
// 메소드 (value receiver)
func (u user) PrintUserAge() {
u.age++
fmt.Println(u.age)
}
// 메소드 (pointer receiver)
func (u *user) PrintUserAge() {
u.age++
fmt.Println(u.age)
}
위와 같이 type method는 일반 함수와 구현부는 완벽히 같다.
하지만 type method는 method이기 때문에 호출 방식이 다음과 같이 다르다.
// 일반 함수 호출
PrintUserAge(u)
// 메소드 호출
u.PrintUserAge()
value receiver는 값을 복사하여 전달하기 때문에 method 내부에서 값을 변경해도 원본 값은 변화가 없는 반면,
pointer receiver는 주소를 전달하기 때문에 method 내부에서 값을 변경하면 원본 값이 변경된다.