การใช้ goto คุ้มค่าไหม?


29

gotoเกือบจะท้อแท้ในระดับสากล การใช้คำสั่งนี้คุ้มค่าหรือไม่?



1
gotoซีพียูเป็นสิ่งที่ในที่สุดทำ แต่มันไม่ทำงานได้ดีกับสิ่งที่มนุษย์ต้องเข้าใจและเป็นนามธรรมเนื่องจากไม่มีเครื่องหมายที่ปลายเป้าหมาย เปรียบเทียบกับ COMEFROMINTERCAL

2
@ ThorbjørnRavnAndersenมนุษย์มีความหมายว่าอย่างไรเมื่อพวกเขากำลังพูดถึงการเปลี่ยนสถานะในเครื่องของรัฐ คุณไม่เห็นความคล้ายคลึงกันใช่ไหม "ไปยังสถานะที่กำหนด" นั่นคือความหมายและสิ่งอื่น ๆ จะเป็นอะไรนอกจากความยุ่งยากที่ไม่จำเป็นของสิ่งเล็กน้อย และคุณหมายถึงอะไรโดย "ไม่มีเครื่องหมาย"? ฉลากเป็นเครื่องหมาย
SK-logic

@ SK-logic ขึ้นอยู่กับว่าคุณจะอนุญาตให้ข้ามไปนานแค่ไหน เครื่องของรัฐไม่จำเป็นต้องใช้ข้ามไปใช้งาน

@ ThorbjørnRavnAndersenแน่นอนgotoไม่จำเป็นต้องใช้ มันเป็นวิธีที่มีเหตุผลมากที่สุดในการนำพวกเขาไปใช้ในภาษาที่จำเป็นเนื่องจากเป็นสิ่งที่ใกล้เคียงที่สุดกับความหมายของการเปลี่ยนสถานะ และปลายทางนั้นค่อนข้างไกลจากแหล่งที่มามันจะไม่ขัดขวางความสามารถในการอ่าน ตัวอย่างที่ชื่นชอบของรหัสนี้คือการนำเกมของ DE Knuth ไปใช้งาน
SK-logic

คำตอบ:


49

มีการพูดคุยกันหลายครั้งใน Stack Overflow และ Chris Gillum สรุปการใช้ที่เป็นไปได้ของgoto :

ออกจากฟังก์ชันอย่างหมดจด

บ่อยครั้งในฟังก์ชั่นคุณอาจจัดสรรทรัพยากรและจำเป็นต้องออกในหลาย ๆ ที่ โปรแกรมเมอร์สามารถลดความซับซ้อนของรหัสของพวกเขาโดยการใส่รหัสการล้างทรัพยากรในตอนท้ายของฟังก์ชั่นทั้งหมด "ออกคะแนน" ของฟังก์ชั่นจะได้รับฉลากการทำความสะอาด ด้วยวิธีนี้คุณไม่จำเป็นต้องเขียนโค้ดการล้างข้อมูลในทุก ๆ "จุดออก" ของฟังก์ชั่น

กำลังออกจากลูปซ้อนกัน

หากคุณอยู่ในลูปซ้อนกันและต้องการแยกลูปออกทั้งหมดลูปสามารถทำให้สิ่งนี้สะอาดและง่ายกว่าการใช้คำสั่ง break และ if-checks

การปรับปรุงประสิทธิภาพระดับต่ำ

นี่เป็นเพียงรหัสที่สมบูรณ์แบบ แต่คำสั่ง goto จะดำเนินการอย่างรวดเร็วและสามารถเพิ่มความสามารถให้คุณได้เมื่อเคลื่อนที่ผ่านฟังก์ชัน นี่เป็นดาบสองคมเนื่องจากคอมไพเลอร์โดยทั่วไปไม่สามารถปรับรหัสที่มี gotos ได้

ฉันจะเถียงเพราะคนอื่น ๆ จะเถียงว่าในทุกกรณีการใช้งานgotoนั้นถูกใช้เป็นเครื่องมือในการออกจากมุมหนึ่งที่เขียนรหัสตัวเองลงไป


