Kiedy używać os.Exit () i panic ()?


95

Czy ktoś mógłby wyjaśnić kluczowe różnice między os.Exit()i panic()oraz w jaki sposób są one używane w praktyce w Go?


11
Tylko komentarz, który, miejmy nadzieję, pomoże w przyszłym czytaniu kodu Go: w wielu przykładowych kodach panicjest używany do kończenia pracy w przypadku błędu, wyłącznie dlatego, że jest łatwy do zrozumienia i eliminuje importowanie jakichkolwiek innych pakietów. To nie znaczy, że jest dobry, lub idiomatyczne praktykę! . To tylko urządzenie oszczędzające miejsce, na przykład kod. IRL rezerwuje panicna bardzo szczególne sytuacje.
Intermernet

2
Hm..good) zwłaszcza skrót "IRL" - to dla mnie nowość :) Czy możesz wyjaśnić, jak panika eliminuje importowanie paczek?
Timur Fayzrakhmanov

5
panicjest wbudowany. Zaleca się (zależnie od okoliczności), aby użyć czegoś podobnego os.Exit, log.Fatalitd., Która zwróci kod błędu do systemu operacyjnego (zalecane zawsze, jeśli to możliwe). Wszystko to obejmuje importowanie pakietu, a tym samym „zaśmiecanie” przykładowego kodu. Przykładowy kod powinien być zawsze używany tylko w celu zademonstrowania rozwiązania określonego problemu. Mogą istnieć inne problemy z kodem, które sprawiają, że kod jest bardziej złożony, jeśli jest odpowiednio zademonstrowany, a zatem utrudniają wyjaśnienie udzielonej odpowiedzi. YMMV.
Intermernet

1
Ok, rozumiem) Wielkie dzięki) widzę, że jest jeszcze inny skrót do mojego słownictwa :)!
Timur Fayzrakhmanov

2
NP, z przyjemnością pomogę i zwiększysz swój akronimiczny leksykon :-)
Intermernet,

Odpowiedzi:


85

Przede wszystkim, kiedy masz pytanie „jak to jest używane w praktyce”, dobrym sposobem na rozpoczęcie jest przeszukanie kodu źródłowego Go (lub dowolnej wystarczająco dużej bazy kodu Go, tak naprawdę) i dokumentacji pakietu w celu uzyskania odpowiedzi.

Teraz os.Exiti panicsą zupełnie inne. panicjest używany, gdy program lub jego część osiągnęły stan niemożliwy do odzyskania.

Gdy panicjest wywoływana, w tym niejawnie w przypadku błędów czasu wykonywania, takich jak indeksowanie wycinka poza granicami lub niepowodzenie potwierdzenia typu, natychmiast zatrzymuje wykonywanie bieżącej funkcji i rozpoczyna rozwijanie stosu goroutine, uruchamiając po drodze wszelkie odroczone funkcje. Jeśli to odwijanie osiągnie szczyt stosu gorutyny, program umiera.

os.Exitjest używany, gdy trzeba natychmiast przerwać program , bez możliwości przywrócenia lub wykonania odroczonej instrukcji czyszczenia, a także zwrócić kod błędu (który inne programy mogą wykorzystać do zgłoszenia tego, co się stało). Jest to przydatne w testach, gdy już wiesz, że po tym, jak jeden test się nie powiedzie, drugi również się nie powiedzie, więc równie dobrze możesz teraz po prostu zakończyć. Można tego również użyć, gdy program zrobił wszystko, co musiał, a teraz musi tylko zakończyć, tj. Po wydrukowaniu komunikatu pomocy.

W większości przypadków nie będziesz używać panic(powinieneś errorzamiast tego zwrócić ) i prawie nigdy nie potrzebujesz os.Exitpoza niektórymi przypadkami w testach i do szybkiego zakończenia programu.


9
„Jest to przydatne w testach, kiedy już wiesz, że po tym, jak jeden test się nie powiedzie, drugi również się nie powiedzie…” To pachnie testującym anty-wzorcem testów zależnych. W dobrze napisanym zestawie testów każdy test jest niezależny; wynik jakiegokolwiek testu nigdy nie powinien przesądzać o wyniku żadnego innego testu.
gotgenes

1
@gotgenes Niekoniecznie. Jeśli mam test, w którym określona funkcja zwraca strukturę różną od zera, a ten test się nie powiedzie, to mogę się spodziewać, że wszystkie testy sprawdzające wartości struktury również zakończą się niepowodzeniem. To kod jest zależny, a nie testy. (To powiedziawszy, nie użyłbym exitw tym przypadku, po prostu spodziewałbym się dużego stosu nieudanych asercji.)
David Moles

84

Przede wszystkim os.Exit()można go użyć do normalnego wyjścia z programu bez błędu i bez paniki, więc jest to jedna kluczowa różnica. Innym jest to, że gdzieś panikę można złapać i zignorować lub zarejestrować za pomocą recover.

Ale jeśli mówimy o błędnym kodzie wyjścia, powiedzmy:

Użyj, panicgdy coś pójdzie nie tak, prawdopodobnie błąd programisty, który powinien zostać wyłapany przed przejściem do produkcji. Dlatego drukuje stos.

Użyj os.Exit(errorCode)lub czegoś takiego, jeśli chcesz:

  1. kontrolować kod zakończenia programu do celów skryptowych.

  2. chcą uporządkowanego zakończenia w przypadku oczekiwanego błędu (np. błąd danych wejściowych użytkownika).

Zasadniczo panika jest dla ciebie, zły kod wyjścia jest dla twojego użytkownika.


Dzięki bardzo pomocne!)
Timur Fayzrakhmanov

14
„Więc generalnie panika jest dla ciebie, zły kod wyjścia dla twojego użytkownika”. <- Niesamowita wskazówka
psousa

1
Czy możemy powiedzieć, że panic () jest w jakiś sposób powiązane ze zwykłym wywołaniem assert () w zwykłym C? Cóż ... Wiem, że zawsze usuwam wywołanie potwierdzające przed przekazaniem do produkcji, włączam je tylko podczas testowania nowej funkcji. Chodzi mi o to, że przez większość czasu używam assert () do weryfikacji niezmienników, które, jak sądzę, muszą być prawdziwe w moim kodzie. Czy widzisz to samo użycie dla panic ()? :-)
yves Baumes

7

Kluczowe różnice to:

  1. os.Exit pomija wykonanie odroczonej funkcji.
  2. Za pomocą os.Exitmożna określić kod zakończenia.
  3. panickończy, podczas gdy os.Exitnie jest. (Wydaje się, że inne odpowiedzi o tym nie wspominają.)

Jeśli chcesz wykonać odroczoną funkcję, nie masz innego wyjścia panic. (Z drugiej strony, jeśli chcesz pominąć wykonywanie funkcji odroczonej, użyj os.Exit.)

Jeśli funkcja nie pusta jest zdefiniowana w następujący sposób:

  1. funkcja zawiera wiele gałęzi
  2. wszystkie gałęzie są zakończone returnlubpanic

Wtedy nie możesz zamienić na, panicw os.Exitprzeciwnym razie kompilator odmówi kompilacji programu, mówiąc „brak powrotu na końcu funkcji”. (Go jest tutaj bardzo głupi, nawet log.Panicnie kończy funkcji).

W innych warunkach:

  1. Użyj, panicgdy dzieje się coś naprawdę połączonego, np. Błąd logiki programowania.
  2. Użyj, os.Exitgdy chcesz natychmiastowego wyjścia z określonym kodem zakończenia.
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.