#4.3 Singleton Pattern
func (b *blockchain) addBlock(data string) {
newBlock := block{data, "", b.getLastHash()}
hash := sha256.Sum256([]byte(newBlock.data + newBlock.prevHash))
newBlock.hash = fmt.Sprintf("%x", hash)
b.blocks = append(b.blocks, newBlock)
}
- 이 Function은 3가지 일을 한다.
- Block을 생성하고, Block을 Hash하고, 새로운 Block을 Append한다.
- 분해해서 하나의 일만 하게 만들어보자.
- 패키지를 작성해보자.
- blockchain 폴더를 생성하고, blockchain.go를 생성한다.
- 이 파일에 일어나고 있는 것들을 옮겨준다.
- main.go에 blockchain에 관한 함수들을 제외해야한다. 왜냐하면 main.go에서 많은 일이 일어나기 때문이다.
- main.go는 많고 다양한 것들의 출입구가 될 것이다.
package blockchain
type block struct {
data string
hash string
prevHash string
}
type blockchain struct {
blocks []block
}
- 여기에 blockchain을 공유하고 초기화하는 부분을 구현할 것이다.
- 우리가 여기서 사용할 것은 Singleton 패턴이라고 불리는 녀석이다.
- Singleton 패턴이란 우리의 application 내에서 언제든지 blockchain의 단 하나의 instance만을 공유하는 방법을 말한다.
package blockchain
type block struct {
data string
hash string
prevHash string
}
type blockchain struct {
blocks []block
}
var b *blockchain
- Singleton 패턴을 구현하기 위해서는 변수를 먼저 하나 선언하고 초기화 하지 않는다.
- blockchain으로의 pointer type을 가지고 있는다.
- 이 변수를 아무하고도 공유하지 않을 것이다.
- 이 blockchain 패키지 내부에서만 이 변수에 접근할 수 있다.
- 왜냐하면 대문자가 아니기 때문이다.
- Singleton의 의미는 이 변수의 instance를 직접 공유하지 않고, 그 대신 이 변수의 instance를 우릴 대신해서 드러내주는 function을 생성한다.
- 우리가 function을 생성하는 만큼 다른 패키지에서 우리의 blockchain이 어떻게 드러날 지를 제어할 수 있다는 의미이기도 하다.
func GetBlockchain() *blockchain {
if b == nil {
b = &blockchain{}
}
return b
}
- GetBlockchain이라는 function을 예를 들어 생성해보자
- 이 function은 위 b 변수와 동일한 타입인 blockchain의 pointer를 반환할 것이다.
- 첫 번째로 해야 할 것은 이 b라는 변수가 초기화가 됐는지를 확인해야 한다.
- b 변수가 nil 값인지 확인해보는 것이다.
- 여기서 b를 처음이자 마지막으로 초기화해 줄 것이다.
- 여기서 b를 초기화해주고, 기존 변수를 update 해 줄 것이다.
- := 대신에 =로 값을 대입한다.
- blockchain의 instance를 생성해주고, 마지막으로 b를 반환해 줄 것이다.
- blockchain이 어떻게 초기화되고 공유될 지를 제어할 수 있다.
- 만약에 누군가 이 blockchain을 처음으로 요청한다면, nil을 반환할 일이 전혀 없다.
- 항상 blockchain을 먼저 초기화 한 뒤에 반환시켜줄 것이다.
- 그리고 향후에 이 패턴이 얼마나 유용한지 알게 될 것이다.
- 왜냐하면 여기서 blockchain이 어떻게 생성될 지 제어할 수 있기 때문이다.
- 만약 database를 연동한다면, 이 초기화 단계에서 blockchain을 database에서 가져올 수 있다는 의미이다.
- 하지만 이건 단 한번만 실행 될 것이다.
- 이 코드가 실행되는 순간, b는 더이상 nil이 아니기 때문이다.
- 누군가 이 blockchain을 다시 접근하려고 이 GetBlockchain을 실행한다면 이 프로세스는 더 이상 실행되지 않고, 현재의 blockchain instance를 바로 반환할 것이다.
- 이 코드의 시점에서 이 blockchain이 이미 초기화 되었기 때문이다.
- 이것이 singleton 패턴이다.
func main() {
chain := blockchain.GetBlockchain()
}
- main.go에서는 이렇게 실행될 것이다.
- 하지만 이제 우린 blockchain이 어떻게 초기화 될 지 제어할 수 있게 됐다.
- refactoring의 도입부이다.
정리 : 노마드코더 노마드코인 강의
댓글 영역