28
ปัญหาแรกนั้นได้รับการแก้ไขอย่างเป็นระเบียบโดยfinallyบล็อกในภาษาสมัยใหม่และที่สองนั้นถูกแก้ไขโดยbreaks หากคุณติดอยู่กับ C อย่างไรก็ตามgotoมันเป็นวิธีเดียวที่จะแก้ปัญหาเหล่านี้ได้อย่างสวยงาม
Chinmay Kanchi

2
จุดที่ดีมาก ฉันชอบวิธีที่ Java อนุญาตให้แบ่งออกเป็นหลายระดับ
Casebash

4
@Chinmay - ในที่สุดบล็อกจะมีผลกับ 1) ภาษาสมัยใหม่ที่มีและ b) คุณสามารถทนต่อค่าใช้จ่าย (การจัดการข้อยกเว้นจะมีค่าใช้จ่าย) นั่นคือการใช้finallyจะใช้ได้ภายใต้เงื่อนไขเหล่านั้นเท่านั้น มีสถานการณ์ที่หายากมาก แต่ก็ใช้ได้จริงที่ goto เป็นหนทางที่จะไป
luis.espinal

21
คนเอาล่ะ ... ห่าคือความแตกต่างระหว่างbreak 3หรือและbreak myLabel goto myLabelโอ้นั่นเป็นเพียงคำหลักที่ถูกต้อง หากคุณกำลังใช้breakงานcontinueหรือมีคำหลักที่คล้ายกันคุณใช้ infact goto(หากคุณใช้for, while, foreach, do/loopคุณกำลังใช้ goto แบบมีเงื่อนไข)
Matthew Whited

4
เกี่ยวกับประสิทธิภาพในระดับต่ำ - พฤติกรรมของโปรเซสเซอร์ที่ทันสมัยอาจยากต่อการคาดการณ์ (ไปป์ไลน์การดำเนินการที่ไม่เป็นไปตามลำดับ) ดังนั้นอาจเป็น 99% ของกรณีที่ไม่คุ้มค่าหรืออาจช้าลง @MatthewWhited: การกำหนดขอบเขต หากคุณป้อนขอบเขตที่จุดใด ๆ ก็ไม่ชัดเจน (สำหรับคน) สิ่งที่ผู้สร้างควรจะเรียก (ปัญหามีอยู่ใน C เช่นกัน)
Maciej Piechotka

42

การสร้างโฟลว์การควบคุมระดับสูงกว่ามีแนวโน้มที่จะสอดคล้องกับแนวคิดในโดเมนปัญหา ถ้า / อื่นเป็นการตัดสินใจตามเงื่อนไขบางประการ วนบอกว่าจะดำเนินการบางอย่างซ้ำ ๆ แม้แต่ประโยคหยุดบอกว่า "เรากำลังทำสิ่งนี้ซ้ำ ๆ แต่ตอนนี้เราต้องหยุด"

ในทางตรงกันข้ามคำสั่ง goto มีแนวโน้มที่จะสอดคล้องกับแนวคิดในโปรแกรมที่กำลังทำงานไม่ใช่ในโดเมนปัญหา มันบอกว่าจะดำเนินการต่อการดำเนินการที่จุดที่ระบุไว้ในโปรแกรม บางคนที่อ่านโค้ดจะต้องอนุมานความหมายที่เกี่ยวข้องกับโดเมนปัญหา

แน่นอนว่าการสร้างระดับที่สูงขึ้นทั้งหมดสามารถกำหนดได้ในรูปของ gotos และสาขาที่มีเงื่อนไขแบบง่าย ไม่ได้หมายความว่าพวกเขาเป็นเพียงการปลอมแปลง คิดว่ามันเป็นgotos ที่ถูก จำกัด - และมันเป็นข้อ จำกัด ที่ทำให้พวกมันมีประโยชน์ คำสั่ง break ถูกนำไปใช้เป็นการข้ามไปยังจุดสิ้นสุดของลูปการล้อมรอบ แต่มันเป็นการดีกว่าที่จะใช้กับลูปโดยรวม

รหัสอื่นที่มีโครงสร้างเทียบเท่ากับโดเมนปัญหามีแนวโน้มที่จะอ่านและบำรุงรักษาได้ง่ายกว่า

