for
을 사용하여 Sum
함수를 만들 것이다. Sum
함수는 숫자 배열들을 가지고 총합을 리턴할 것이다.테스트 기반 설계
스킬을 활용할 것이다.sum_test.go
라는 파일을 생성한 후 아래 코드를 집어넣는다.numbers := [5]int{1, 2, 3, 4, 5}
numbers := [...]int{1, 2, 3, 4, 5}
go test
로 실행을 시키면 다음과 같이 컴파일 에러가 날것이다. ./sum_test.go:10:15: undefined: Sum
sum.go
를 다음과 같이 한다면,sum_test.go:13: got 0 want 15 given, [1 2 3 4 5]
array[index]
라는 syntax를 사용하면 된다. 지금과 같은 경우에는, 우 for
을 이용하여 5번을 반복하며 배열의 각 항목들을 sum에 더할 것이다.range
를 사용하여 코드를 간추릴 것이다.range
는 배열에 반복적인 처리를 할 수 있게 한다. range
는 호출될 때마다 인덱스와 값, 총 두 개의 값을 리턴한다. 우리는 여백 식별자인 _
를 사용하여 인덱스의 값을 무시할 것이다.[5] int
를 요구하는 함수에 [4] int
가 입력될 경우 컴파일 되지 않을 것이다. 이 이유는 바로 타입이 다르기 때문이다, 이는 int
를 요구하는 함수에 string
을 입력한 것과 같다.slice
타입을 이용할 것이다. 슬라이스의 syntax는 배열과 매우 유사하다, 그저 선언할 때 크기를 생략하기만 하면 된다.myArray := [3]int{1,2,3}
대신 mySlice := []int{1,2,3}
처럼./sum_test.go:22:13: cannot use numbers (type []int) as type [5]int in argument to Sum
Sum
을 배열 대신 슬라이스로 바꾸어 주는 것이다. 만약 우리가 이 방법을 사용한다면 우리는 다른 사람의 하루를 망쳤을 수도 있다. 이는 우리의 다른 테스트들을 컴파일 되지 않도록 하기 때문이다.Sum
을 리팩토링을 하였으며, 우리는 그저 배열을 슬라이스로 바꾸기만 했다. 그러므로 이 부분에서는 많이 할 것이 없다. 우리는 리팩토링 단계에서 테스트 코드를 소홀히 하면 안 되고 이 단계에서 우리가 해야 할 것이 있다는 것을 기억해야 한다.go test -cover
SumAll
이라는 여러 슬라이스를 받고 그들의 합을 슬라이스들로 리턴할 새로운 함수가 필요하다.SumAll([]int{1,2}, []int{0,9})
는 []int{3, 9}
을 리턴할 것이다.SumAll([]int{1,1,1})
는 []int{3}
를 리턴할 것이다../sum_test.go:23:9: undefined: SumAll
./sum_test.go:26:9: invalid operation: got != want (slice can only be compared to nil)
got
슬라이스와 want
슬라이스를 반복하여 그들의 값을 비교하는 함수를 만들 수 있다. 하지만 이 방법은 편리하지 않다. 그래서 우리는 any
타입이나 비교할 수 있는 reflect.DeepEqual
를 사용할 수 있다.import reflect
가 있어야 DeepEqual
를 사용할 수 있다.)reflect.DeepEqual
는 "type safe"하지 않다는 것이다. 당신이 멍청한 짓을 했어도 코드는 그냥 컴파일 될 것이다. 이것을 확인하고 싶다면 테스트를 잠시 동안 다음과 같이 바꾼다.슬라이스
와 문자열
을 비교하려고 하고 있다는 것이다. 이것은 터무니없는 일이지만 테스트는 컴파일 되었다. 따라서 reflect.DeepEqual
를 사용하여 슬라이스를 (그리고 다른 문자열들을) 비교하는 것은 매우 편리하지만 사용할 때에 주의를 요한다.sum_test.go:30: got [] want [3 9]
varags
들을 반복적으로 처리하며, 우리의 Sum
한수를 사용해서 합을 계산을 한 후 우리가 리턴할 슬라이스에 추가해야한다.make
함수는 우리가 작업해야 할 numbersToSum
의 len
만큼의 시작 크기를 가지는 슬라이스를 만들 수 있도록 해준다. 당신은 배열에서 mySlice[N]
하듯이 슬라이스에서도 인덱스를 사용할 수 있으며, 새로운 값을 =
를 이용해서 지정해 줄 수 있다.mySlice[10] = 1
를 시도한다면 이것은 런타임 에러가 날것이다.append
함수를 이용할 수 있다.sums
라는 슬라이스에 Sum
함수의 결괏값을 vararngs들을 처리할 때마다 append
를 사용할 것이기 때문이다. 컬렉션의 꼬리 란 제일 첫 번째인 ("머리")를 제외한 나머지 것들을 이야기한다.SumAll
을 모든 슬라이스의 꼬리들의 합을 계산하는 SumAllTails
로 바꾸는 것이다../sum_test.go:26:9: undefined: SumAllTails
SumAllTails
로 이름을 변경하고 테스트를 다시 실행한다.sum_test.go:30: got [3 9] want [2 9]
slice[low:high]
를 통해 잘릴 수 있다. 당신이 :
의 옆에 값을 누락시킨다면, 이것은 그 값부터 끝까지의 값을 가져온다. 우리와 같은 경우 "1부터 끝까지 가져와"를 numbers[1:]
과 같이 표현할 수 있다. 당신은 시간을 조금 투자해서 다른 테스트 등을 통하여 슬라이스와 슬라이스 오퍼레이터와 익숙해져도 좋다.myEmptySlice[1:]
있는 모든 요소들을 달라고 한다면 어떻게 될 것 같은가?checkSums(t, got, "dave")
를 사용하여 새로운 테스트를 한다면 컴파일러가 스스로 테스트들을 멈출 것이다.append
를 사용하여 기존의 슬라이스를 새로운 슬라이스로 만드는 방법len
을 이용하여 배열과 슬라이스의 크기를 받기reflect.DeepEqual
이 왜 유용하며, 왜 코드의 type-safety를 저해할 수 있는가[][] string
당신이 필요하다면.