Wallet
구조체를 만들고 Bitcoin
을 입금해 보자../wallet_test.go:7:12: undefined: Wallet
Wallet
이 무엇인지 모르기 때문에 알려줘야 한다.wallet_test.go:15: got 0 want 10
balance
필드에 구조체 안에 있는 "receiver" 변수를 통해서만 접근할 수 있다는 것을 기억 해야 한다.wallet_test.go:15: got 0 want 10
func (w Wallet) Deposit(amount int)
에 w
는 메서드를 호출하는 것의 복사본이다.&myVal
와 같은 방식으로 값의 메모리 주소 bit를 찾을 수 있다.\n
은 , 메모리 주소를 아웃풋으로 출력한 뒤 줄 바꿈을 해준다. &
라는 심볼의 주소로 어떤 것에 대한 포인터를 얻는다.Wallet
이 아니라 *Wallet
이라고 쓰고 이것은 "wallet에 대한 포인터"라고 얘기할 수 있다.(*w)
를 사용한 코드는 완벽하게 타당하다. 그러나, Go 언어의 개발자들은 이 표기가 쓰기 귀찮은 것이라고 생각했고 그래서 Go에서는 특별한 역참조에 대한 명시 없이 w.balance
라고 쓰는 것을 허용했다. 이 구조체에 대한 포인터는 다음과 같이: 구조체 포인터 라고 불리고 자동 역참조가 된다.Balance
라는 메서드는 포인터 리시버를 사용할 필요가 없고 balance의 복사본을 사용하여도 문제는 없다. 그러나 관습적으로 당신은 메서드 리시버 타입을 하나의 통일성 있게 가져가야 한다.int
를 사용하였는데 그것은 무언가를 세는 데 있어서 좋은 타입이기 때문이다.구조체
를 추가로 생성해 사용하는 것은 좀 과하다고 생각할 수 있다. int
만으로 동작하는 데는 문제가 없지만 그것을 잘 설명해주지 못하는 점이 있다.type MyName OriginalType
Bitcoin
을 만들기 위해서는 Bitcoin(999)
와 같이 사용하면 된다.fmt
패키지에 정의되어 있고 프린트에서 %s
포맷의 스트링을 사용하는 경우 당신의 타입이 어떻게 출력될지 정의한다.String()
을 사용하도록 포맷 스트링을 바꿔준다.wallet_test.go:18: got 10 BTC want 20 BTC
Withdraw
함수를 위한 것이다.Deposit()
에 대부분 반대로 적용한다../wallet_test.go:26:9: wallet.Withdraw undefined (type Wallet has no field or method Withdraw)
wallet_test.go:33: got 20 BTC want 10 BTC
Withdraw
를 계좌에 남아있는 잔액보다 많이 시도하게 된다면 어떻게 될까? 지금까지는, 우리의 요구사항은 초과 인출 시설에 대해서는 가정하지 않았다.Withdraw
를 사용하다 문제가 생긴 경우 우리는 어떻게 알려야 할까?err
를 보내주어 호출자가 확인하고 행동 할 수 있도록 해준다.Withdraw
에서는 에러를 리턴하도록 해야한다.nil
이 리턴 된다면 테스트가 실패하도록 하여 에러를 체크할 것이다.nil
은 다른 프로그래밍 언어에서의 null
과 동의어다. 에러는 nil
이 될 수 있는데, 그 이유는 Withdraw
의 리턴 타입이 error
이고 이것은 인터페이스이기 때문이다. 만약 인터페이스를 인자나 리턴 값으로 받는 함수를 보게 되면 이것은 nil
이 될 수 있다(nillable).null
처럼 만약 nil
값에 접근하려 하면 런타임 패닉을 던지게 됩니다. 이것은 매우 안 좋다! 반드시 nil인지 확인해야 한다../wallet_test.go:31:25: wallet.Withdraw(Bitcoin(100)) used as value
Withdraw
의 의도는 단지 호출하는 것이였고, 값을 리턴하지 않았다. 컴파일이 되게 하기 위해서는 이 메서드가 리턴 타입을 가지도록 해주어야 한다.Withdraw
메서드를 error
를 리턴하도록 수정하고 지금부터는 어떤 것 을 리턴해야하기 때문에 일단 nil
을 리턴하도록 해보자.errors
를 import 해주는 것을 기억해야 한다.errors.New
는 당신이 작성한 메시지와 함께 새로운 error
를 생성하여 준다.string
을 비교하도록 업데이트한다.t.Fatal
를 사용하였는데 이것은 불리게 된다면 테스트를 중지한다. 주위에 하나도 없는 것이 아니라면, 반환된 오류에 대해 더는 assertions이 일어나게 하고 싶지 않기 때문이다. 이것이 없다면 테스트는 다음 스텝으로 계속 진행되고 nil 포인터에 의해 패닉이 일어난다.wallet_test.go:61: got err 'oh no' want 'cannot withdraw, insufficient funds'
Withdraw
코드 모두 에러 메시지를 포함하고 있어 중복이 있다.var
키워드는 패키지에서 전역으로 변수를 선언 할 수 있도록 허용한다.Withdraw
함수는 매우 깔끔해졌기 때문에 이것은 그 자체로 매우 긍정적인 변화이다.ErrInsufficientFunds
와 동일한지 확인하고 적절히 행동하면 된다.errcheck
를 설치하자go get -u github.com/kisielk/errcheck
errcheck .
을 실행하자.wallet_test.go:17:18: wallet.Withdraw(Bitcoin(10))
Withdraw
가 성공적인지, 즉 에러가 반환되지 않았는지 확인하지 않았다는 것을 의미한다.