ไม่มีกรณีที่จำเป็นต้องมีคำสั่ง goto อย่างแน่นอน (มีทฤษฎีบทเกี่ยวกับผลกระทบนั้น) แต่มีบางกรณีที่สามารถเป็นวิธีแก้ปัญหาที่แย่ที่สุดได้ กรณีเหล่านี้แตกต่างจากภาษาเป็นภาษาขึ้นอยู่กับสิ่งที่สร้างระดับสูงกว่ารองรับภาษา

ยกตัวอย่างเช่นใน C ฉันเชื่อว่ามีสามสถานการณ์พื้นฐานที่มีการข้ามไปเหมาะสม

  1. แยกออกจากวงซ้อนกัน สิ่งนี้จะไม่จำเป็นหากภาษานั้นมีคำสั่ง break
  2. การประกันตัวออกจากรหัส (โดยทั่วไปจะเป็นส่วนของฟังก์ชั่น) ในกรณีที่เกิดข้อผิดพลาดหรือเหตุการณ์ที่ไม่คาดคิดอื่น ๆ สิ่งนี้จะไม่จำเป็นหากภาษานั้นมีข้อยกเว้น
  3. การใช้เครื่องสถานะ จำกัด อย่างชัดเจน ในกรณีนี้ (และฉันคิดว่าเฉพาะในกรณีนี้) goto สอดคล้องกับแนวคิดโดยตรงในโดเมนปัญหาเปลี่ยนจากสถานะหนึ่งไปเป็นสถานะอื่นที่ระบุซึ่งสถานะปัจจุบันถูกแสดงโดยบล็อกของรหัสที่กำลังทำงานอยู่ .

ในอีกทางหนึ่งเครื่องสถานะ จำกัด ชัดเจนยังสามารถนำมาใช้กับคำสั่งเปลี่ยนภายในวง สิ่งนี้มีความได้เปรียบที่ทุกรัฐเริ่มต้นที่สถานที่เดียวกันในรหัสซึ่งสามารถเป็นประโยชน์สำหรับการดีบักตัวอย่างเช่น

การใช้งานหลักของ goto ในภาษาสมัยใหม่ที่สมเหตุสมผล (ภาษาที่รองรับหาก / else และ loops) คือการจำลองโครงสร้างโฟลว์การควบคุมที่ขาดหายไปจากภาษา


5
นี่เป็นคำตอบที่ดีที่สุดเท่าที่จะทำได้ - น่าประหลาดใจมากสำหรับคำถามที่มีอายุหนึ่งปีครึ่ง :-)
Konrad Rudolph

1
+1 ถึง "คำตอบที่ดีที่สุด" --- "การใช้งานหลักของ goto ในภาษาสมัยใหม่ที่สมเหตุสมผล (ภาษาที่รองรับถ้า / และลูป) คือการจำลองโครงสร้างการควบคุมการไหลที่ขาดหายไปจากภาษา"
Dave Dopson

gotoในเครื่องของรัฐสวิทช์คำสั่งการเขียนไปยังค่าการควบคุมทุกคนจริงๆ SSSM มักเป็นโครงสร้างที่ดีที่จะใช้เนื่องจากพวกเขาแยกรัฐ SM ออกจากโครงสร้างการดำเนินการ แต่พวกเขาไม่ได้กำจัด "gotos" จริงๆ
supercat

2
"ทุกอย่างเท่าเทียมกันรหัสที่โครงสร้างแสดงว่าโดเมนปัญหามีแนวโน้มที่จะอ่านและดูแลง่ายกว่า" ฉันรู้จักสิ่งนี้มานานแล้ว แต่ไม่มีคำพูดที่จะสื่อสารอย่างแม่นยำในแบบที่โปรแกรมเมอร์คนอื่นสามารถทำได้และจะเข้าใจได้จริง ขอบคุณสำหรับสิ่งนี้.
สัญลักษณ์แทน

"ทฤษฎีบทของโปรแกรมที่มีโครงสร้าง" ทำให้ฉันสนุกเพราะมันมีแนวโน้มที่จะแสดงให้เห็นอย่างชัดเจนว่าการใช้คำสั่งการเขียนโปรแกรมแบบมีโครงสร้างเพื่อเลียนแบบ goto นั้นสามารถอ่านได้น้อยกว่าการใช้ goto!

11

