[GO]은행 계좌 만들기

포동동·2022년 7월 21일
0

GOLANG

목록 보기
1/4

Go 도전

부트캠프 수료중에 흥미가 떨어져 개발공부쪽으로 방향을 틀고 제일 먼저 공부한 건 JAVA였다. 백엔드를 공부해두면 그냥 백엔드 엔지니어로 취업하기도 좋고 DE로 시작하기 어려운 주니어들에게 도움이 된다고 해서

JAVA ➡ Spring ➡ 각종 데이터 관련 툴

이런식으로 공부를 해나가려고 하던 와중, 나의 부트캠프 중 가장 큰 은인인 니꼴라스의 강의 중 GO를 소개하는 영상을 보았고 너무 재밌어 보여서(자바보다 쉬워보여서) 바로 강의를 수강하였다.

두 번 보세요 니꼴라스 샘👍

이론적인 이야기나 코드적인 분석은 다른 블로그들에서도 쉽게 찾을 수도 있을뿐더러 아직 내가 공부가 다 끝나지 않았기 때문에 깊은 내용은 다룰 수 없고 간단한 실습을 진행한 것을 나를 위해 그리고 나와 같은 Go 입문자들을 위해 적어보려 한다.

(항상 블로그를 찾아보면 이론적인 이야기만 있지, 그래서 어떻게 코드를 짜야하는지는 꽤 구글링 해야 나오기 때문에 열받아서 적어본다)



은행 계좌 만들기

아주 간단한 예시로, 이름과 잔액을 입력하고, 여기에 입금, 출금하는 기능을 넣고,
잔액을 체크하는 코드를 짜보려 한다.

폴더는 아래와 같이 짜면 된다.

---learngo
     main.go
     ---accounts
          accounts.go              


STEP1. 새로운 예금자 추가

우선 간단하게 accounts.go 파일에 struct(python으로 치자면 빈 dictionary, db로 치자면 빈 table)를 만들어 주고 계좌의 주인과 기본 금액을 입력하는 함수를 만들어준다.

package accounts

// Account struct
type Account struct {
	owner   string
	balance int
}

// NewAccount build func
func NewAccount(owner string) *Account {
	account := Account{owner: owner, balance: 100}
	return &account
}

type으로 시작하는 코드는 계좌에 대한 정보를 담는 빈 table을 하나 만들어주었다고 생각하면 된다. 그리고 아래의 NewAccount에서는 잔액에는 접근할 수 없게 계좌 주인만 등록할 수 있게 owner만 argument로 받는다. 여기서는 balance를 default로 100으로 주었는데, 보통 0으로 하는 게 맞다.(코드상에서라도 풍족하라고)

주석을 넣어줘야 하는 것을 잊지말자. 또한 주석은 함수명으로 시작하도록 지어준다(약속이라고 한다).


그리고 main.go에 가서 accounts.go package를 불러와 함수를 호출해본다.


package main

import (
	"fmt"
    "github.com/chaiwon/learngo/accounts"
)

func main() {
	account := accounts.NewAccount("podo")
	fmt.Println(account)
}

결과를 보면 podo라는 owner의 계좌에 100이라는 잔액이 남아있다는 것을 알 수 있다 ✅



STEP2. 입금과 출금 기능 추가

다시 accounts.go로 돌아가서 입금과 출금 method를 추가해준다.

🛑주의할 점🛑

method는 함수(function)과 거의 비슷하지만 내가 생각했을 때 다른 점은, method는 대상을 불러와(이 경우엔 Account라는 struct) 바로 어떠한 일을 시키는 것(이 경우엔 입금과 출금)이고, function은 대상을 복사해와 일을 시키는 것(이 경우엔 새로운 계좌를 만들어주는 것)이라고 이해했다. (method는 main.go에서 사용하는 function이라, function의 일부라도 봐도 되지 않을까...)

비슷한 개념이지만 복사를 해왔냐, 바로 갖다 쓰냐 그 차이라고 이해했고, 생김새도 비슷하다. method에는 reciever라는 것만 추가해주면 된다.

package accounts

// Account struct
type Account struct {
	owner   string
	balance int
}

// Deposit method
func (a *Account) Deposit(amount int) {
	a.balance += amount
}

// Withdraw method
func (a *Account) Withdraw(amount int) {
	a.balance -= amount
}

// Balance checking method
func (a Account) Balance() int {
	return a.balance
}

🛑주의할 점🛑

  1. reciever에는 위에서 설정한 struct가 들어간다. 즉, 이 method가 어디에서 실행될지 지정해줘야 한다. (function은 내가 갖다 쓰고싶은 곳에 집어넣으면 되고 method는 여기다 쓰고 싶다고 콕 찝어 불러와야 한다.)

  2. reciever에는 alias(별칭)를 쓸 수 있는데, 보통 그 대상의 앞글자 소문자를 따와서 사용한다.

  3. 지금 보면, Deposit, Withdraw method에 reciever로 *Account가 들어간 게 보일텐데, 만약 그냥 Account를 사용하면 복사된 대상이 불려오기 때문에 원본엔 변화가 반영되지 않기 때문에 "나 원본에 입금, 출금 내역 반영시킬거임"이라는 의미로 대상 앞에 *를 붙여준다.


그리고 그냥 잔액만 보는 method을 추가해 main.go에서 깔끔하게 표현하였다. (Balance라는 method에 *가 붙지 않은 이유는 어차피 Deposit이나 Withdraw라는 method때문에 원본에 반영이 됐을거기 때문에 고대로 원본만 가져와 return하면 되기 때문이다.)


package main

import (
	"fmt"
	"github.com/chaiwon/learngo/accounts"
)

