속성 과정 제7부분: 함수, 클로즈업과 지연


기능
우리는 앞장에서 함수를 상세하게 토론했다.하지만 이제 함수의 더 많은 특성을 소개해 봅시다.함수는 고 문법의 첫 번째 종류의 공민이다.이것은 함수가 다른 유형과 유사하여 다른 함수에 전달될 수도 있고 함수에서 되돌아올 수도 있다는 것을 의미한다.그러나 우리가 함수에 대해 할 수 있는 또 다른 일은 함수 유형을 정의하는 것이다.
type HandlerFunc func(ResponseWriter, *Request)

The above is from actual source code of go pkg net/http HandlerFunc


함수에 형식 정의를 만들 수 있다는 것은 정말 대단하다.우리가 이렇게 하기를 희망하는 주요 원인 중 하나는 우리가 더 적은 코드를 작성할 수 있기 때문이다.
func takesFunc(func (int, string, bool) (bool, error)) int

//vs

type CrazyFunc(int, string, bool) (bool, error)
func takesFunc(c CrazyFunc) int
양자 사이에서 나는 후자가 더욱 가독성과 가독성을 갖추고 있다고 생각한다.코드 라이브러리에 뛰어든 사람은 takesFunc 계약이 무엇을 완성해야 하는지 쉽게 알 수 있다.그 밖에 만약에 우리가 CrazyFunc을 매개 변수로 하는 함수가 여러 개 있다면, 우리가 최종적으로 작성한 코드는 더욱 적을 것이다.이것은 윈윈이다.
그러나 함수 유형을 정의할 수 있는 더 중요한 장점은 우리가 방법을 함수에 추가할 수 있다는 것이다.우리는 아직 방법에 대해 언급하지 않았지만, 간단하게 말하면 방법은 특정 유형에 부가된 함수이다.우리는 func 키워드와 함수명 사이에 나타나는receiver 매개 변수를 사용하여 방법을 표시합니다.우리가 함수를 가진 인터페이스를 실현할 수 있기 때문에 방법을 정의할 수 있는 것은 정말 강력하다.예를 들어 HandlerFunc 함수의 예.우리는 함수 자체를 호출하는 방법인 ServeHTTP을 추가했다. 현재 우리의 HandlerFuncHandler 인터페이스를 실현했다. 이것은 http 서버를 구축하는 데 필요한 것이다.
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
    f(w, r)
}
현재, 우리 코드에서, 우리는 Handle에서 *http.ServeMux 방법과 유사한 처리 프로그램을 전달해야 한다. 우리는 HandlerFunc 형식과 HandlerFunc이 같은 서명을 가진 함수로 변환할 수 있다.

In practice we probably will use the HandleFunc method that does the casting for us. But its possible.


만약 네가 우리가 여기서 말한 모든 것을 이해하지 못한다면 걱정하지 마라.가능한 것이 무엇인지 빨리 알 수 있도록 하기 위해서다.우리는 이 모든 것을 정확하게 이용할 수 있도록 좀 더 기본적인 지식이 필요하다.

가방을 닫다
클립을 이해하기 전에 익명 함수를 이해해야 한다.

익명 함수
익명 함수는 말 그대로 익명이다.그것들은 이름이 없는 함수다.go에서 우리는 함수 내연을 변수로 정의하거나 되돌릴 수 있다.
adder := func(a int, b int) int {
    return a + b
}

가방을 닫다
클로즈업은 함수 범위 밖에서 정의된 변수의 익명 함수를 가리킨다.역할 영역은 함수에 유효해야 합니다.
func counter() func() int {
    i := 0
    return func() int {
        i++
        return i
    }
}
이 예에서, 우리는 함수 counter이 하나 있는데, 이 함수는 익명 함수를 되돌려줍니다. 이 함수는 counter에서 설명한 변수를 인용합니다.그래서 우리가 되돌아오는 내부 함수는 클립입니다.
우리 코드에서 우리는 이 함수를 사용할 수 있다
counter1 := counter()
counter2 := counter()

fmt.Println(counter1()) // 1
fmt.Println(counter2()) // 1
우리는 그것들을 호출할 때마다 두 개의 독립된 계수기를 만들었다.계수기는 상당히 어리석은 클립 예일 수도 있지만, 나는 그것이 사람들로 하여금 이 점을 이해하게 할 수 있기를 바란다.그리고 this amazing article by Jon Calhoun은 더욱 깊이 들어가 클립을 이용하여 코드를 개선할 수 있다.

미루다
Go에서 defer 키워드는 주변 함수가 반환될 때까지 함수의 실행을 지연시키는 데 사용됩니다.
func deferredPrint() {
    defer fmt.Println("defer 1")
    fmt.Println("regular thing")
    defer fmt.Println("defer 2")
}
이 작업을 수행하면 deferredPrint이 인쇄됩니다.
regular thing
defer 2
defer 1
여기에는 두 가지 관건적인 관찰 결과가 있다.우선, 우리의 fmt.Println 함수 호출은 지연이 없이 먼저 실행됩니다.이것은 일리가 있다. 왜냐하면 defer는 우리가 함수의 끝에 도달할 때까지 다른 함수 호출의 집행을 늦출 수 있기 때문이다.그 다음으로, 우리의 지연 함수의 인쇄 순서는 상반된 것 같다.이것은 랜덤이 아니다.우리의 모든 연기는 상반된 순서에 따라 집행될 것이다.
어떤 상황이 발생하든지 간에, 데이터베이스 연결을 닫거나 파일을 닫을 때, '지연' 은 특히 유용하다.지연도 공황 회복에 도움이 된다.우리는 아직 공황에 대해 이야기하지 않았다.통상적으로, 우리 프로그램에서 당황하는 것은 결코 좋은 생각은 아니지만, 어떤 경우에는 그것이 적합하다.우리는 다음 장에서 공황에 대해 상세하게 토론할 것이다.

다음 단계
고속성반 시리즈 7부다.

좋은 웹페이지 즐겨찾기