แน่นอนมันขึ้นอยู่กับภาษาการเขียนโปรแกรม เหตุผลหลักที่gotoมีการโต้เถียงเป็นเพราะผลกระทบที่ไม่ดีที่เกิดขึ้นเมื่อคอมไพเลอร์ช่วยให้คุณใช้มันอย่างอิสระเกินไป ตัวอย่างเช่นปัญหาอาจเกิดขึ้นได้หากมันช่วยให้คุณใช้gotoในลักษณะที่ตอนนี้คุณสามารถเข้าถึงตัวแปร uninitialised หรือแย่กว่านั้นเพื่อข้ามไปยังเมธอดอื่นและยุ่งกับ call stack มันควรจะเป็นความรับผิดชอบของคอมไพเลอร์ที่จะไม่อนุญาตการไหลของการควบคุมที่ไร้สาระ

Java ได้พยายาม“ แก้ไข” ปัญหานี้โดยไม่อนุญาตgotoทั้งหมด อย่างไรก็ตาม Java ช่วยให้คุณใช้returnภายในfinallyบล็อกและทำให้เกิดข้อยกเว้นเพื่อการกลืนโดยไม่ตั้งใจ ปัญหาเดียวกันยังคงมีอยู่: คอมไพเลอร์ไม่ทำงาน การลบออกgotoจากภาษายังไม่ได้รับการแก้ไข

ใน C #, gotoคือเป็นที่ปลอดภัยbreak, continue, และtry/catch/finally returnมันไม่อนุญาตให้คุณใช้ตัวแปรที่ไม่กำหนดค่าเริ่มต้นมันจะไม่ยอมให้คุณกระโดดออกจากบล็อกในที่สุด ฯลฯ คอมไพเลอร์จะบ่น นี่เป็นเพราะมันแก้ปัญหาที่แท้จริงซึ่งเป็นเหมือนที่ฉันบอกว่าการควบคุมการไหลไร้สาระ gotoไม่ได้ยกเลิกการวิเคราะห์ที่ได้รับมอบหมายอย่างชัดเจนและการตรวจสอบคอมไพเลอร์ที่สมเหตุสมผลอื่น ๆ อย่างน่าอัศจรรย์


ประเด็นของคุณคือ C # gotoไม่ใช่ความชั่วร้าย? ถ้าเป็นเช่นนั้นเป็นกรณีที่สำหรับทุกภาษาที่ทันสมัยใช้เป็นประจำด้วยการgotoสร้างไม่เพียง แต่ C # ...
lvella

9

ใช่. เมื่อลูปของคุณซ้อนกันหลายระดับลึกgotoเป็นวิธีเดียวที่จะหลุดออกจากวงในอย่างหรูหรา ตัวเลือกอื่นคือการตั้งค่าสถานะและแยกออกจากแต่ละวงถ้าธงนั้นเป็นไปตามเงื่อนไข นี่เป็นสิ่งที่น่าเกลียดมากและอาจเกิดข้อผิดพลาดได้ง่าย ในกรณีเหล่านี้gotoดีกว่า

แน่นอนว่าข้อความที่มีข้อความกำกับของ Java นั้นbreakทำสิ่งเดียวกัน แต่ไม่อนุญาตให้คุณข้ามไปยังจุดใดก็ได้ในรหัสซึ่งแก้ปัญหาได้อย่างเรียบร้อยโดยไม่ยอมให้สิ่งgotoชั่วร้าย


ใครสนใจอธิบายการลงคะแนนเสียง? นี่เป็นคำตอบที่ถูกต้องสมบูรณ์แบบสำหรับคำถาม ...
Chinmay Kanchi

4
ข้ามไปไม่ได้คำตอบที่สง่างาม เมื่อลูปของคุณซ้อนกันหลายระดับลึกปัญหาของคุณคือคุณไม่สามารถสร้างโค้ดของคุณเพื่อหลีกเลี่ยงการวนซ้ำแบบหลายเธรด ขั้นตอนการโทรไม่ใช่ศัตรู (อ่านเอกสาร "แลมบ์ดา: สุดยอด ... ") การใช้ goto เพื่อแยกวงลูปซ้อนกันหลายระดับความลึกคือการใส่วงช่วยเหลือลงบนรอยร้าวที่เปิดหลายครั้ง: มันอาจจะง่าย แต่ก็ไม่ถูกต้อง ตอบ.
John R. Strohm

