패키지 errors
는 오류를 조작하는 기능을 구현한다.
New 함수는 내용만으로 문자 메시지인 오류를 만든다.
Unwrap
, Is
, As
기능은 다른 오류를 래핑할 수 있는 오류에 대해 작동한다.
유형에 메소드가 있다면 오류가 다른 오류를 래핑한다.
Unwrap() error
e.Unwrap()
이 nil
이 아닌 오류를 반환한다면 e
가 w
을 래핑한다 라고 말한다.
Unwrap
은 래핑된 에러를 언팩한다. 인수의 타입이 Unwrap
함수를 가질 경우, 메소드를 한번 호출한다. 그렇지 않으면 nil
을 반환한다.
래핑된 오류를 만드는 간단한 방법은 fmt.Errorf
를 호출하고 %w
동사에 오류 인수를 적용하는 것이다.
errors.Unwrap(fmt.Errorf("... %w ...", ..., err, ...))
위는 err
를 리턴한다.
Is
는 첫 인수를 순차적으로 풀어 두 번째 인수와 일치하는 오류를 찾는다.
단순한 평등 검사보다 우선적으로 사용해야 한다.
if errors.Is(err, fs.ErrExist)
위는 ==
연산보다 바람직 하다.
if err == fs.ErrExist ❌
왜냐면 err
가 fs.ErrExist
를 래핑하면 전자가 성공하기 때문이다.
func As(err error, target interface{}) bool
As
는 target
과 일치하는 err
의 체인에서 첫 번째 오류를 찾고,
그렇다면 target
을 해당 오류 값으로 설정하고 true
를 반환한다.
그렇지 않으면 false
를 반환한다.
체인은 err
자체와 Unwrap
을 반복적으로 호출하여 얻은 오류 시퀀스로 구성된다.
오류 유형은 다른 유형인 것처럼 처리할 수 있도록 As
메소드를 제공한다.
target
이 오류를 구현하는 유형 또는 모든 인터페이스 유형에 대한 nil
이 아닌 포인터가 아니면 패닉으로 나타난다.
func Is(err, target error) bool
오류 체인의 오류가 대상과 일치하는 지 여부를 반환한다.
체인은 err
자체와 Unwrap
을 반복적으로 호출하여 얻은 오류 시퀀스로 구성된다.
오류는 대상과 일치하거나 Is
함수가 true
를 리턴하는 Is (error) bool
메소드를 구현하는 경우 대상과 일치하는 것으로 간주한다.
func New (text string) error
New
는 주어진 텍스트로 포맷하는 오류를 반환한다.
New
에 대한 각 호출은 텍스트가 동일해도 고유한 오류 값을 반환한다.
패키지 sort
는 슬라이스 및 사용자 정의 컬렉션을 정렬하기 위한 기능을 제공한다.
func Float64s (x [] float64)
Float64s
는 float64 조각을 오름차순으로 정렬.
NaN
값은 다른 값보다 먼저 정렬된다.
func Float64sAreSorted(x [] float64) bool
Float64sAreSorted
는 조각 x
가 다른 값보다 먼저 NaN
값을 사용하여 오름차순으로 정렬되는지 여부를 반환
func Ints(x [] int)
Ints
는 int 조각을 오름차순 정렬
finc IntsAreSorted
IntsAreSorted
는 슬라이스 x
가 오름차수능로 정렬됐는지 여부 반환
func IsSorted(data interface) bool
데이터의 정렬 여부를 반환
func Search(n int, f func(int) bool) int
이진 검색으로 f(i)
가 참인 [0, n]
에서 가장 작은 인덱스 i
를 반환
이진 검색이기 때문에 데이터가 내림차순인지 오름차순인지 알 필요가 있다.
오름차순의 데이터에서 5
를 찾기 위해선 다음과 같이
Search (len (data), func (i int) bool {return data [i]> = 5})
별도로 테스트를 진행해야 한다.
오름차순은 >=
, 내림차순은 <=
을 사용하자.
위를 이해하기 위해 간단한 예제를 살펴보자.
func main() {
x := 5
data := []int{1, 2, 3, 4, 5}
i := sort.Search (len (data), func (i int) bool {
return data [i] >= x
})
if i <len (data) && data [i] == x {
fmt.Printf("x는 data [%d]에 존재합니다.", i)
}
}
예제를 살펴보면 데이터가 오름차순이고 data[i] >= x
를 확인할 수 있다.
위 결과는 x 는 data [4]에 존재합니다.
가 출력된다.
반대로 data[i] <= x
도 시도해보자.
func SearchFloat64s(a[] float64 ,x float64) int func SearchInts(a[] int ,x int) int func SearchStrings(a []string, x string) int
위 Search[Float64s|Ints|Strings]
는 오름차순 정렬된 슬라이스 중에서 x
를 검색하여 지정된 인덱스를 반환한다.
x
가 없을 경우의 반환 값은 x
를 삽입할 인덱스(len(a)
일 수 있음) 이다.
func Slice(x interface{}, less func(i, j int) bool)
Slize
는 제공된 less
함수로 슬라이스 x
를 정렬한다.
만약 x
가 슬라이스가 아니라면 패닉이 발생한다.
정렬이 안정적이라고 보장할 수 없으며 동일한 요소가 원래 순서에서 반전될 수도 있다.
안정적인 정렬을 위해 SliceStable
를 사용한다.
less
함수는 인터페이스 유형의 Less
메소드와 동일한 요구 사항을 충족해야 한다.
func SliceIsSorted(x interface{}, less func(i, j int) bool) bool
SliceSorted
는 슬라이스 x
가 제공된 less
함수에 따라 정렬되는지 여부를 반환한다.
x
가 슬라이스가 아니라면 패닉이 발생한다.
func SliceStable(x interface{}, less func(i, j int) bool)
SliceStable
은 제공된 less
함수를 사용하여 슬라이스 x
를 정렬하여 동일한 요소를 원래 순서대로 유지한다.
x
가 슬라이스가 아니라면 패닉이 발생한다.
less
함수는 인터페이스 유형의 Less
메소드와 동일한 요구사항을 충족해야 한다.
func Sort(data Interface)
Sort
는 data
를 정렬한다.
data.Len
을 한 번 호출하여 n
을 결정하고 O(n*log(n))
은 data.Less
와 data.Swap
을 호출한다.
이 정렬은 안전하다고 보장할 수 없다.
func Stable(data Interface)
Stable
는 동등한 요소의 원래 순서를 유지하며 데이터를 정렬한다.
data.Len
을 한 번 호출하여 n
을 결정하고 O(n*log(n))
은 data.Less
를 호출하고 O(n*log(n)*log(n))
은 data.Swap
을 호출한다.
func Strings(x []string)
Strings
는 문자열 슬라이스를 오름차순으로 정렬한다.
func StringsAreSorted(x []string) bool
StringsAreSorted
는 슬라이스 x
가 오름차순 정렬인지 여부를 반환한다.
func Reverse(data interface) interface
Reverse
는 데이터의 역순으로 인터페이스를 반환한다.
다음과 같이 사용할 수 있다.
func main() {
s := []int{5, 2, 6, 3, 1, 4} // 정렬되지 않음
sort.Sort(sort.Reverse(sort.IntSlice(s)))
fmt.Println(s) // [6 5 4 3 2 1] 출력
}
다음과 같은 인터페이스의 형태가 있다.
type Interface interface {
// 해당 컬렉션의 요소들의 갯수
Len() int
// i 인 요소가 j 보다 먼저 정렬되는지 여부를 반환
Less(i, j int) bool
// 인덱스 i 와 j 의 순서를 교체한다.
// Swap swaps the elements with indexes i and j.
Swap(i, j int)
}
다음 인터페이스는 Interface
의 메소드와 각 타입의 슬라이스를 연결한다.
Float64Slice
, IntSlice
, StringSlice
위 Interface
의 메소드에 추가적으로
Search
, Sort
가 있다. (앞서 배운 것들)