Go에 "goto"문이있는 이유


110

Go에 'goto' 문 이 있다는 사실에 놀랐습니다 . 저는 항상 'goto'문이 과거의 일이며 프로그램의 실제 흐름을 막고 함수 나 방법이 흐름을 제어하는 ​​더 나은 방법이라는 점을 항상 배웠습니다.

뭔가 빠졌 나봐요. Google이이를 포함시킨 이유는 무엇입니까?


5
goto 문이 정말로 필요한 경우가 있습니다. 고토는 무차별 적으로 사용될 때만 악합니다. 예를 들어, 불가능하지는 않더라도 goto 문을 사용하여 유한 상태 머신 파서를 작성하는 것이 매우 어렵다면.
xbonez

5
Go에만 국한된 것은 아니지만, 언어가 성명을 유지하는 이유에 대한 좋은 토론과 사용에 대한 논쟁을 보려면 이 게시물을 확인하십시오 . 질문에 연결된 좋은 참조가 있습니다. 편집 : 여기에 또 다른 .
Cᴏʀʏ 2012-06-16

3
제공된 SO 토론을 통해 OP를 모으는 것을 방지하기 위해 LKML에 대한 토론 이 있습니다. 이 토론goto 은 특정 경우에 유용한 이유를 거의 요약합니다 . @Kissaki의 대답을 공부 한 후 읽으십시오.
kostix


연속 패턴을 구현하는 데 유용합니다. 여기서 스택을 저장 한 다음 다시 시작하려는 위치로 돌아갑니다.
Justin Dennahower

답변:


78

실제로 Go 표준 라이브러리의 소스 코드를 확인하면 gotos가 실제로 잘 적용된 위치를 확인할 수 있습니다 .

예를 들어, math/gamma.go파일에서 다음 goto명령문이 사용됩니다 .

  for x < 0 {
    if x > -1e-09 {
      goto small
    }
    z = z / x
    x = x + 1
  }
  for x < 2 {
    if x < 1e-09 {
      goto small
    }
    z = z / x
    x = x + 1
  }

  if x == 2 {
    return z
  }

  x = x - 2
  p = (((((x*_gamP[0]+_gamP[1])*x+_gamP[2])*x+_gamP[3])*x+_gamP[4])*x+_gamP[5])*x + _gamP[6]
  q = ((((((x*_gamQ[0]+_gamQ[1])*x+_gamQ[2])*x+_gamQ[3])*x+_gamQ[4])*x+_gamQ[5])*x+_gamQ[6])*x + _gamQ[7]
  return z * p / q

small:
  if x == 0 {
    return Inf(1)
  }
  return z / ((1 + Euler*x) * x)
}

goto이 경우는 마지막 검사 단지 제어 흐름을 위해 사용되는 또 다른 (부울) 변수를 도입 우리를 저장한다. 이 경우 , goto문장은 실제로 코드를 더 읽기 쉽고 따라 가기 쉽게 만듭니다 ( goto당신이 언급 한 반대 주장과는 반대로 ).

또한이 goto명령문에는 매우 구체적인 사용 사례가 있습니다. goto언어 사양에 따르면 범위 (선언중인)로 들어오는 변수를 건너 뛸 수 없으며 다른 (코드) 블록으로 건너 뛸 수 없습니다.


69
귀하의 예에서 small(x,z)대신 호출 할 함수 를 소개하지 않는 이유는 무엇입니까? 이렇게하면 small:레이블 에서 액세스 할 수있는 변수에 대해 생각할 필요가 없습니다 . 이유는 go가 여전히 컴파일러에서 특정 유형의 인라인 지원이 부족하기 때문이라고 생각합니다.
Thomas Ahle 2013-06-02

5
@Jessta : 그것이 우리가 가시성과 범위를 가지고있는 것입니다.
Thomas Ahle 2014

