goto를 사용하는 것이 가치가 있습니까?


29

goto거의 보편적으로 낙담했습니다. 이 진술을 사용하는 것이 가치가 있습니까?



1
gotoCPU가 궁극적으로하는 일이지만 대상 끝에 표시가 없기 때문에 인간이 이해하고 추상화 해야하는 것과 잘 작동하지 않습니다. Intercal과 비교하십시오 COMEFROM.

2
@ ThorbjørnRavnAndersen, 인간 이 상태 머신에서 상태 전환 에 대해 이야기 할 때 다른 의미는 무엇 입니까? 유사성을 볼 수 없습니까? "주어진 상태로 가십시오 "는 그것이 의미하는 바입니다. 그 밖의 것은 사소한 일의 불필요한 합병증 일뿐입니다. "마크 없음"은 무슨 뜻입니까? 라벨은 그런 마크입니다.
SK-logic

@ SK-logic은 고토가 얼마나 멀리 떨어져 있는지에 따라 다릅니다. 상태 머신은 구현하기 위해 goto를 요구하지 않습니다.

@ ThorbjørnRavnAndersen은 물론 goto필요하지 않습니다. 그것은 국가 전환의 의미론에 가장 가깝기 때문에 명령형 언어로 그것들을 구현하는 가장 합리적인 방법입니다. 그리고 목적지는 소스에서 멀리 떨어져있어 가독성을 방해하지 않습니다. 이러한 코드 중 내가 가장 좋아하는 예는 DE Knuth의 Adventure 게임 구현입니다.
SK-logic

답변:


49

이것은 스택 오버플로에서 여러 번 논의되었으며 Chris Gillum 은 다음과 같은 용도를 요약했습니다goto .

기능을 완전히 종료

종종 함수에서 자원을 할당하고 여러 곳에서 종료해야 할 수도 있습니다. 프로그래머는 함수의 끝 부분에 리소스 정리 코드를 넣어 함수의 모든 "종료 지점"이 정리 레이블로 이동하여 코드를 단순화 할 수 있습니다. 이런 식으로 함수의 "종료 지점"마다 정리 코드를 작성할 필요가 없습니다.

중첩 루프 종료

중첩 루프에 있고 모든 루프에서 분리해야하는 경우 goto는 break 문 및 if-check보다 훨씬 깨끗하고 간단하게 만들 수 있습니다.

저수준 성능 개선

이것은 per-critical 코드에서만 유효하지만 goto 문은 매우 빠르게 실행되며 함수를 이동할 때 부스트를 줄 수 있습니다. 그러나 컴파일러는 일반적으로 gotos가 포함 된 코드를 최적화 할 수 없기 때문에 양날의 검입니다.

다른 많은 사람들이 주장 하듯이,이 모든 경우에 사용은 goto자신을 코딩 한 구석에서 벗어날 수있는 수단으로 사용되며 일반적으로 리팩토링 될 수있는 코드의 증상이라고 주장합니다.


28
첫 번째 문제는 finally현대 언어의 블록으로 매우 깔끔하게 해결되고 두 번째 문제는 breaks 로 표시 됩니다. 그러나 C에 갇혀 있다면 goto이 문제를 우아하게 해결할 수있는 유일한 방법입니다.
Chinmay Kanchi

2
아주 좋은 지적입니다. Java가 여러 수준의 루프를 차단하는 방법을 좋아합니다
Casebash

4
@Chinmay-마지막으로 블록은 1) 최신 언어에만 적용됩니다. b) 오버 헤드를 허용 할 수 있습니다 (예외 처리에는 오버 헤드가 있습니다) finally. goto가가는 길은 매우 드물지만 유효한 상황입니다.
luis.espinal