6
และแน่นอนไม่มีกรณีแปลก ๆ เมื่อมีการเรียกใช้ลูปซ้อนกันอย่างล้ำลึกเพื่อ? การเป็นโปรแกรมเมอร์ที่ดีไม่เพียง แต่ทำตามกฎ แต่ยังเกี่ยวกับการรู้ว่าเมื่อไรที่จะทำลายมัน
Chinmay Kanchi

2
@ JohnR.Strohm ไม่เคยพูดไม่เคย หากคุณใช้คำอย่าง "ไม่เคย" ในการเขียนโปรแกรมคุณไม่ได้จัดการกับกรณีมุม, การเพิ่มประสิทธิภาพ, ข้อ จำกัด ด้านทรัพยากร, ฯลฯ อย่างชัดเจนในลูปที่ซ้อนกันอย่างลึกล้ำ, gotoเป็นวิธีที่สะอาดและสง่างามที่สุดในการออกจากลูป ไม่สำคัญว่าคุณได้ปรับเปลี่ยนรหัสของคุณเป็นจำนวนเท่าไร
Sujay Phadke

@ JohnR.Strohm: ฟีเจอร์ที่พลาดไปมากที่สุดอันดับสองในการเปลี่ยนจาก VB.NET เป็น C #: Doloop ทำไม? เพราะผมสามารถเปลี่ยนหนึ่งวงที่ต้องการแบ่งลึกเข้าไปในDoห่วงและพิมพ์และไม่มีExit Do GoToลูปซ้อนกันเกิดขึ้นตลอดเวลา การแตกสแต็กจะเกิดขึ้นบาง% ของเวลา
โยชูวา

7

ความท้อแท้ส่วนใหญ่เกิดขึ้นในรูปแบบของ "ศาสนา" ที่ได้รับการสร้างขึ้นมาโดยพระเจ้า Djikstra ซึ่งเป็นแรงบันดาลใจในช่วงต้นยุค 60 เกี่ยวกับพลังที่ไม่สามารถแยกแยะได้ดังนี้

  • กระโดดไปที่ใดก็ได้ในบล็อกของรหัส
    • ฟังก์ชั่นไม่ได้ดำเนินการจากจุดเริ่มต้น
    • ลูปไม่ถูกดำเนินการตั้งแต่ต้น
    • ข้ามการเริ่มต้นตัวแปร
  • กระโดดจากบล็อกรหัสใด ๆ โดยไม่ต้องล้างข้อมูลใด ๆ

สิ่งนี้ไม่มีอะไรเกี่ยวข้องกับgotoคำแถลงของภาษาสมัยใหม่ซึ่งมีอยู่เพียงเพื่อสนับสนุนการสร้างโครงสร้างรหัสอื่น ๆ นอกเหนือจากภาษาที่ให้ไว้

โดยเฉพาะอย่างยิ่งจุดหลักแรกด้านบนได้รับอนุญาตอีกต่อไปและที่สองคือการทำความสะอาด (ถ้าคุณgotoออกจากบล็อกกองจะผ่อนคลายอย่างถูกต้องและ destructors ที่เหมาะสมทั้งหมดที่เรียกว่า)

คุณสามารถอ้างถึงคำตอบนี้เพื่อให้ทราบว่าแม้แต่โค้ดที่ไม่ได้ใช้ goto สามารถอ่านไม่ได้ ปัญหาไม่ได้เป็นของตัวเอง แต่ใช้ไม่ได้ผล

ฉันสามารถเขียนโปรแกรมทั้งหมดโดยไม่ต้องใช้เพียงif forแน่นอนว่ามันจะไม่สามารถอ่านได้ดีมีลักษณะเงอะงะและซับซ้อนโดยไม่จำเป็น

forแต่ปัญหาก็คือไม่ได้ ฉันเอง.

