2013-02-26 16 views
22

Jakie korzyści wynikają z nazewnictwa parametrów zwracanych przez funkcję?Dlaczego powinny być zwracane nazwy parametrów?

func namedReturn(i int) (ret int) { 
    ret = i 
    i += 2 
    return 
} 

func anonReturn(i int) int { 
    ret := i 
    i += 2 
    return ret 
} 
+0

Aby dodać do odpowiedzi z @ thomaskappler i dyskusji tam (nie mogę jeszcze komentować), można użyć nazwanych parametrów wyników, a także określić zmienne w swoim zwrocie. Zapewnia to korzyści wynikające z dokumentacji, ale usuwa obawy związane z cieniem. Jednak eliminuje> Jeśli masz wiele witryn zwrotnych, nie musisz ich zmieniać, jeśli zmienisz wartości zwracane przez funkcję, ponieważ po prostu powiesz "return". zasiłek. – darkwing

Odpowiedz

28

Istnieją pewne korzyści dla ich nazewnictwa:

  • Służy jako dokumentacji.
  • Są one automatycznie zadeklarowane i zainicjowane na wartości zerowe.
  • Jeśli masz wiele witryn zwrotnych, nie musisz ich zmieniać, jeśli zmienisz wartości zwracane przez funkcję, ponieważ po prostu powiesz "return".

Istnieją również wady, głównie że łatwo jest przypadkowo je zacienić, deklarując zmienną o tej samej nazwie.

Efektywny Go ma section on named result parameters.

+4

Shadowing to poważny problem. Często mam coś takiego: 'i, err: = strconv.Atoi (...)'. 'i' jest zmienną lokalną, ale chcę, żeby err była wartością zwracaną. Aby to zadziałało, muszę zadeklarować wcześniej i nie używać: = – tjameson

+0

"Są one automatycznie zadeklarowane i zainicjowane na wartości zerowe." - Nie widzę, jak to jest korzyść. Ogólnie rzecz biorąc, jest to bardzo dziwne i wręcz ryzykowne, że Golang uzyskuje swobodę zwracania wartości z metody i oczekuje, że kod klienta będzie wiedział, że jest to wartość domyślna zwracana automatycznie w przypadku, gdy nie zwrócono żadnej innej wartości. – luqo33

3

Jest to przydatne w co najmniej dwóch przypadkach:

  1. Ilekroć trzeba zadeklarować zmienne, które zamierzamy powrócić. Na przykład.

    func someFunc() (int, error) { 
        var r int 
        var e error 
        ok := someOtherFunc(&r) // contrived, I admit 
        if !ok { 
         return r, someError() 
        } 
        return r, nil 
    } 
    

    vs.

    func someFunc() (r int, e error) { 
        ok := someOtherFunc(&r) 
        if !ok { 
         e = someError() 
        } 
        return 
    } 
    

    ten staje się coraz bardziej ważne, jak liczba ścieżek wykonawczej przez wzrasta funkcyjnych.

  2. Podczas dokumentowania wartości zwracanych i chcesz odwoływać się do nich po nazwie. godoc uwzględnia zmienne zwracane jako część podpisu funkcji.

2

Na przykład nazwane parametry powrotu są dostępne za pomocą, no, nazwa.

func foo() (a, b, c T) { 
     // ... 
     if qux { 
       b = bar() 
     } 
     // ... 
     return 
} 

To nie jest łatwe do powielenia bez nazwanych parametrów zwracanych. Należy wprowadzić zmienne lokalne o zasadniczo takiej samej funkcjonalności, co nazwane parametry zwracane:

func foo() (T, T, T) { 
     var a, b, c T 
     // ... 
     if qux { 
       b = bar() 
     } 
     // ... 
     return a, b, c 
} 

Łatwiej jest to dopuścić bezpośrednio.

Dodatkowo są przystępnie również w drugą stronę:

func foo() (a, b, c T) { 
     // ... 
     if a > c { 
       b = bar() 
     } 
     // ... 
     return 
} 

Itd

16

Innym specjalnego przeznaczenia dla zmiennej o nazwie powrotną ma zostać przechwycone przez odroczony funkcji dosłownym. Niewielka ilustracja:

package main 

import (
    "errors" 
    "fmt" 
) 

func main() { 
    fmt.Println(f()) 
} 

var harmlessError = errors.New("you should worry!") 

func f() (err error) { 
    defer func() { 
     if err == harmlessError { 
      err = nil 
     } 
    }() 
    return harmlessError 
} 

Wyjście to <nil>. W bardziej praktycznych sytuacjach funkcja odroczona może obsługiwać panikę i może modyfikować inne wartości zwracane poza wynikiem błędu. Magia powszechna jednak polega na tym, że odroczony literał ma szansę zmodyfikować wartości zwracane przez f po tym jak f jest zakończone, albo normalnie, albo przez panikę.

+0

Czy f() nie działa tak samo, nawet jeśli błąd został zadeklarowany lokalnie wewnątrz f(), a następnie użyty przez odroczenie? => func f() (błąd err) {} @sonia –

Powiązane problemy