공개 필드와 비공개 필드
Coddy GO 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 107개 중 47번째.
Go에서 구조체 수준의 캡슐화는 field 이름의 대소문자로 제어됩니다. 이 간단한 규칙에 따라 구조체가 정의된 패키지 외부에서 field에 접근할 수 있는지가 결정됩니다.
uppercase letter로 시작하는 fields는 exported됩니다: 모든 패키지에서 accessible합니다. lowercase letter로 시작하는 fields는 unexported됩니다: 동일한 패키지 내에서만 accessible합니다:
// "user" 패키지에서
type User struct {
Name string // Exported - 어디서나 접근 가능
Email string // Exported - 어디서나 접근 가능
password string // Unexported - "user" 패키지 내에서만 접근 가능
age int // Unexported - "user" 패키지 내에서만 접근 가능
}
다른 패키지가 이 구조체를 import하여 사용할 때, exported fields와만 상호 작용할 수 있습니다:
// 패키지 "main"에서
import "user"
func main() {
u := user.User{
Name: "Alice", // 작동함
Email: "a@mail.com", // 작동함
// password: "secret", // 컴파일 오류: 알 수 없는 필드
}
fmt.Println(u.Name) // 작동함
// fmt.Println(u.password) // 컴파일 오류: 내보내지 않은 필드를 참조할 수 없음
}
이 메커니즘은 민감한 데이터와 내부 구현 세부 정보를 보호합니다. password field는 패키지 외부에서 직접 읽거나 수정할 수 없으므로, 다른 코드는 사용자가 제공하는 methods를 사용해야 합니다. 이것이 데이터 은닉을 달성하기 위한 Go의 방식이며, 객체 지향 프로그래밍에서 캡슐화의 핵심 원칙입니다.
챌린지
쉬움내보낸 필드와 내보내지 않은 필드를 통해 캡슐화를 보여 주는 bank account 시스템을 만들어 봅시다. 민감한 금융 데이터를 보호하면서 안전한 public 정보를 노출하는 package를 만들게 됩니다.
코드를 두 개의 파일로 구성합니다:
account.go:mainpackage에 실제 bank account를 모델링하고 적절한 data protection을 적용하는BankAccountstruct를 만듭니다:HolderName(내보냄) - account holder의 이름으로, public하게 표시해도 안전합니다AccountType(내보냄) - account의 유형입니다 (예: "Savings", "Checking")balance(내보내지 않음) - 보호해야 하는 실제 잔액입니다pin(내보내지 않음) - account PIN으로, 매우 민감한 데이터입니다
BankAccount에 대한 포인터를 반환하는 constructor functionNewBankAccount를 추가합니다. 또한 다음 형식을 반환하는GetPublicInfo() stringmethod를 추가합니다:Account: [HolderName] ([AccountType])main.go: 입력에서 account 세부 정보를 읽고, constructor를 사용하여BankAccount를 생성한 다음 캡슐화를 보여 줍니다. method를 사용하여 public 정보를 출력한 후, 각 내보낸 field에 직접 접근하여 별도의 줄에 출력합니다. 내보내지 않은 field(balance및pin)는 보호됩니다. 이 field는 constructor를 통해서만 설정할 수 있습니다.
다음 입력이 제공됩니다:
- 1번째 줄: Account holder 이름
- 2번째 줄: Account 유형
- 3번째 줄: Initial balance (float 형식)
- 4번째 줄: PIN 코드
예를 들어 Alice Johnson, Savings, 5000.50, 1234가 주어지면 출력은 다음과 같아야 합니다:
Account: Alice Johnson (Savings)
Holder: Alice Johnson
Type: Savingsbalance와 PIN은 출력에 절대 나타나지 않는다는 점에 주목하세요. 이 값들은 struct 내부에 안전하게 숨겨져 있으며 package 내부에서만 accessed할 수 있습니다. 이것이 바로 캡슐화의 실제 적용입니다. 민감한 데이터는 보호되는 동시에 public 정보는 accessible한 상태로 유지됩니다.
직접 해보기
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// 계좌 소유자 이름 읽기
holderName, _ := reader.ReadString('\n')
holderName = strings.TrimSpace(holderName)
// 계좌 유형 읽기
accountType, _ := reader.ReadString('\n')
accountType = strings.TrimSpace(accountType)
// 초기 잔액 읽기
balanceStr, _ := reader.ReadString('\n')
balanceStr = strings.TrimSpace(balanceStr)
balance, _ := strconv.ParseFloat(balanceStr, 64)
// PIN 읽기
pinStr, _ := reader.ReadString('\n')
pin := strings.TrimSpace(pinStr)
// TODO: 생성자를 사용하여 새 BankAccount 생성
// account := NewBankAccount(...)
// TODO: GetPublicInfo() 메서드를 사용하여 공개 정보 출력
// TODO: 내보낸 필드에 직접 접근하여 소유자 이름 출력
// fmt.Println("Holder:", ...)
// TODO: 내보낸 필드에 직접 접근하여 계좌 유형 출력
// fmt.Println("Type:", ...)
// Note: balance와 pin은 내보내지 않음 - 여기서 직접 접근할 수 없음
// 그것들은 struct 내에서 안전하게 캡슐화되어 있습니다
_ = balance // balance를 사용할 때 이 줄을 제거하세요
_ = pin // pin을 사용할 때 이 줄을 제거하세요
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
8에러 처리와 OOP
error 인터페이스사용자 정의 에러 타입에러 래핑 (fmt.Errorf)센티넬 에러errors.Is()와 errors.As()Panic, Defer, Recover요약 - 파일 파서직접 연습해 보세요: 온라인 Go 컴파일러