สิ่งที่ชอบbreak, continue, throw, bool needed=true; while(needed) {...}ฯลฯ จะสังเกตมากกว่าสวมหน้ากาก gotoที่จะหลบหนีออกไปจากดาบของหัวรุนแรง Djikstrarian ที่ -50 ปีหลังจากการประดิษฐ์ของ laguages- สมัยใหม่ยังคงต้องการที่นักโทษของพวกเขา พวกเขาลืมสิ่งที่ Djikstra พูดถึงพวกเขาจำได้แค่ชื่อโน้ตของเขาเท่านั้น (GOTO ถือว่าเป็นอันตรายและไม่ใช่แม้แต่ชื่อของเขา: มันเปลี่ยนโดยบรรณาธิการ) และตำหนิและทุบตีทุบตีและตำหนิทุกโครงสร้างที่มี 4 ตัวอักษรเรียงตามลำดับ

ถึงปี 2011: ถึงเวลาที่จะเข้าใจว่าgotoการไม่ปฏิบัติตามGOTOคำแถลง Djikstra นั้นเป็นเรื่องที่น่าสนใจ


1
"สิ่งต่าง ๆ เช่นหยุดพักดำเนินการโยนบูลต้องการ = จริงในขณะที่ (จำเป็น) {... } ฯลฯ ไม่เห็นมากกว่าหน้ากากปลอมเลย" ฉันไม่เห็นด้วย ฉันต้องการ "สิ่งต่าง ๆ เช่น break etc ถูกจำกัด goto" หรืออะไรทำนองนั้น ปัญหาหลักของ goto คือมันมักจะทรงพลังเกินไป เท่าที่ข้ามไปปัจจุบันมีพลังน้อยกว่าของ Dijkstra คำตอบของคุณใช้ได้กับฉัน
มูฮัมหมัดอัลคาริ

2
@ MuhammadAlkarouri: ฉันเห็นด้วยอย่างยิ่ง คุณเพิ่งพบถ้อยคำที่ดีกว่าเพื่อแสดงแนวคิดของฉันอย่างแท้จริง ประเด็นของฉันคือข้อ จำกัด เหล่านั้นบางครั้งอาจไม่สามารถใช้ได้และประเภทของข้อ จำกัด ที่คุณต้องการไม่ได้อยู่ในภาษา จากนั้นสิ่งที่ "มีประสิทธิภาพ" มากขึ้นมีความเชี่ยวชาญน้อยกว่าคือสิ่งที่ทำให้คุณสามารถแก้ไขปัญหาได้ ตัวอย่างเช่น Java break nไม่พร้อมใช้งานใน C ++ ดังนั้นgoto escapeแม้ว่าescapeไม่จำเป็นต้องออกจากลูป n-ple
Emilio Garavaglia

4

goto แปลก ๆ ที่นี่หรือที่นั่นตราบใดที่มันมีฟังก์ชั่นในท้องถิ่น มันมักจะได้รับประโยชน์จากการดึงความสนใจไปที่ความจริงที่ว่ามีบางสิ่งผิดปกติเกิดขึ้นในรหัสนี้ซึ่งจำเป็นต้องใช้โครงสร้างการควบคุมที่ค่อนข้างแปลก

ถ้า gotos (ในพื้นที่) เป็นอันตรายต่อความสามารถในการอ่านอย่างมีนัยสำคัญโดยทั่วไปแล้วมันเป็นสัญญาณว่าฟังก์ชั่นที่มี goto นั้นซับซ้อนเกินไป

การข้ามไปครั้งสุดท้ายที่ฉันใส่ลงไปในรหัส C คือการสร้างลูปที่เชื่อมต่อกัน มันไม่พอดีกับคำจำกัดความปกติของการใช้ข้ามไป "ยอมรับ" แต่ฟังก์ชั่นสิ้นสุดลงมีขนาดเล็กลงและชัดเจนขึ้น เพื่อหลีกเลี่ยงการข้ามไปนั้นจะต้องมีการละเมิดยุ่งโดยเฉพาะอย่างยิ่งของ DRY