21
좋아 사람들 ... 도대체 차이점이 무엇인지 break 3break myLabel하고 goto myLabel. 아, 바로 키워드입니다. 당신이 사용하는 경우 break, continue또는 일부 유사한 키워드 당신은 사용 가리키고있다 goto(당신이 사용하는 경우 for, while, foreach, do/loop조건부 고토를 사용하고 있습니다.)
마태 복음 회칠 한

4
낮은 수준의 성능 정보-최신 프로세서의 동작을 예측하기 어려울 수 있으므로 (파이프 라인, 순서가 잘못된 실행) 99 %의 경우 가치가 없거나 느려질 수 있습니다. @MatthewWhited : 범위 지정. 임의의 시점에 스코프를 입력하면 어떤 생성자를 호출해야하는지 명확하지 않습니다 (문제는 C에도 있습니다).
Maciej Piechotka

42

높은 수준의 제어 흐름 구성은 문제 영역의 개념에 해당하는 경향이 있습니다. if / else는 일부 조건에 따른 결정입니다. 루프는 어떤 동작을 반복적으로 수행하라고 말합니다. 브레이크 선언조차도 "우리는 이것을 반복적으로하고 있었지만 이제는 멈춰야한다"고 말합니다.

반면에 goto 문은 문제 영역이 아닌 실행중인 프로그램의 개념에 해당하는 경향이 있습니다. 프로그램 의 특정 지점 에서 실행을 계속한다고 말합니다 . 코드를 읽는 사람 은 문제 영역과 관련하여 그 의미 를 추론 해야합니다.

물론 모든 상위 레벨 구조는 gotos 및 간단한 조건부 분기로 정의 할 수 있습니다. 그렇다고해서 변장 한 것만은 아닙니다. 그것들을 제한된 gotos 라고 생각하십시오 -그것들을 유용하게 만드는 것은 제한입니다. break 문은 둘러싼 루프의 끝으로 점프하는 것으로 구현되지만 루프 전체에서 작동하는 것이 더 좋습니다.

다른 모든 것은 동일하다. 구조가 문제 영역의 구조를 반영하는 코드는 읽고 유지하기가 더 쉽다.

goto 문이 절대적으로 필요한 경우는 없지만 ( 그 효과에 대한 정리 가 있음) 가장 나쁜 해결책이 될 수있는 경우가 있습니다. 이러한 경우는 언어가 지원하는 상위 구조에 따라 언어마다 다릅니다.

예를 들어 C에서는 goto가 적합한 세 가지 기본 시나리오가 있다고 생각합니다.

  1. 중첩 루프에서 벗어나기 언어에 레이블이 지정된 break statement가 있으면 불필요합니다.
  2. 오류 또는 기타 예상치 못한 이벤트가 발생하는 경우 코드 (일반적으로 함수 본문)에서 벗어나기. 언어에 예외가있는 경우에는 불필요합니다.
  3. 명시 적 유한 상태 머신을 구현합니다. 이 경우 goto는 문제 도메인의 개념에 직접 대응하여 한 상태에서 지정된 다른 상태로 전환하며 현재 상태는 현재 실행중인 코드 블록으로 표시됩니다. .

한편, 명시 적 유한 상태 머신은 루프 내부의 switch 문으로도 구현할 수 있습니다. 이것은 모든 상태가 코드에서 같은 위치에서 시작한다는 장점이 있는데, 예를 들어 디버깅에 유용 할 수 있습니다.

합리적으로 현대적인 언어 (if / else 및 루프를 지원하는 언어)에서 goto의 주요 용도는 언어에서 누락 된 제어 흐름 구성을 시뮬레이션하는 것입니다.


5
이것은 실제로 지금까지 가장 좋은 답변입니다 – 1.5 년 된 질문에 대한 것입니다. :-)
Konrad Rudolph

1
"지금까지 최고의 답변"+1 --- "합리적으로 현대적인 언어 (if / else 및 루프를 지원하는 언어)에서 goto의 주요 용도는 언어에서 누락 된 제어 흐름 구조를 시뮬레이션하는 것입니다."
Dave Dopson