func main() {
	account := accounts.NewAccount("podo")
	fmt.Println(account.Balance())
	account.Deposit(30)
	fmt.Println(account.Balance())
	account.Withdraw(80)
	fmt.Println(account.Balance())
}

결과를 보면 기본 100이었던 잔액에 30만큼 입금을 하고 80만큼 출금한 후 잔액을 볼 수 있다 ✅
(쥐똥만큼 입금하고 소똥만큼 출금되는게 내 통장 같구먼😥)



STEP3. 잔액부족이면 출금불가 기능 추가

실생활에서는 마이너스 통장이라는 것이 존재하지만, 우리가 짜 볼 코드엔 그런 거 없다. 만약 잔액보다 출금하고자 하는 금액이 크면 가차없이 "Nope"을 외쳐주는 코드를 짜보도록 하자.

우선 accounts.go 파일에 가서 Withdraw method를 아래와 같이 바꿔준다.


package accounts

import "errors"

// Account struct
type Account struct {
	owner   string
	balance int
}

// Withdraw method
func (a *Account) Withdraw(amount int) error {
	if a.balance < amount {
		return errors.New("Nope. You are poor.")
	}
	a.balance -= amount
	return nil
}

일단 if문을 써준다. 다만 Go에선 python이나 JS처럼 친절히 error를 일반적인 string으로 반환해주지 않기 때문에 내가 직접 error라고 명시하고 그 안에 에러메세지를 써야한다.

그래서 잔액이 출금하려는 금액보다 적으면 "Nope. You are poor."라는 에러메세지를 반환시키고,
만약 출금하려는 금액이 금액이 잔액보다 적으면 nil(None, Null과 같음)을 return한다. (else는 안 써도 되며, else 뒤에 정상 작동하게 하고 싶으면 가만히 냅두는 게 아니라 nil이라고 써줘야 한다고 한다)


그런 다음, main.go에서 잔액보다 많은 금액을 출금하려고 하는 코드를 짜보면,

package main

import (
	"fmt"
	"github.com/chaiwon/learngo/accounts"
)

func main() {
	account := accounts.NewAccount("podo")
	fmt.Println(account.Balance())
	account.Deposit(30)
	fmt.Println(account.Balance())
	err := account.Withdraw(150)
	fmt.Println(account.Balance())
}

아무런 변화가 없다...ㅎ
왜냐하면, python에서는 if가 만족되면 자동으로 에러메세지가 뜨는 반면, Go에서는 그 error를 내가 확인하고 반환해달라고 요구해야한다(try, exception 못 잃어). 따라서 아래와 같이 코드를 작성해야 한다.


package main

import (
	"fmt"
	"github.com/chaiwon/learngo/accounts"
)

func main() {
	account := accounts.NewAccount("podo")
	fmt.Println(account.Balance())
	account.Deposit(30)
	fmt.Println(account.Balance())
	err := account.Withdraw(150)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(account.Balance())
}

위와 같이 작성하면,

Withdraw라는 method를 실행하고 ➡ err가 있는지 없는지 확인하고 ➡ not nil(즉, 있다면) err를 print해라
라는 순서로 작동한다.

그 뒤, 다시 한 번 잔액을 보여주도록 짜보았다.

위에서부터 기본 잔액 100, 30 입금 후 130, 분수 넘치게도 150을 출금하려 했으나 Nope. You are poor. 당하고, 다시 잔액확인 해보니 130이 나오는 것을 확인할 수 있다 ✅



STEP4. 예금주 업데이트

처음 등록한 예금주를 바꿔주는 method도 추가해보겠다.

당연하게도 accounts.go에 들어가서 아래와 같은 코드를 작성해준다.


package accounts

// Account struct
type Account struct {
	owner   string
	balance int
}

// ChangeOwner method
func (a *Account) ChangeOwner(newOwner string) {
	a.owner = newOwner
}

// Owner checking method
func (a Account) Owner() string {
	return a.owner
}

ChangeOwner method를 통해 원래 있던 owner를 newOwner로 바꿔준다. 그리고 추가로 owner만 보여주는 Owner method도 추가해준다(위의 Balance라는 method와 같은 역할이다)


그런 다음, main.go에 가서 확인해보자.

package main

import (
	"fmt"
	"github.com/chaiwon/learngo/accounts"
)

func main() {
	account := accounts.NewAccount("podo")
	fmt.Println(account.Owner())
	account.ChangeOwner("namu")
	fmt.Println(account.Owner())
}

그 결과, podo였던 예금주 이름이 namu로 바뀐 것을 확인할 수 있다 ✅



마무리🙆‍♂️

기본적인 function, method, error들을 다루는 법에 대해 익힐 수 있는 실습이었길 바라며 Go를 이용한 실습은 앞으로도 몇 개 더 올려보도록 하겠다.


이번 실습의 전체코드는 아래와 같다.


// accounts.go

package accounts

import "errors"

// Account struct
type Account struct {
	owner   string
	balance int
}

// NewAccount build func
func NewAccount(owner string) *Account {
	account := Account{owner: owner, balance: 100}
	return &account
}

// Deposit method
func (a *Account) Deposit(amount int) {
	a.balance += amount
}

// Withdraw method
func (a *Account) Withdraw(amount int) error {
	if a.balance < amount {
		return errors.New("Nope. You are poor.")
	}
	a.balance -= amount
	return nil
}

// Balance checking method
func (a Account) Balance() int {
	return a.balance
}

// ChangeOwner method
func (a *Account) ChangeOwner(newOwner string) {
	a.owner = newOwner
}

// Owner checking method
func (a Account) Owner() string {
	return a.owner
}
profile
완료주의

2개의 댓글

comment-user-thumbnail
2022년 7월 31일

오, 재밌는 공부 시작하셨네요! 응원합니다 💪💪

1개의 답글