1
คำตอบสำหรับคำถามนี้มีสาระสำคัญที่สุดในสโลแกน "Lay's Potato Chips" ที่เก่าแก่ที่สุด: "พนันได้เลยว่าคุณไม่สามารถกินได้เพียงคนเดียว" ในตัวอย่างของคุณคุณมี "การประสาน" สองอย่าง (นั่นหมายถึงอะไรและฉันเดิมพันว่ามันไม่สวย) ลูปและการข้ามไปก็ทำให้คุณได้ราคาถูก แล้วผู้ชายบำรุงรักษาใครจะต้องแก้ไขโค้ดนั้นหลังจากที่คุณถูกรถบัสชน? ไปที่จะทำให้ชีวิตของเขาง่ายขึ้นหรือยากขึ้น? ลูปทั้งสองนั้นจำเป็นต้องคิดใหม่หรือไม่?
John R. Strohm

3

ฉันคิดว่าปัญหาทั้งหมดนี้เป็นกรณีของการเห่าต้นไม้ผิด

GOTO เช่นนั้นดูเหมือนจะไม่เป็นปัญหาสำหรับฉัน แต่มันมักจะเป็นอาการของบาปจริง: รหัสสปาเก็ตตี้

ถ้า GOTO เป็นสาเหตุให้เกิดการข้ามสายควบคุมการไหลสำคัญก็ถือว่าไม่ดีระยะเวลา ถ้ามันข้ามไม่มีเส้นควบคุมการไหลมันไม่เป็นอันตราย ในเขตสีเทาในระหว่างที่เรามีสิ่งต่าง ๆ เช่นวน bailouts ยังมีบางภาษาที่ยังไม่ได้เพิ่มโครงสร้างที่ครอบคลุมทุกกรณีสีเทาที่ถูกต้อง

กรณีเดียวที่ฉันพบว่าตัวเองใช้งานจริงในหลายปีคือกรณีของลูปที่จุดตัดสินใจอยู่ตรงกลางของลูป คุณจะเหลือรหัสที่ซ้ำกันทั้งธงหรือ GOTO ฉันพบทางออกที่ดีที่สุดของสาม GOTO ไม่มีการข้ามเส้นควบคุมที่นี่มันไม่เป็นอันตราย


กรณีที่คุณพาดพิงถึงบางครั้งขนานนามว่า "วนครึ่งหนึ่ง" หรือ "N บวกหนึ่งครึ่งวน" และมันเป็นกรณีการใช้งานที่มีชื่อเสียงสำหรับgotos ที่กระโดดลงในลูป (ถ้าภาษาอนุญาตสิ่งนี้; ออกจากห่วงตรงกลางมักจะไม่สำคัญgoto)
Konrad Rudolph

(อนิจจาภาษาส่วนใหญ่ห้ามกระโดดเป็นวง)
Konrad Rudolph

@KonradRudolph: หากคุณใช้ "loop" กับ GOTO จะไม่มีโครงสร้างวนรอบอื่น ๆ ที่จะข้ามไป
Loren Pechtel

1
ผมคิดว่าgotoเป็นตะโกนการควบคุมการไหลที่นี่ไม่เหมาะกับรูปแบบปกติมีโครงสร้างการเขียนโปรแกรม เนื่องจากการควบคุมการไหลที่เหมาะสมกับรูปแบบการเขียนโปรแกรมที่มีโครงสร้างจะให้เหตุผลได้ง่ายกว่าสิ่งที่ไม่เหมาะสมดังนั้นจึงควรใช้รูปแบบดังกล่าวเมื่อเป็นไปได้ หากรหัสเหมาะสมกับรูปแบบดังกล่าวเราไม่ควรตะโกนว่ามันไม่เป็นเช่นนั้น ในทางกลับกันในกรณีที่รหัสไม่เหมาะกับรูปแบบดังกล่าวการตะโกนเกี่ยวกับมันอาจจะดีกว่าการทำเป็นรหัสที่เหมาะสมเมื่อมันไม่จริง
supercat

1

ใช่ goto สามารถใช้เพื่อให้ได้รับประโยชน์จากประสบการณ์ของผู้พัฒนา: http://adamjonrichardson.com/2012/02/06/long-live-the-goto-statement/

อย่างไรก็ตามเช่นเดียวกับเครื่องมืออันทรงพลังใด ๆ (พอยน์เตอร์การสืบทอดหลาย ๆ แบบ) ต้องมีระเบียบวินัยในการใช้งาน ตัวอย่างที่มีให้ในลิงค์ใช้ PHP ซึ่ง จำกัด การใช้ goto construct ให้เป็นฟังก์ชัน / วิธีการเดียวกันและปิดการใช้งานความสามารถในการข้ามไปยังบล็อกควบคุมใหม่ (เช่นวนรอบคำสั่งสลับ ฯลฯ )