switch-statement state machine에서 제어 값에 대한 모든 쓰기는 실제로입니다 goto. SSSM은 SM 상태를 실행 구성과 분리하기 때문에 사용하기에 좋은 구조 인 경우가 많지만 실제로는 "고 토스"를 제거하지는 않습니다.
supercat

2
"다른 모든 것은 동일하다. 구조가 문제 영역의 구조를 반영하는 코드는 읽고 유지하기가 더 쉽다." 나는 이것을 오랫동안 완전히 알고 있었지만 다른 프로그래머가 실제로 이해할 수 있고 이해할 수있는 방식으로 정확하게 의사 소통 할 단어가 부족했습니다. 감사합니다.
와일드 카드

"구조화 된 프로그램 정리"는 고토를 에뮬레이트하기 위해 구조화 된 프로그래밍 문을 사용하는 것이 단지 고토를 사용하는 것보다 읽기 쉽지 않다는 점을 명확하게 설명하는 경향이 있기 때문에 저를 즐겁게합니다!

11

확실히 그것은 프로그래밍 언어에 달려 있습니다. goto논쟁의 여지가 있었던 주된 이유 는 컴파일러가 너무 자유롭게 사용할 수있을 때 발생하는 악영향 때문입니다. 예를 들어 goto초기화되지 않은 변수에 액세스하거나 다른 방법으로 이동하여 호출 스택을 망칠 수있는 방식으로 사용할 수있는 경우 문제가 발생할 수 있습니다 . 무의미한 제어 흐름을 허용하지 않는 것은 컴파일러의 책임입니다.

Java는이 문제를 goto완전히 금지 함으로써이 문제를“해결”하려고 시도했습니다 . 그러나 Java를 사용하면 블록 return내부에서 사용할 finally수 있으므로 예외가 실수로 삼키게됩니다. 동일한 문제가 여전히 존재합니다. 컴파일러가 작업을 수행하지 않습니다. goto언어에서 제거해도 문제 가 해결되지 않았습니다.

C #에서, goto안전뿐만 같다 break, continue, try/catch/finallyreturn. 초기화되지 않은 변수를 사용할 수 없으며 finally 블록을 뛰어 넘을 수 없습니다. 컴파일러가 불평합니다. 이것은 실제 문제를 해결하기 때문입니다. 이것은 내가 무의미한 제어 흐름이라고 말한 것과 같습니다. goto명확한 할당 분석 및 기타 합리적인 컴파일러 검사를 마술처럼 취소하지 않습니다.


요점은 C # goto이 악하지 않다는 것입니다. 그렇다면, gotoC #뿐만 아니라 구문 과 함께 일상적으로 사용되는 모든 현대 언어의 경우입니다 .
lvella

9

예. 루프가 여러 수준으로 중첩 된 경우 내부 루프를 우아하게 분리 할 수 goto있는 유일한 방법입니다. 다른 옵션은 플래그를 설정하고 해당 플래그가 조건을 만족하는 경우 각 루프에서 분리하는 것입니다. 이것은 실제로 추악하고 오류가 발생하기 쉽습니다. 이 경우 goto단순히 더 좋습니다.

물론 Java의 레이블이 지정된 break명령문은 동일한 작업을 수행하지만 코드에서 임의의 지점으로 이동할 수 goto없으므로 악의적 인 것을 허용하지 않고 문제를 깔끔하게 해결할 수 있습니다.


downvote를 설명 할 사람이 있습니까? 이것은 질문에 대한 완벽한 답변이었습니다 ...
Chinmay Kanchi

4
goto는 결코 우아한 대답이 아닙니다. 루프가 여러 수준으로 중첩 된 경우 문제는 다중 중첩 루프를 피하기 위해 코드를 설계하지 못한 것입니다. 절차 호출은 적이 아닙니다. ( "Lambda : The Ultimate ..."논문을 읽어보십시오.) goto를 사용하여 여러 레벨 깊이로 중첩 된 루프에서 벗어나는 것은 개방형 다중 골절에 반창고를 놓는 것입니다. 단순 할 수도 있지만 옳지 않습니다. 대답.
John R. Strohm

