Go'nun neden "git" ifadesi var?


110

Go'nun bir 'git' ifadesine sahip olduğunu görünce şaşırdım . Bana her zaman 'goto' ifadelerinin geçmişte kaldığı ve bir programın gerçek akışını tıkadığı için kötü olduğu ve işlevlerin veya yöntemlerin akışı kontrol etmenin daha iyi bir yolu olduğu öğretildi.

Bir şey kaçırıyor olmalıyım. Google bunu neden dahil etti?


5
Bir goto ifadesine gerçekten ihtiyaç duyduğunuz zamanlar vardır. Goto'lar yalnızca ayrım gözetmeden kullanıldığında kötüdür. Örneğin, bir Sonlu durum makinesi ayrıştırıcısı yazmak çok zorsa, imkansız değilse, ifadelere gitmeden.
xbonez

5
Go'ya özgü değil, ancak dillerin neden bu ifadeyi koruduğuna dair iyi bir tartışma ve kullanımına karşı argümanlar görmek için bu gönderiye göz atın . Soruda bağlantılı bazı iyi referanslar var. Düzenleme: işte başka .
Cᴏʀʏ

3
Sağlanan SO tartışmalar yoluyla grepping gelen OP kaydetmek için, burada LKML tartışması hoş çok özetliyor neden gotobazı durumlarda yararlıdır. @ Kissaki'nin cevabını inceledikten sonra okuyun.
kostix


Yığını kaydettikten sonra devam etmek istediğinizde bulunduğunuz yere geri döndüğünüz bir devam modeli uygulamak faydalıdır.
Justin Dennahower

Yanıtlar:


78

Go standart kitaplığının kaynak kodunu gerçekten kontrol ettiğimizde, URL'lerin gotogerçekte iyi uygulandığını görebiliriz.

Örneğin, math/gamma.godosyanın, deyim kullanılan olduğunu :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)
}

gotoBu durumda sonunda kontrol sadece kontrol akışı için kullanılan başka bir (boolean) değişken tanıtan bizi kurtarır. Bu durumda , gotoifade, kodu gerçekten daha iyi okumayı ve takip etmeyi kolaylaştırır ( gotobahsettiğiniz karşı argümanın tam tersine ).

Ayrıca, gotoifadenin çok özel bir kullanım durumu olduğuna dikkat edin . Goto dil belirtimi kapsam içine gelen değişkenler üzerinden atlama olmayabilir devletler (ilan edilen) ve diğer (Kodunuzu) bloklar halinde atlama olmayabilir.


69
Örneğinizde, neden small(x,z)bunun yerine çağırmak için bir işlev tanıtmıyorsunuz? Bu şekilde, small:etikette hangi değişkenlerin erişilebilir olduğunu düşünmemize gerek kalmaz . Bunun nedeninin hala derleyicide belirli türde inlining desteğinden yoksun olduğundan şüpheleniyorum.
Thomas Ahle

5
@Jessta: Görünürlük ve kapsamımız bunun için değil mi?
Thomas Ahle

6
@ThomasAhle Go, gotoyeni değişkenler tanıtıldıktan sonra bir etiketi göstermeye izin vermiyor . "Goto" ifadesinin yürütülmesi, goto noktasında kapsamda olmayan herhangi bir değişkenin kapsama girmesine neden olmamalıdır.
km6zla

4
@ ogc-nick Üzgünüm net değildim, işlevlerin ihtiyaç duyulduğu yerde bildirilebileceğini kastettim, böylece onlara ihtiyaç duymayan kodlar tarafından görünmezler. Goto'dan ve kapsamdan bahsetmiyordum.
Thomas Ahle

4
@MosheRevah Başvurulan kod okunabilirlik için optimize edilmemiştir. Tek bir işlevde 22 satıra yayılan bir goto kullanılarak ham performans için optimize edilmiştir. (Ve Thomas Ahle'nin teklifi gözüme daha da okunabilir.)
joel.neely

30

Goto, yerleşik kontrol özelliklerinden hiçbiri istediğinizi tam olarak yapmadığında ve istediğinizi bir goto ile ifade edebildiğinizde iyi bir fikirdir. (Bu durumlarda, bazı dillerde bir gitmediğinizde utanç vericidir. Sonunda bazı kontrol özelliklerini kötüye kullanırsınız, boole bayrakları kullanırsınız veya gitmekten daha kötü başka çözümler kullanırsınız.)

Eğer başka bir kontrol özelliği (oldukça açık bir şekilde kullanılırsa) istediğinizi yapabiliyorsa, gitmeyi tercih ederek onu kullanmalısınız. Değilse, cesur olun ve goto kullanın!

Son olarak, Go'nun goto'sunun bazı belirsiz hatalardan kaçınmak için tasarlanmış bazı kısıtlamalara sahip olduğunu belirtmek gerekir. Spesifikasyondaki bu kısıtlamalara bakın .


7

Goto ifadeleri, 60'lı ve 70'li yıllarda Spagetti kodu çağından bu yana çok fazla itibar kaybetti. O zamanlar yazılım geliştirme metodolojisi çok zayıftı ya da hiç yoktu. Bununla birlikte, Goto doğal olarak kötü değildir, ancak elbette tembel veya vasıfsız programcılar tarafından kötüye kullanılabilir ve istismar edilebilir. Kötüye kullanılan Gotos ile ilgili birçok sorun, ekip kodu incelemeleri gibi geliştirme süreçleriyle çözülebilir.

gotoaynı teknik şekilde atlar continue, breakve return. Bunların aynı şekilde kötü ifadeler olduğu iddia edilebilir, ancak bunlar değildir.

Go ekibi neden Gotos'u dahil etti, muhtemelen bunun ortak bir akış kontrolü ilkeli olduğu gerçeğidir. Ek olarak, umarız ki Go'nun kapsamının, kötüye kullanımın mümkün olmadığı aptalca güvenli bir dili dışladığı sonucuna varmışlardır.


continue, breakve returnözellikle bir anahtar açısından çok farklıdır: yalnızca "çevreleyen kapsamdan ayrıl" seçeneğini belirtirler. Sadece teşvik etmekle kalmaz, aynı zamanda geliştiricinin kodlarının yapısını dikkate almasını ve yapısal programlama ilkelerine (döngüler, işlevler ve anahtar ifadeleri için) güvenmesini gerektirir . gotoİfadelerin bir ve tek tasarruf zarafeti , derleyicinin optimize edicisi göreve bağlı olmadığında bir HLL'ye montaj yazmanıza izin vermeleridir, ancak bu okunabilirlik ve sürdürülebilirlik pahasına gelir.
Parthian Shot

Bu yüzden seferde bulmak için şaşırtıcı olmasının sebebi, golang geliştiricileri yapısal programlama paradigması ve "istisnai akış kontrolü" arasında bir seçim vardı her durumda / talimat işaretçi manipülasyonları gibi yani setjmp, longjmp, goto, ve try / except / finallyonlar tarafında err seçti Dikkatli olun. goto, fwict, önceden "yapılandırılmış programlama" kontrol akışının tek rızasıdır.
Parthian Shot
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.