구조체의 메서드
값 리시버와 포인터 리시버 비교
구조체의 메서드은(는) CoddyKit의 무료 Go Academy 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Go Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Go Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
메서드란 무엇입니까?
메서드는 리시버 인자를 가진 함수입니다. 리시버는 func 키워드와 메서드 이름 사이에 위치하며, 함수를 특정 타입에 연결합니다.
값 리시버
값 리시버는 구조체의 복사본을 받습니다. 상태를 변경할 필요가 없는 메서드에 사용합니다:
package main
import "fmt"
type Circle struct{ Radius float64 }
func (c Circle) Area() float64 {
return 3.14159 * c.Radius * c.Radius
}
func main() {
c := Circle{Radius: 5}
fmt.Printf("%.2f\n", c.Area()) // 78.54
}포인터 리시버
포인터 리시버를 사용하면 메서드가 구조체를 변경할 수 있습니다. 큰 구조체에서 더 효율적입니다:
package main
import "fmt"
type Counter struct{ N int }
func (c *Counter) Increment() { c.N++ }
func (c *Counter) Reset() { c.N = 0 }
func main() {
c := Counter{}
c.Increment(); c.Increment()
fmt.Println(c.N) // 2
c.Reset()
fmt.Println(c.N) // 0
}포인터 리시버를 사용하는 경우
다음과 같은 경우 포인터 리시버를 사용합니다:
- 메서드가 리시버를 수정해야 하는 경우
- 구조체가 큰 경우(복사를 피할 수 있습니다)
- 일관성을 유지해야 하는 경우: 하나의 메서드라도 포인터 리시버를 사용한다면 모두 포인터 리시버를 사용합니다
구조체가 작고 메서드가 데이터만 읽는 경우에는 값 리시버를 사용합니다.
메서드 표현식과 메서드 값
메서드는 일급 값으로 사용할 수 있습니다:
package main
import "fmt"
type Adder struct{ Base int }
func (a Adder) Add(n int) int { return a.Base + n }
func main() {
a := Adder{Base: 10}
fn := a.Add // method value — bound to a
fmt.Println(fn(5)) // 15
}구조체가 아닌 타입의 메서드
구조체뿐 아니라 같은 패키지에 있는 모든 이름 있는 타입에 메서드를 정의할 수 있습니다:
package main
import "fmt"
type Celsius float64
func (c Celsius) ToFahrenheit() float64 {
return float64(c)*9/5 + 32
}
func main() {
t := Celsius(100)
fmt.Println(t.ToFahrenheit()) // 212
}포인터 역참조 자동 처리
메서드를 호출할 때 Go가 자동으로 주소를 가져오거나 역참조합니다. (&c).Method()를 직접 작성할 필요가 없습니다:
package main
import "fmt"
type Box struct{ Val int }
func (b *Box) Double() { b.Val *= 2 }
func main() {
b := Box{Val: 5}
b.Double() // Go auto-takes address
fmt.Println(b.Val) // 10
}메서드 연결
메서드 연결(빌더 패턴)을 사용하려면 리시버 포인터를 반환합니다:
package main
import "fmt"
type Builder struct{ result string }
func (b *Builder) Add(s string) *Builder {
b.result += s
return b
}
func (b *Builder) Build() string { return b.result }
func main() {
s := (&Builder{}).Add("Hello").Add(", ").Add("World").Build()
fmt.Println(s)
}문자열 메서드(fmt.Stringer)
String() string 메서드를 구현하여 타입이 출력되는 방식을 제어합니다:
package main
import "fmt"
type Point struct{ X, Y int }
func (p Point) String() string {
return fmt.Sprintf("(%d, %d)", p.X, p.Y)
}
func main() {
p := Point{3, 4}
fmt.Println(p) // (3, 4)
}nil 포인터 리시버
포인터 리시버를 사용하는 메서드는 nil 포인터에서도 호출할 수 있어 기본 동작을 제공할 때 유용합니다:
package main
import "fmt"
type Node struct{ Val int }
func (n *Node) Value() int {
if n == nil { return 0 }
return n.Val
}
func main() {
var n *Node
fmt.Println(n.Value()) // 0
}일관성 원칙
Go 표준 라이브러리와 관용적인 Go 코드에서는 한 타입의 모든 메서드가 같은 종류의 리시버를 사용합니다. 모두 포인터 리시버이거나 모두 값 리시버여야 합니다. 혼용하면 인터페이스에서 미묘한 버그가 발생합니다.
빠른 확인
어떤 리시버 타입을 사용해야 메서드가 구조체의 필드를 수정할 수 있습니까?
복습: 메서드
핵심 내용:
- 메서드에는
func와 이름 사이에 리시버가 있습니다 - 값 리시버: 읽기 전용 작업과 작은 구조체에 사용합니다
- 포인터 리시버: 변경, 큰 구조체, 일관성 유지에 사용합니다
- Go는 자동으로 역참조하므로
(&v).Method()를 작성할 필요가 없습니다 - 사용자 지정 출력을 위해
String() string을 구현합니다
연습 과제
Balance float64 필드를 가진 BankAccount 구조체를 정의하십시오. Deposit 및 Withdraw 포인터 리시버 메서드와 String() 값 리시버 메서드를 추가하십시오.
자주 묻는 질문
“구조체의 메서드” 강의는 무료인가요?
네 — “구조체의 메서드” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Go Academy 강의 전체를 잠금 해제할 수 있습니다. Go Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“구조체의 메서드”에서 뭘 배우나요?
값 리시버와 포인터 리시버 비교 브라우저에서 직접 실행하는 실습 코드로 Go Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Go Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Go Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.
“구조체의 메서드” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Go Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Go Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 구조체 정의와 사용
- 구조체의 메서드
- 생성자 패턴
- 익명 구조체와 조합