1

ขึ้นอยู่กับภาษา มันยังคงใช้กันอย่างแพร่หลายในการเขียนโปรแกรม Cobol เช่น ฉันยังทำงานกับอุปกรณ์ Barionet 50 ซึ่งภาษาการเขียนโปรแกรมเฟิร์มแวร์เป็นภาษาเบสิกพื้นฐานที่แน่นอนว่าคุณต้องใช้ Goto


0

ฉันจะบอกว่าไม่มี หากคุณพบว่าจำเป็นต้องใช้ GOTO ฉันจะเดิมพันว่ามีความจำเป็นต้องออกแบบรหัสใหม่


3
บางที แต่คุณยังไม่ได้ให้เหตุผลใด ๆ
Casebash

Dijkstra ให้เหตุผลโดยละเอียดหลายทศวรรษมาแล้ว
John R. Strohm

2
แค่เชื่อ ไม่มีการ resons หมายเหตุ: Djikstra ไม่ใช่คำตอบที่ถูกต้องอีกต่อไป: มันเป็นการอ้างถึงคำสั่ง BASIC หรือ FORTRAN GOTO ของช่วงต้นยุค 60 พวกเขาไม่มีอะไรเกี่ยวข้องกับโรคโลหิตจาง (เทียบกับพลังของพวกมัน) gots-s ในปัจจุบัน
Emilio Garavaglia

0

gotoอาจมีประโยชน์เมื่อทำการย้ายรหัสแอสเซมเบลอร์ดั้งเดิมเป็น C ในตัวอย่างแรกการแปลงคำสั่งโดยคำสั่งเป็น C โดยใช้gotoแทนbranchคำสั่งของแอสเซมเบลอร์สามารถเปิดใช้งานการพอร์ตได้อย่างรวดเร็วมาก


-1

ฉันจะเถียงไม่ พวกเขาควรจะถูกแทนที่ด้วยเครื่องมือที่เฉพาะเจาะจงมากขึ้นกับปัญหาที่ goto ถูกใช้เพื่อแก้ปัญหา (เว้นแต่ว่ามันจะไม่สามารถใช้ได้ในภาษาของคุณ) ตัวอย่างเช่นตัวแบ่งงบและข้อยกเว้นแก้ปัญหาก่อนหน้าแก้ปัญหาของการหลบหนีวนและการจัดการข้อผิดพลาด


ฉันขอยืนยันว่าเมื่อภาษามีคุณสมบัติทั้งสองนี้gotoโดยทั่วไปแล้วจะขาดไปจากภาษาเหล่านั้น
Chinmay Kanchi

แต่นั่นเป็นเพราะพวกเขาไม่ต้องการพวกเขาหรือเพราะคนคิดว่าพวกเขาไม่ต้องการพวกเขา?
Michael K

มุมมองของคุณมีขนาดใหญ่ มีหลายกรณีgotoที่สิ่งที่ใกล้เคียงกับซีแมนทิกส์ของโดเมนที่มีปัญหามากที่สุดคืออะไรก็ตามที่เป็นแฮ็คที่สกปรก
SK-logic

@ SK-logic: ฉันไม่คิดว่าคำว่า "bigoted" หมายถึงสิ่งที่คุณคิดว่ามันหมายถึง
Keith Thompson

1
@ Keith "ทุ่มเทอย่างมากกับความคิดเห็นและอคติของเขาหรือเธอ" - นั่นคือสิ่งที่ฉันสังเกตเห็นอย่างสม่ำเสมอที่นี่ด้วยการปิดตาแบบนี้มากมาย "ควรจะถูกแทนที่" เป็นคำพูดที่คลั่งไคล้อย่างน้อย ไม่มีอะไรใกล้เคียงกับความเห็นที่เหมาะสม แต่เป็นความดื้อรั้นที่บริสุทธิ์ "เสมอ" นี้ไม่ได้เว้นที่ว่างสำหรับความคิดเห็นทางเลือกใด ๆ ดู?
SK-logic
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.