Adapter 패턴은 어댑터라는 말 그대로 서로 다른 구조체간의 연결을 하기 위한 패턴으로
interface를 활용하여 연결하게 됩니다.
golang의 http 관련 내부 패키지중에 HandlerFunc라는 타입이 있는데
HandlerFunc가 어댑터 패턴으로 구현되어 있습니다.
1
2
3
4
5
|
type HandlerFunc func(ResponseWriter, *Request)
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
|
cs |
go에 기본적으로 구현되어 있는 HandlerFunc의 코드입니다.
보다시피 HandlerFunc 타입은 ServeHTTP 메서드를 구현하고 있습니다.
1
2
3
|
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
|
cs |
역시 go에 기본적으로 구현되어있는 Handler 타입입니다.
Handler 타입을 구현하려면 ServeHTTP를 구현해야 합니다. 즉, HandlerFunc는 Handler 타입을 구현하게 도와주는 어댑터입니다.
HandlerFunc가 어떻게 쓰이는지 좀 더 정확히 알아보겠습니다.
1
2
3
|
func Home(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Here is my home"))
}
|
cs |
위에 함수를 http.Handle함수의 인자로 넣고 싶다고 가정해보겠습니다.
1
|
func Handle(pattern string, handler Handler)
|
cs |
그런데 공식문서에 Handle 함수의 정의는 위와 같습니다.
1
|
http.Handle("/home", Home)
|
cs |
즉, 우리는 위와 같은 코드를 작성하고 싶지만
Home 함수는 Handler 타입이 아니기 때문에 위 같은 코드를 작성할 수 없습니다.
이 때 위에서 살펴본 어댑터 함수인 HandlerFunc가 쓰이게 됩니다.
1
|
http.Handle("/home", HandlerFunc(Home))
|
cs |
이렇게 HandlerFunc로 감싸주면 에러없이 동작합니다.
다시 HandlerFunc 함수를 살펴보겠습니다.
1
2
3
4
5
6
|
type HandlerFunc func(ResponseWriter, *Request)
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
|
cs |
f(w, r) 코드는 결국 func(ResponseWriter, *Request)에 해당하는 함수를 그대로 실행하는 것뿐입니다.
이해를 돕기 위해 간단한 예제를 보여드리겠습니다.
1
2
3
4
5
6
7
8
9
10
11
|
type testFunc func(string) string
func Hello(name string) string {
return fmt.Sprintf("%s hello", name)
}
func main() {
t := testFunc(Hello)
fmt.Println(t("kim"))
}
|
cs |
이렇게 t("kim")은 결국 Hello("kim")과 같은 동작을 합니다.
그러나 HandlerFunc의 경우 ServeHTTP가 구현되어있으므로 HandlerFunc로 감싼 타입은
Handler 타입이 적용되기 때문에 어댑터의 역할을 하게 됩니다.
http.Handler는 middleware를 만들 때 많이 사용하게 됩니다.
예를 들어 json header를 붙여주는 middleware를 만들어보겠습니다.
1
2
3
4
5
6
|
func AddJsonHeaderMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Content-Type", "application/json")
next.ServeHTTP(w, r)
})
}
|
cs |
함수의 인자로 http.Handler를 받은 후 json header를 붙여주고
인자로 받은 함수를 실행시켜주는 middleware 입니다.
'golang > design pattern' 카테고리의 다른 글
golang design pattern #7 Composite (0) | 2021.11.12 |
---|---|
golang design pattern #6 Bridge (0) | 2021.11.12 |
golang design pattern #4 Singleton (0) | 2021.11.11 |
golang design pattern #3 Prototype (0) | 2021.11.11 |
golang design pattern #2 Factory (0) | 2021.11.10 |