go에서 메소드 만드는 방법이 조금 특이하다.
type Account struct {
owner string
balance int
}
func (a *Account) Deposit(amount int) {
a.balance += amount
}
Receiver가 추가된 함수라고 생각하면 되는데, 여기서 receiver는 (a Account) 부분을 말한다. 즉 어떤 struct에 속한 메소드인지 receiver로 정해줄 수 있다.
한 가지 주의할 점은 struct의 앞 한글자의 소문자로 시작하는 단어를 앞에 작성해줘야 한다는 것이다. 여기서는 Account의 소문자인 a로 시작하는 단어를 사용해야 한다.
추가적으로 주의해야 할 부분이 더 있는데, Deposit 메소드처럼 그 객체의 실제 값을 변경할 때는 receiver에 * 을 붙여줘야 한다. 만약 붙여주지 않고 메소드를 만들면 실제값이 아닌 복사된 값이 변경되기 때문에 메소드가 제대로 동작하지 않을 수 있다.
func (a *Account) Withdraw(amount int) error {
if a.balance < amount {
return errors.New("can't withdraw. you are poor")
}
a.balance -= amount
return nil
}
위 메소드에서 봐야 할 점은 크게 3가지다.
nil을 리턴으로 적어줘야 한다. nil은 error의 반대 즉, 정상적으로 동작하는 것을 의미한다.func main() {
account := accounts.NewAccount("nico")
account.Deposit(200)
fmt.Println(account.Balance())
err := account.Withdraw(300)
if err != nil {
log.Fatalln(err)
}
fmt.Println(account.Balance())
}
log.Fatalln()을 적어줌으로써 에러가 날 경우 콘솔창에 에러메세지를 띄우고 프로그램을 종료시킬 수 있도록 해야한다. log.Fatalln(err) 대신 fmt.Println(err) 를 써줘도 상관 없다. 어차피 에러가 나면 메소드는 실행되지 않기 때문.struct뿐만 아니라 Map 형식에도 메소드를 추가할 수 있다.
type Dictionary map[string]string
var errNotFound = errors.New("NotFound")
func (d Dictionary) Search(word string) (string, error) {
value, exists := d[word]
if exists {
return value, nil
}
return "", errNotFound
}