6
물론 깊게 중첩 된 루프가 호출 될 때 이상한 경우는 없을까요? 좋은 프로그래머가되는 것은 규칙을 따르는 것뿐만 아니라 규칙을 어기 게 될 때를 아는 것입니다.
Chinmay Kanchi

2
@ JohnR.Strohm 절대 말하지 마십시오. 프로그래밍에서 "never"와 같은 용어를 사용하는 경우 코너 사례, 최적화, 리소스 제약 등을 다루지 않았습니다. 깊게 중첩 된 루프에서 goto 는 실제로 루프를 종료하는 가장 깨끗하고 우아한 방법입니다. 코드를 얼마나 많이 리팩터링했는지는 중요하지 않습니다.
Sujay Phadke

@ JohnR.Strohm : VB.NET에서 C #으로 전환 할 때 가장 많이 누락 된 기능 : Do루프. 왜? Do루프와 유형 으로의 깊은 휴식이 필요한 하나의 루프를 변경할 수 있기 때문에 Exit Do없습니다 GoTo. 중첩 루프는 항상 발생합니다. 스택을 깨는 것은 시간의 일부 %가 발생합니다.
여호수아

7

낙담의 대부분은 60 년대 초반에 다음과 같은 무차별적인 힘에 대해 설득력있는 신 지크 스트라 (Jaikstra) 신에게 큰 소리로 창조 된 일종의 "종교"에서 나온다.

  • 어떤 코드 블록 으로든 뛰어들 수 있습니다.
    • 처음부터 기능이 실행되지 않음
    • 처음부터 실행되지 않은 루프
    • 건너 뛴 변수 초기화
  • 가능한 정리없이 코드 블록에서 벗어나십시오.

이것은 goto현대 언어 의 진술 과 더 이상 관련이 없으며 , 존재하는 언어 이외의 코드 구조의 생성을 지원하기 위해 존재합니다.

특히 위의 첫 번째 주요 지점은 더 이상 허용되고 두 번째 주요 지점은 청소됩니다 ( goto블록에서 스택을 가져 오면 스택이 올바르게 풀리고 모든 적절한 소멸자가 호출 됨)

goto를 사용하지 않는 코드조차도 읽을 수없는 방법을 알기 위해이 답변 을 참조 할 수 있습니다. 문제 자체가 아니라 잘못 사용하는 것입니다.

if그냥 사용하지 않고 전체 프로그램을 작성할 수 있습니다 for. 물론, 읽기 어렵고, 어색하고 불필요하게 복잡하지는 않습니다.

그러나 문제는 아닙니다 for. 나야

상황이 좋아 break, continue, throw, bool needed=true; while(needed) {...}, 등의 이상 지적하는 가장 무도회 goto -50 년 현대 laguages-의 발명 이후 여전히 포로를 원하는의 Djikstrarian 광신자의 scimitars에서 멀리 탈출. 그들은 지크 스트라가 말한 것을 잊었고, 단지 그의 음표의 제목 만 기억하고 (GOTO는 해로운 것으로 간주되었고 그의 제목도 아니었다 : 편집자에 의해 변경되었다) 4 순서대로 배치 된 편지.

2011 년 : Djikstra가 강요 gotoGOTO진술 을 다루지 않은 것을 이해해야 할 때 입니다.


1
"휴식, 계속, 던지기, bool needed = true; (필요한) {...} 등은 가장 무도회 고토 이상을 지적하고 있습니다"라고 나는 동의하지 않습니다. 나는 "휴식 등의 것들이 제한되어있다 "또는 그와 같은 것을 선호 한다. goto의 주요 문제점은 일반적으로 너무 강력하다는 것입니다. 현재 goto가 Dijkstra보다 강력하지 않은 한, 당신의 대답은 저에게 좋습니다.
Muhammad Alkarouri

