![[Learn Go with Tests] 의존성 주입](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYlGyc%2FbtsIKTDtq2o%2FckIKP2OTvkeuGFgYel9VKK%2Fimg.png)
해당 문서를 통해 우리는 아래의 항목이 가능한가에 대해 배울것이다
- 프레임 워크가 필요하지 않다.
- 디자인을 지나치게 복잡하게 하지 않는다
- 테스트를 용이하게 한다
- 범용적인 함수를 뛰어나게 작성할 것이다.
func Greet(name string) {
fmt.Printf("Hello, %s", name)
}
간단한 printf 함수가 있다. fmt.Printf를 호출하면 stdout으로 출력된다. 우리는 이제부터 print 하는 것을 의존성 주입(인자를 넘기는 것을 고급지게 표현했다- tdd 문서 표현)을 해보도록 한다
우리의 함수는 어디에서 또는 어떻게 print가 발생하는 지를 신경 쓸 필요가 없다. 그래서 우리는 구체적인 type보다는 interface type을 허용해야 한다.
⇒ 즉, 우리는 제어하는 어떤 것으로 출력하도록 구현을 변경해 테스트 할 수 있다.
fmt.Printf의 소스 코드를 보면서 연결하는 방법을 알아보자
// 쓰여진 바이트 수와 발생한 error를 반환합니다.
func Printf(format string, a ...interface{}) (n int, err error) {
return Fprintf(os.Stdout, format, a...)
}
내부적으로 Printf는 os.Stdout을 전달하는 Fprintf를 호출하고 있다. 그렇다면 여기서 os.Stdout은 뭐길래 부르고 있을까?
func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
p := newPrinter()
p.doPrintf(format, a)
n, err = w.Write(p.buf)
p.free()
return
}
io.Writer를 호출하고 있다.
type Writer interface {
Write(p []byte) (n int, err error)
}
우리는 앞으로도 interface를 많이 보게 될 것이다. data를 어딘가에 넣는 것을 표현하기에 아주 적합한 general purpose interface기 때문이다.
즉! 우리는 어딘가에 print 인삿말을 보내기 위해 Writer를 사용하고 있다. 기존의 추상화를 사용하여 코드를 테스트 할 수 있고 더 재사용이 가능하도록 만들어보자.
의존성 주입을 위한 출력 테스트
테스트하기
func TestGreet(t *testing.T) {
buffer := bytes.Buffer{}
Great(&buffer, "Chris")
got := buffer.String()
want := "Hello, Chris"
if got != want {
t.Errorf("got %q want %q", got, want)
}
}
- bytes 패키지의 Buffer type은 Writer 인터페이스를 구현한다
- 우리는 Buffer를 Writer로서 사용할 것이다
- 이후 Great를 호출한 뒤 무엇이 buffer에 쓰여졌는지 비교하고자 한다.
서비스 코드 작성하기
func Great(writer *bytes.Buffer, name string) {
fmt.Fprintf(writer, "Hello, %s", name)
}
위와 같이 버퍼에 Hello %s를 작성하면 테스트는 통과가 가능하다.
리팩터링 하기
이전에 컴파일러는 bytes.Buffer에 대한 포인터를 전달하고는 있지만, 유용하지는 않다. 그렇다면 Great 함수를 표준 출력으로 인쇄하는 Go 애플리케이션에 연결해보자.
func main() {
Greet(os.Stdout, "Elodie")
}
func Greet(writer io.Writer, name string) {
fmt.Fprintf(writer, "Hello, %s", name)
}
io.Writer는 무엇인가?
우리는 위의 코드를 io.Writer를 사용하면서 general purpose 해진 함수가 되었다.
Example Code
package main
import (
"fmt"
"io"
"net/http"
)
func Greet(writer io.Writer, name string) {
fmt.Fprintf(writer, "Hello, %s", name)
}
func MyGreeterHandler(w http.ResponseWriter, r *http.Request) {
Greet(w, "world")
}
func main() {
http.ListenAndServe(":5000", http.HandlerFunc(MyGreeterHandler))
}
위의 코드를 보면 http.ResponseWriter에서도 Greet 함수를 호출하는데, writer를 사용하여 응답을 쓰는 것이 가능하다.
'Language > Go' 카테고리의 다른 글
[Learn Go with Tests] 맵 (0) | 2024.07.24 |
---|---|
[Learn Go with Tests] 포인터 & 에러 (1) | 2024.07.24 |
[Learn Go with Tests] 구조체, 메서드 & 인터페이스 (0) | 2024.07.18 |
[Learn Go with Tests] 슬라이스 및 배열 (0) | 2024.07.18 |
[Learn Go with Tests] Iteration (0) | 2024.07.18 |
보안 전공 개발자지만 대학로에서 살고 싶어요
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!