분류실

분류실

학습 연습 문제

소개

타입 변환

Go에서는 서로 다른 타입 사이의 변환을 명시적으로 해 줘야 해요. 타입 사이를 변환하는 것(타입 캐스팅이라고도 해요)은 변환하려는 타입의 이름을 가진 함수를 통해 해요. 예를 들어 int를 float64로 변환하려면 다음과 같이 하면 돼요:

var x int = 42 // x has type int
f := float64(x) // f has type float64 (ie. 42.0)

기본 타입과 문자열 사이의 변환

기본 타입(int 같은)과 string 사이를 변환하기 위한 strconv 패키지가 있어요.

import "strconv"

var intString string = "42"
var i, err = strconv.Atoi(intString)

var number int = 12
var s string = strconv.Itoa(number)

타입 단언

Go의 인터페이스는 기반 타입에 대해 모호함을 만들어낼 수 있어요. 타입 단언을 사용하면 interfaceVariable.(concreteType)이라는 문법으로 인터페이스 값의 실제 구체 타입 값을 꺼낼 수 있어요.

예를 들어요:

var input any = 12
number := input.(int)

참고: 인터페이스 변수가 해당 구체 타입의 값을 가지고 있지 않으면 패닉이 발생해요.

타입 단언의 두 반환 값, 즉 실제 값과 단언이 성공했는지를 알려 주는 불리언 값을 모두 사용하면 인터페이스 값이 특정 구체 타입을 가지고 있는지 확인할 수 있어요. 예를 들어요:

str, ok := input.(string) // no panic if input is not a string

input이 string을 가지고 있다면 str이 실제 값이 되고 ok는 true가 돼요. input이 string을 가지고 있지 않다면 str은 string 타입의 제로 값(즉, "", 빈 문자열)이 되고 ok는 false가 돼요. 어느 경우에도 패닉은 발생하지 않아요.

타입 스위치

타입 스위치는 여러 타입 단언을 연달아 수행할 수 있어요. 문법은 타입 단언(interfaceVariable.(concreteType))과 같지만, concreteType 자리에 type 키워드가 들어가요. 예를 들어요:

var i any = 12 // try: 12.3, true, int64(12), []int{}, map[string]int{}

switch v := i.(type) {
case int:
    fmt.Printf("the integer %d\n", v)
case string:
    fmt.Printf("the string %s\n", v)
default:
    fmt.Printf("type, %T, not handled explicitly: %#v\n", v, v)
}

지침

Jen은 큰 공장의 분류실에서 일해요. 분류실은 들어오는 모든 것에 라벨을 붙여 분류하는 방식으로 처리해야 해요. Jen은 숫자로 미리 분류된 것들을 맡고 있고, 분류 작업을 도와줄 프로그램이 필요해요.

대부분의 원시 값에는 단순한 라벨이 붙어야 해요. 숫자의 경우, Jen은 (숫자가 2라면) "This is the number 2.0" 같은 문자열을 원해요. Jen은 정수와 실수에 대해 같은 출력을 원해요.

내용물을 얻으려면 포장을 풀어야 하는 Box 인터페이스가 몇 가지 있어요. NumberBox의 경우, (Number() 메서드가 3을 반환하면) "This is a box containing the number 3.0" 같은 문자열을 원해요. FancyNumberBox의 경우, 타입이 FancyNumber일 때만 "This is a fancy box containing the number 4.0" 같은 문자열을 원해요.

예상치 못한 것은 무엇이든 "Return to sender"라고 해야 Jen이 그것들을 온 곳으로 돌려보낼 수 있어요.

1. 간단한 숫자 설명하기

Jen은 숫자가 "This is the number 2.0" 같은 문자열을 반환하기를 원해요 (소수점 뒤 한 자리를 포함해서요):

fmt.Println(DescribeNumber(-12.345))
// Output: This is the number -12.3

2. 숫자 상자 설명하기

Jen은 숫자 상자가 "This is a box containing the number 2.0" 같은 문자열을 반환하기를 원해요 (마찬가지로 소수점 뒤 한 자리를 포함해서요):

fmt.Println(DescribeNumberBox(numberBoxContaining{12}))
// Output: This is a box containing the number 12.0

3. 팬시 숫자 상자에서 숫자를 추출하는 메서드 구현하기

Jen은 FancyNumberBox에서 숫자를 추출할 도우미 함수가 필요해요. FancyNumberBox가 FancyNumber라면, 값을 추출해서 string에서 int로 변환해요. 다른 타입의 FancyNumberBox는 0을 반환해야 해요.

fmt.Println(ExtractFancyNumber(FancyNumber{"10"}))
// Output: 10
fmt.Println(ExtractFancyNumber(AnotherFancyNumber{"4"}))
// Output: 0

4. 팬시 숫자 상자 설명하기

FancyNumberBox가 FancyNumber라면, Jen은 "This is a fancy box containing the number 4.0" 같은 문자열을 원해요. 다른 타입의 FancyNumberBox는 "This is a fancy box containing the number 0.0"라고 해야 해요.

fmt.Println(DescribeFancyNumberBox(FancyNumber{"10"}))
// Output: This is a fancy box containing the number 10.0
fmt.Println(DescribeFancyNumberBox(AnotherFancyNumber{"4"}))
// Output: This is a fancy box containing the number 0.0

참고: ExtractFancyNumber 함수를 사용해야 해요!

5. 이 모든 것을 사용하는 DescribeAnything 구현하기

이것은 Jen이 필요로 하는, 어떤 입력이든 받는 핵심 함수예요. DescribeAnything은 전달된 값의 타입에 따라 다른 함수에 위임해야 해요. 더 구체적으로는:

  • int와 float64는 둘 다 DescribeNumber에 위임해야 해요
  • NumberBox는 DescribeNumberBox에 위임해야 해요
  • FancyNumberBox는 DescribeFancyNumberBox에 위임해야 해요
  • 그 외에는 "Return to sender"가 되어야 해요
fmt.Println(DescribeAnything(numberBoxContaining{12.345}))
// Output: This is a box containing the number 12.3
fmt.Println(DescribeAnything("some string"))
// Output: Return to sender
GitHub에서 편집 링크가 새 창이나 탭에서 열려요
Go Exercism

분류실 문제를 시작해 볼 준비가 됐나요?

Exercism에 가입하고 Go 트랙을 개념 34개연습 문제 166개, 그리고 실제 사람의 멘토링과 함께 배우고 익혀 보세요. 모두 무료예요.