2
@ MuhammadAlkarouri : 전적으로 동의합니다. 내 개념을 정확하게 표현하기 위해 더 나은 표현을 찾았습니다. 내 요점은 이러한 제한이 적용되지 않을 수 있으며 필요한 제한이 언어에 없다는 것입니다. 그런 다음 덜 전문화 된 "강력한"것은 해결 방법입니다. 예를 들어, Java break n는 C ++에서 사용할 수 없으므로 n-ple 루프에서 벗어날 필요가없는 goto escape경우에도 마찬가지 escape입니다.
Emilio Garavaglia

4

함수가 지역적으로 존재하는 한 여기 저기의 이상한 이동은 가독성을 크게 해치지 않습니다. 이 코드에는 다소 드문 제어 구조를 사용해야하는 비정상적인 문제가 있다는 사실에주의를 기울임으로써 종종 이점이 있습니다.

(로컬) gotos가 가독성을 크게 손상시키는 경우 일반적으로 goto를 포함하는 함수가 너무 복잡해 졌다는 신호입니다.

내가 C 코드에 넣은 마지막 goto는 한 쌍의 연동 루프를 만드는 것이 었습니다. "허용되는"goto 사용의 일반적인 정의에는 맞지 않지만 결과적으로 함수는 훨씬 작고 명확 해졌습니다. 고토를 피하기 위해서는 특히 지저분한 DRY 위반이 필요했을 것입니다.


1
이것에 대한 답은 오래된 "레이 포테이토 칩"슬로건에서 가장 많이 언급되었습니다 : "단 하나만 먹을 수는 없습니다". 귀하의 예에서, 당신은 두 개의 "인터 록킹"을 가지고 있습니다 (그것이 무엇이든간에 그것이 내 말은 그렇지 않다는 것을 의미합니다). 버스에 부딪힌 후 코드를 수정해야하는 유지 보수 담당자는 어떻습니까? 고토가 그의 삶을 더 쉬워 지거나 더 어려울 것입니까? 이 두 개의 루프를 다시 생각해야합니까?
John R. Strohm

3

나는이 모든 문제가 잘못된 나무를 짖는 사례라고 생각합니다.

GOTO는 나에게는 문제가되지 않지만 오히려 종종 스파게티 코드의 실제 죄의 증상입니다.

GOTO가 유량 제어 라인의 주요 교차점을 유발하면 기간이 좋지 않습니다. 흐름 제어 라인을 통과하지 않으면 무해합니다. 그 사이의 회색 영역에는 루프 구제 금융과 같은 것들이 있지만 모든 합법적 인 회색 사례를 다루는 구문을 추가하지 않은 언어가 여전히 있습니다.

내가 몇 년 동안 실제로 그것을 사용하는 유일한 사례는 결정 지점이 루프의 중간에있는 루프의 경우입니다. 중복 코드, 플래그 또는 GOTO가 남아 있습니다. GOTO 솔루션이 3 가지 중 최고라고 생각합니다. 흐름 제어 라인이 교차하지 않으며 무해합니다.


당신이 암시하는 경우는 때때로 "루프와 반"또는 "N 더하기 반 루프"라고 불리며 goto, 루프로 점프 하는 유명한 유스 케이스입니다 (언어가 이것을 허용한다면; 다른 경우에는 점프하기) 중간에있는 루프에서 일반적으로 goto) 없이 사소 합니다.
Konrad Rudolph

(아아, 대부분의 언어는 루프로 점프하는 것을 금지합니다.)
Konrad Rudolph

@KonradRudolph : GOTO로 "루프"를 구현하면 다른 루프 구조가 없습니다.
Loren Pechtel

