프로그래밍/Go
[Go] 구조체 (Struct)
프로그래민구찌
2024. 11. 22. 20:28
Go 언어의 구조체 (Struct)
- 구조체는 Go언어에서 데이터를 묶어서 표현하기 위해 사용하는 사용자 정의 타입
- 여러 필드를 하나로 묶어 관련된 데이터를 관리
- 객체지향 언어의 클래스와 비슷하지만 메서드와 상속 기능은 없으며, 필드만을 정의
특징
1. 데이터 묶음
- 서로 다른 데이터 타입의 필드를 하나로 묶어서 사용할 수 있음.
2. 타입 정의
- 구조체는 새 데이터 타입을 정의하는 데 사용됨.
3. 메모리
- 값 타입으로 동작하지만, 포인터로 참조하여 동작할 수도 있음.
4. 내장 필드 및 사용자 정의 필드 사용 가능
- 필드에 기본값 없음(명시적으로 초기화 해야함.)
구조체 정의와 사용법
1. 기본 구조체 정의
package main
import "fmt"
// 구조체 정의
type Person struct {
Name string
Age int
City string
}
func main() {
// 구조체 인스턴스 생성 및 초기화
p1 := Person{Name: "Alice", Age: 30, City: "Seoul"}
p2 := Person{"Bob", 25, "Busan"} // 필드 순서대로 초기화
// 값 출력
fmt.Println("Person 1:", p1)
fmt.Println("Person 2:", p2)
}
출력결과
Person 1: {Alice 30 Seoul}
Person 2: {Bob 25 Busan}
2. 구조체의 필드 접근 및 수정
package main
import "fmt"
type Person struct {
Name string
Age int
City string
}
func main() {
// 구조체 초기화
p := Person{Name: "Charlie", Age: 28, City: "Incheon"}
// 필드 접근
fmt.Println("Name:", p.Name)
fmt.Println("Age:", p.Age)
fmt.Println("City:", p.City)
// 필드 값 수정
p.Age = 29
fmt.Println("Updated Age:", p.Age)
}
출력결과
Name: Charlie
Age: 28
City: Incheon
Updated Age: 29
3. 포인터를 사용한 구조체 수정
package main
import "fmt"
type Account struct {
Number string
Balance float64
}
func UpdateBalance(a *Account, amount float64) {
a.Balance += amount // 포인터를 통해 원본 수정
}
func main() {
acc := Account{Number: "123-456", Balance: 1000.0}
// 함수 호출 전
fmt.Println("Before:", acc.Balance)
// 함수 호출
UpdateBalance(&acc, 500)
// 함수 호출 후
fmt.Println("After:", acc.Balance)
}
출력결과
Before: 1000
After: 1500
4. 메서드를 사용하는 구조체
- 구조체와 함께 메서드를 정의하면 객체지향적인 코드 작성이 가능
package main
import "fmt"
type Rectangle struct {
Width, Height float64
}
// 구조체 메서드 정의
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
func (r Rectangle) Perimeter() float64 {
return 2 * (r.Width + r.Height)
}
func main() {
rect := Rectangle{Width: 10, Height: 5}
// 메서드 호출
fmt.Println("Area:", rect.Area())
fmt.Println("Perimeter:", rect.Perimeter())
}
출력결과
Area: 50
Perimeter: 30
5. 구조체 임베디드 패턴
- 다른 관점으로 메소드를 재사용하는 장점 제공
- 상속을 허용하지 않는 Go언어에서 메소드 상속 활용을 위한 패턴
package main
import "fmt"
type Employee struct {
name string
salary float64
bonus float64
}
func (e Employee) Calculate() float64 {
return e.salary + e.bonus
}
type Executives struct {
Employee // is a 관계
specialBonus float64
}
func main() {
// 구조체 임베디드 패턴
// 다른 관점으로 메소드를 재사용하는 장점 제공
// 상속을 허용하지 않는 Go 언어에서 메소드 상속 활용을 위한 패턴
// 직원
ep1 := Employee{"kim", 2000000, 150000}
ep2 := Employee{"park", 1500000, 200000}
// 임원
ex := Executives {
Employee{"lee", 5000000, 1000000},
1000000, // specialBonus
}
fmt.Println("ex1 : ", int(ep1.Calculate()))
fmt.Println("ex1 : ", int(ep2.Calculate()))
// Employee 구조체 통해서 메소드 호출
fmt.Println("ex2 : ", int(ex.Calculate() + ex.specialBonus))
}
출력결과
ex1 : 2150000
ex1 : 1700000
ex2 : 7000000
6. 구조체 임베디드 메소드 오버라이딩 패턴
// 구조체 심화(5)
package main
import "fmt"
type Employee struct {
name string
salary float64
bonus float64
}
func (e Employee) Calculate() float64 {
return e.salary + e.bonus
}
func (e Executives) Calculate() float64 {
return e.salary + e.bonus + e.specialBonus
}
type Executives struct {
Employee // is a 관계
specialBonus float64
}
func main() {
// 직원
ep1 := Employee{"kim", 2000000, 150000}
ep2 := Employee{"park", 1500000, 200000}
// 임원
ex := Executives {
Employee{"lee", 5000000, 1000000},
1000000, // specialBonus
}
fmt.Println("ex1 : ", int(ep1.Calculate()))
fmt.Println("ex1 : ", int(ep2.Calculate()))
// Employee 구조체 통해서 메소드 호출
fmt.Println("ex2 : ", int(ex.Calculate()))
}
출력결과
ex1 : 2150000
ex1 : 1700000
ex2 : 7000000
요약
- 구조체는 데이터의 묶음으로 관련 데이터를 하나로 관리.
- 초기화 시 필드를 명시적으로 작성하거나, 필드 순서대로 값을 설정 가능.
- 포인터를 통해 원본 데이터 수정 가능.
- 메서드를 사용하여 구조체와 관련된 동작을 정의 가능.