6
@ThomasAhle Go는 goto새 변수가 도입 된 후 레이블을 가리킬 수 없습니다 . "goto"문을 실행하면 goto 지점에서 범위에 있지 않은 변수가 범위에 포함되지 않아야합니다.
km6zla 2014 년

4
@ ogc-nick 죄송합니다. 명확하지 않았습니다. 필요한 범위에서 함수를 선언 할 수 있으므로 필요하지 않은 코드에는 표시되지 않습니다. 나는 고토와 스코프에 대해 말하는 것이 아닙니다.
Thomas Ahle 2014 년

4
@MosheRevah 참조 된 코드는 가독성을 위해 최적화되지 않았습니다. 단일 함수 내에서 22 줄에 걸쳐있는 goto를 사용하여 원시 성능에 최적화되어 있습니다. (그리고 토마스 Ahle의 제안은 훨씬 더 읽기 내 눈입니다.)
joel.neely

30

Goto는 내장 된 제어 기능 중 어느 것도 원하는 기능을 수행하지 않는 경우와 goto로 원하는 것을 표현할 수있는 경우 좋은 생각입니다. (이 경우 일부 언어에서 goto가없는 경우 부끄러운 일입니다. 일부 제어 기능을 남용하거나 부울 플래그를 사용하거나 goto보다 더 나쁜 다른 솔루션을 사용하게됩니다.)

다른 제어 기능 (합리적으로 분명한 방식으로 사용됨)이 원하는 작업을 수행 할 수있는 경우 goto보다 우선적으로 사용해야합니다. 그렇지 않다면 대담하게 고토를 사용하세요!

마지막으로 Go의 goto에는 모호한 버그를 방지하기 위해 설계된 몇 가지 제한 사항이 있습니다. 사양 에서 이러한 제한 사항을 참조하십시오 .


7

Goto 진술은 60 년대와 70 년대 스파게티 코드 시대 이후 많은 불신을 받았습니다 . 당시에는 소프트웨어 개발 방법론이 매우 열악했습니다. 그러나 Goto는 본질적으로 악하지는 않지만 게 으르거나 숙련되지 않은 프로그래머에 의해 오용되고 남용 될 수 있습니다. 악용 된 Gotos의 많은 문제는 팀 코드 검토와 같은 개발 프로세스를 통해 해결할 수 있습니다.

gotocontinue, break및과 같은 기술적 방식으로 점프합니다 return. 이것들은 같은 방식으로 악한 진술이라고 주장 할 수 있지만 그렇지 않습니다.

Go 팀에 Gotos가 포함 된 이유는 아마도 이것이 일반적인 흐름 제어 기본 요소이기 때문일 것입니다. 또한 그들은 Go의 범위가 바보에게 안전한 언어를 남용 할 수 없도록 만드는 것을 배제한다는 결론을 내 렸습니다.


continue, break,와 return매우 다른 하나의 키 특정 : 그들은 단지 지정 "바깥 쪽 범위를두고". 개발자가 코드 구조를 고려하고 구조화 된 프로그래밍 기본 요소 (루프, 함수 및 switch 문)에 의존하도록 권장 할뿐만 아니라 명시 적으로 요구합니다 . goto명령문의 유일한 장점은 컴파일러의 옵티마이 저가 작업에 맞지 않을 때 HLL에서 어셈블리를 작성할 수 있다는 것 입니다 . 그러나 이것은 가독성과 유지 보수성을 희생해야합니다.
Parthian Shot 19

이 때문에 이동에서 찾을 놀라운 이유는 golang 개발자가 구조화 프로그래밍 패러다임과 "뛰어난 흐름 제어"사이에 선택의 여지가 다른 모든 경우에 / 명령 포인터 조작 좋아하는이다 setjmp, longjmp, goto, 그리고 try / except / finally그들이 치우쳐 선택 주의. goto, fwict는 사전 "구조화 된 프로그래밍"제어 흐름에 대한 유일한 수용자입니다.
Parthian Shot
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.