1
나는 여기에 제어 흐름goto 을 외치는 것은 정상적인 구조화 된 프로그래밍 패턴을 맞추지 않았다고 생각 합니다. 구조화 된 프로그래밍 패턴에 맞는 제어 흐름은 그렇지 않은 것보다 추론하기가 쉽기 때문에 가능하면 이러한 패턴을 사용하려고 시도해야합니다. 코드가 그러한 패턴에 맞으면, 그렇지 않다고 소리 쳐서는 안됩니다. 반면에, 코드가 실제로 그러한 패턴에 맞지 않는 경우, 코드가 실제로 맞지 않을 때 코드를 맞추는 것보다 소리를 지르는 것이 좋습니다.
supercat

1

예, goto는 개발자의 경험에 도움이 될 수 있습니다 : http://adamjonrichardson.com/2012/02/06/long-live-the-goto-statement/

그러나 강력한 도구 (포인터, 다중 상속 등)와 마찬가지로 도구를 사용하여 훈련해야합니다. 링크에 제공된 예제는 PHP를 사용하는데, goto 구문의 사용법을 동일한 함수 / 방법으로 제한하고 새로운 제어 블록 (예 : loop, switch 문 등)으로 건너 뛰는 기능을 비활성화합니다.


1

언어에 따라 다릅니다. 예를 들어 여전히 Cobol 프로그래밍에서 널리 사용됩니다. 또한 Barionet 50 장치에서 작업했습니다. 펌웨어 프로그래밍 언어는 초기 기본 방언이며 Goto를 사용해야합니다.


0

나는 아니오라고 말할 것입니다. GOTO를 사용할 필요가 있다면 코드를 다시 디자인해야 할 것입니다.


3
아마,하지만 당신은 아무런 추론을하지 않으
셨습니다

Dijkstra는 수십 년 전에 상세하게 추론을 제공했습니다.
John R. Strohm

2
그냥 도그마. 반향 없음. 참고 : Djikstra는 유효한 RESON이 아닙니다. 60 년대 초의 기본 또는 FORTRAN GOTO 문구를 언급 한 것입니다. 그들은 오늘날의 진정한 빈혈 (그들의 힘과 비교)과 관련이 없습니다.
Emilio Garavaglia

0

goto레거시 어셈블러 코드를 C로 포팅 할 때 유용 할 수 있습니다. 첫 번째 경우, goto어셈블러 branch명령을 대신 하여 C 로의 명령 별 변환 은 매우 빠른 포팅을 가능하게합니다.


-1

나는 주장하지 않을 것이다. 그것들은 항상 goto가 해결하는 데 사용되는 문제에 대해 더 구체적인 도구로 대체되어야합니다 (귀하의 언어로 제공되지 않는 한). 예를 들어, break 문과 예외는 루프 이스케이프 및 오류 처리의 이전에 해결 된 문제를 해결합니다.


언어에 이러한 기능 이 모두 있는 경우 goto일반적으로 해당 언어가 없다고 주장합니다 .
Chinmay Kanchi

그러나 그들이 필요하지 않거나 사람들이 필요하지 않다고 생각 하기 때문 입니까?
Michael K

당신의 견해는 비싸다. 문제가 많은 goto도메인 시맨틱에 가장 가까운 것이 많은 경우 가 있습니다.
SK-logic

@ SK-logic : "bigoted"라는 단어가 당신이 생각하는 것을 의미한다고 생각하지 않습니다.
키이스 톰슨

1
@Keith는 "자기 자신의 의견과 편견에 무관심하게 헌신했습니다"라고 말하며, 이것이 바로이 눈에 띄는 눈가리개로 만들어져 있습니다. " 항상 교체 해야 한다"는 최소한 광신자의 말이다. 적절하고 건전한 의견에 가까운 것은 아니지만 순수한 편견입니다. 이 "항상"은 다른 의견을위한 공간을 남겨 두지 않습니다.
SK-logic
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.