Zoeken…


Sluiting Basics

Een sluiting is een functie samen met een omgeving. De functie is meestal een anonieme functie die in een andere functie wordt gedefinieerd. De omgeving is de lexicale reikwijdte van de omhullende functie (een zeer basisidee van een lexicale reikwijdte van een functie zou de reikwijdte zijn die bestaat tussen de accolades van de functie.)

func g() {
    i := 0
    f := func() { // anonymous function
        fmt.Println("f called")
    }
}

Binnen het lichaam van een anonieme functie (zeg f ) gedefinieerd binnen een andere functie (zeg g ), zijn variabelen aanwezig in scopes van zowel f als g toegankelijk. Het is echter de reikwijdte van g die het omgevingsdeel van de afsluiting vormt (functiedeel is f ) en als gevolg daarvan behouden wijzigingen in de variabelen in de reikwijdte van g hun waarden (dwz de omgeving blijft bestaan tussen aanroepen van f ) .

Overweeg de onderstaande functie:

func NaturalNumbers() func() int {
    i := 0
    f:= func() int { // f is the function part of closure
        i++
        return i
    }
    return f
}

In bovenstaande definitie heeft NaturalNumbers een innerlijke functie f die NaturalNumbers teruggeeft. Binnen f wordt toegang verkregen tot variabele i gedefinieerd in het kader van NaturalNumbers .

We krijgen een nieuwe functie van NaturalNumbers als volgt:

n := NaturalNumbers()

Nu is n een sluiting. Het is een functie (gedefinieerd door f ) die ook een bijbehorende omgeving heeft (bereik van NaturalNumbers ).

In het geval van n bevat het omgevingsdeel slechts één variabele: i

Aangezien n een functie is, kan deze worden genoemd:

fmt.Println(n()) // 1
fmt.Println(n()) // 2
fmt.Println(n()) // 3

Zoals uit bovenstaande uitvoer blijkt, wordt elke keer dat n wordt aangeroepen i verhoogd. i begint bij 0 en elke aanroep naar n voert i++ .

De waarde van i blijft behouden tussen gesprekken. Dat wil zeggen, het milieu, dat deel uitmaakt van sluiting, blijft bestaan.

Als u NaturalNumbers opnieuw belt, wordt een nieuwe functie gemaakt en geretourneerd. Dit zou een nieuwe i binnen NaturalNumbers initialiseren. Wat betekent dat de nieuw geretourneerde functie een andere afsluiting vormt met hetzelfde onderdeel voor functie (nog steeds f ) maar een geheel nieuwe omgeving (een nieuw geïnitialiseerde i ).

o := NaturalNumbers()

fmt.Println(n()) // 4
fmt.Println(o()) // 1
fmt.Println(o()) // 2
fmt.Println(n()) // 5

Zowel n als o zijn sluitingen die hetzelfde functiedeel bevatten (waardoor ze hetzelfde gedrag vertonen), maar verschillende omgevingen. Het gebruik van sluitingen maakt het dus mogelijk dat functies toegang hebben tot een persistente omgeving die kan worden gebruikt om informatie tussen oproepen te bewaren.

Een ander voorbeeld:

func multiples(i int) func() int {
    var x int = 0
    return func() int {
        x++
        // paramenter to multiples (here it is i) also forms
        // a part of the environment, and is retained
        return x * i
    }
}

two := multiples(2)
fmt.Println(two(), two(), two()) // 2 4 6

fortyTwo := multiples(42)
fmt.Println(fortyTwo(), fortyTwo(), fortyTwo()) // 42 84 126


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow