🔥 연습문제 - ROT13 Reader 구현하기
Go 언어에서는 io.Reader
를 감싸는 것이 일반적인 패턴이에요. 이렇게 하면 스트림을 어떤 식으로든 수정할 수 있죠.
예를 들어, gzip.NewReader
함수는 io.Reader
(압축된 데이터의 스트림)를 가져와서 io.Reader
(압축이 해제된 데이터의 스트림)도 구현하는 *gzip.Reader
를 반환하지요.
이제 io.Reader
를 구현하고 io.Reader
에서 읽는 rot13Reader
를 구현해 볼 거예요. 이 리더는 모든 알파벳 문자에 ROT13 치환 암호를 적용하여 스트림을 수정할 거랍니다.
rot13Reader
타입은 이미 제공되어 있어요. 이 타입의 Read
메서드를 구현하여 io.Reader
로 만들어 보죠.
package main import ( "io" "os" "strings" ) type rot13Reader struct { r io.Reader } func (r *rot13Reader) Read(p []byte) (n int, err error) { n, err = r.r.Read(p) for i := 0; i < n; i++ { if (p[i] >= 'A' && p[i] <= 'M') || (p[i] >= 'a' && p[i] <= 'm') { p[i] += 13 } else if (p[i] >= 'N' && p[i] <= 'Z') || (p[i] >= 'n' && p[i] <= 'z') { p[i] -= 13 } } return } func main() { s := strings.NewReader("Lbh penpxrq gur pbqr!") r := rot13Reader{s} io.Copy(os.Stdout, &r) }
go
이 코드를 하나하나 뜯어보면서 설명해 드릴게요.
type rot13Reader struct { r io.Reader }
go
먼저, rot13Reader
구조체를 정의하고 있어요. 이 구조체는 io.Reader
를 필드로 가지고 있죠. 이 필드는 ROT13 변환을 적용할 원본 리더를 나타내요.
func (r *rot13Reader) Read(p []byte) (n int, err error) { n, err = r.r.Read(p) for i := 0; i < n; i++ { if (p[i] >= 'A' && p[i] <= 'M') || (p[i] >= 'a' && p[i] <= 'm') { p[i] += 13 } else if (p[i] >= 'N' && p[i] <= 'Z') || (p[i] >= 'n' && p[i] <= 'z') { p[i] -= 13 } } return }
go
그 다음엔 rot13Reader
에 대한 Read
메서드를 구현하고 있습니다. 이 메서드는 io.Reader
인터페이스를 충족시키죠.
우선 원본 리더(r.r
)에서 데이터를 읽어와 p
슬라이스에 저장해요. 이때 읽은 바이트 수 n
과 에러 err
도 함께 반환됩니다.
그런 다음 for
루프를 사용하여 p
슬라이스의 각 바이트에 ROT13 변환을 적용하지요.
- 바이트가 'A'에서 'M' 사이의 대문자이거나 'a'에서 'm' 사이의 소문자인 경우, 해당 바이트에 13을 더해 주어요.
- 반대로 바이트가 'N'에서 'Z' 사이의 대문자이거나 'n'에서 'z' 사이의 소문자인 경우에는 13을 빼 주죠.
이렇게 하면 알파벳을 13자리씩 이동시키는 ROT13 치환이 이루어집니다.
마지막으로 읽은 바이트 수 n
과 에러 err
을 반환하여 Read
메서드를 완성하게 됩니다.
func main() { s := strings.NewReader("Lbh penpxrq gur pbqr!") r := rot13Reader{s} io.Copy(os.Stdout, &r) }
go
main
함수에서는 strings.NewReader
를 사용하여 ROT13으로 인코딩된 문자열 "Lbh penpxrq gur pbqr!"를 읽어들이는 io.Reader
를 생성해요.
그리고 이 리더를 rot13Reader
로 감싸서 r
이라는 새로운 io.Reader
를 만들죠.
마지막으로 io.Copy
를 사용하여 r
에서 읽은 데이터를 표준 출력(os.Stdout
)에 쓰게 됩니다. 이때 rot13Reader
의 Read
메서드가 호출되면서 ROT13 디코딩이 이루어지고, 원래 문자열이 출력되죠. 아래는 출력 결과입니다.
You cracked the code!
text