Zen of Go

Yıllar önce, Python'un çekirdek geliştiricilerinden biri olan Tim Peter tarafından yazılan "The Zen of Python", Python programlama ve tasarımının ana ilkesi haline geldi.

Go diline açık kaynak katkısı olan ve proje üyelerinden biri olarak, bu makalenin yazarı Python'un Zen konusuna odaklanacak ve anladığı şekliyle Go dilinin "Zen" ini önerecek ve "Go dilinin başarısının büyük ölçüde nedeninin Hatalarla başa çıkmanın açık bir yolu ", neden bunu söylüyor? Gelin birlikte bir göz atalım.

Yazar | Dave Cheney, açık kaynak katılımcısı ve Go dilinin proje üyesi

Çevirmen | Sun Wei, sorumlu editör | Wu Xingling

Üretildi | CSDN (ID: CSDNnews)

Aşağıdaki çeviridir:

Son zamanlarda sık sık şu soruyu düşünüyorum: iyi kod nasıl yazılır? Hiç kimsenin aktif olarak kötü kod yazmaya çalışmadığını varsayarsak, şu soru ortaya çıkar: Şu anda yazdığımızın iyi Go kodu olduğunu nasıl anlarız?

İyi kod ile kötü kod arasında süreklilik varsa, iyi kısım nasıl ayırt edilir? Nitelikleri, özellikleri, işaretleri, modelleri ve deyimleri nelerdir?

Go hakkında

Deyimler git

Bu bizi Go'nun deyimlerine - dönemin tarzını izleyerek onların gramerine atıfta bulunan sözde deyimlere götürür. Deyimler olmayanlar popüler stilleri takip etmez ve modaya uygun değildir.

Daha da önemlisi: Kimin kodunun deyime uymadığını söylemek, neden bir deyim olmadığını açıklamaz. Nedeni ne? Tüm gerçekler gibi, cevap da sözlükte bulunabilir.

Deyim: Anlamı kullanımla belirlenen ve anlamı tek bir kelimenin anlamından çıkarılamayan bir grup kelime.

Deyimler paylaşılan değerlerin işaretleridir. Go deyimleri kitaplardan öğrendiğimiz şeyler değildir, ancak Go topluluğuna katılarak öğreniriz.

Gonun deyim kurallarına odaklandığım şey, çoğu durumda deyimler özeldir. Başka bir deyişle, "ikisine birden sahip olamazsınız." Sonuçta, birinin çalışmasını bir deyime uymadığı için eleştirirken, bunu kastetmiyor muyuz? Hatalar yaptılar, sorunlu görünüyorlardı ve zamanın tarzına uymuyorlardı.

Go deyimlerinin mükemmel Go kodu yazmayı öğretmede uygun bir mekanizma olmadığını önermemin nedeni, deyimlerin özünde, diğer tarafa bir hata yaptıklarını söylemek için iyi tanımlanmış şeyler olmalarıdır. Verdiğimiz tavsiye, kod yazarlarının fikirleri kabul etmeye ve onları rahatsız hissettirmeye en istekli olduğu düğümde olmasaydı daha iyi olmaz mıydı?

atasözü

Sorunlu deyimler dışında, Go uzmanlarının başka hangi kültürel alışkanlıkları var? Belki Rob Pikeın harika Go atasözlerinden bahsedebiliriz. Bunlar uygun öğretim araçları mı? Yeni başlayanlara nasıl iyi Go kodu yazacaklarını söyleyebilir misiniz?

Genel olarak, önemli olduğunu sanmıyorum. Pike'ı çürütmek değil, sadece Segoe Kensaku'nun orijinal çalışması gibi Go atasözlerine hitap etmek Bu bir değer ifadesi değil, bir gözlemdir.

Go atasözlerinin amacı, dil tasarımıyla ilgili derin gerçeği ortaya çıkarmaktır, ancak yapılandırılmış türler içermeyen bir programlama dili için boş arayüzler gibi öneriler, acemiler bundan ne kadar yararlanabilir?

Büyüyen bir toplulukta, herhangi bir zamanda Go dilini öğrenenlerin, dile hakim olduğunu iddia edenlerden çok daha fazla sayıda insanın olduğunu fark etmek önemlidir, bu nedenle bu durumda, atasözleri en iyi öğretim aracı olmayabilir.

Mühendislik değeri

Dan Luu, Mark Lucovsky'nin Windows ekibinden Windows NT ve Windows 2000 arasında mühendislik kültürü üzerine bir konuşma keşfetti. Lukovsky'nin kültürü, tasarımı değerlendirmek ve ödünleşimleri tartmak için ortak bir yöntem olarak tanımlaması nedeniyle bahsediliyor.

Kültürü tartışmanın birçok yolu var, ancak mühendislik kültürü açısından Lucovsky'nin açıklaması çok uygun. Ana fikir, bilinmeyen bir tasarım alanında karar vermeye rehberlik etmek için değeri kullanmaktır. NT ekibinin değerleri şunlardır: taşınabilirlik, güvenilirlik, güvenlik ve ölçeklenebilirlik. Mühendislik değerinin kaba bir çevirisi, işin yapılma şeklidir.

Go'nun değerleri

Go dilinin net değerleri nelerdir? Go programcılarının dünyayı yorumlama şekli nasıl tanımlanır ve temel inançları veya felsefeleri nedir? Nasıl yayınlanır, nasıl öğretilir, nasıl uygulanır, zaman içinde nasıl değiştirilir?

Go'da yeni bir programcı olarak, Go'nun mühendislik değerini nasıl aşılayacaksınız? Ya da deneyimli bir Go dili uzmanıysanız, değerlerinizi gelecek nesillere nasıl aktarırsınız? Bu nedenle, bilgi aktarım sürecinin isteğe bağlı olmadığı konusunda çok netiz.Kan ve yeni fikirler olmadan, topluluğumuz dar görüşlü hale gelecektir.

Diğer dillerdeki değerler

Sahneyi bunu anlayacak şekilde ayarlamak için diğer dillere bakabilir ve mühendislik değerlerini anlayabiliriz.

Örneğin: C ++ (ve alternatif Rust), programcıların kullanmadıkları işlevler için ödeme yapmak zorunda olmadığına inanır. Bir program dilin çok fazla hesaplama gerektiren belirli işlevlerini kullanmıyorsa, program bu işlevin maliyetini karşılamaya zorlanmamalıdır. Bu değer, dilden standart kitaplığına kadar uzanır ve C ++ ile yazılmış tüm kodların tasarımını değerlendirmek için bir standart olarak kullanılır.

Java, Ruby ve Smalltalk'ta her şey, mesaj geçişi, bilgi gizleme ve polimorfizm programlama sürecini yönlendiren nesnenin temel değeridir. Halk, bu dillerin tasarımına yordamsal stilleri ve hatta işlevsel stilleri koymanın yanlış olduğuna veya Go uzmanlarının dediği gibi, bunların deyim dışı olduğuna inanıyor.

Kendi topluluğumuza geri dönersek, Go programcılarının mühendislik değeri nedir? Topluluğumuzdaki tartışmalar genellikle çok güvenilmezdir, bu nedenle orijinal ilkelerden bir dizi değer elde etmek büyük bir zorluk olacaktır. Fikir birliği kritiktir, ancak tartışmaya katkıda bulunanların sayısı arttıkça zorluk katlanarak artar. Ama ya birisi bizim için zor işi yaptıysa?

On yıllar önce Tim Peters, Python'un Zen'i: PEP-20'yi yazdı. Peter, Guido van Rossum'un tanık olduğu mühendislik değerini Python'un BDFL'si olarak kaydetmeye çalıştı.

Bu makale Python'un Zen'ine odaklanmaya ve sorular sormaya devam edecek: Go programcılarının mühendislik değerini tanımlayabilecek herhangi bir şey var mı?

İyi bir paket, iyi bir isimle başlar

"Ad alanları harika bir fikirdir - onu iyi kullanmalıyız!" - Python Zen, Madde 19

Bu oldukça açık, Python programcıları ad alanlarını kullanmalı ve bunları kapsamlı bir şekilde kullanmalıdır.

Go tabiriyle ad alanı bir pakettir. Bileşenleri paketlere ayırmanın tasarım ve potansiyel yeniden kullanım açısından yararlı olup olmadığından şüpheliyim. Bununla birlikte, özellikle onlarca yıl başka bir dil kullanılacaksa, doğru yöntemle ilgili sorunlar olabilir.

Go dilinde, her paketin amaçlanan amacı olmalı ve amacını anlamanın en iyi yolu, terim adını kullanmaktır. Bir paketin adı, ne sağladığını açıklar, bu nedenle Peter'ın pasajını yeniden yorumlamak için şunu söyleyebiliriz: Her Go paketinin ayrı bir amacı olmalıdır.

Bu yeni bir fikir değil, bir süredir ondan bahsediyorum ama alt sınıflandırma için paket kullanmak yerine neden bu yapılsın? Sebep değişimdir.

"Tasarım, kodu çalışmak için düzenleme sanatıdır ve her zaman değişkendir." - Sandi Metz

İçinde bulunduğumuz oyunun adı değişimdir, Programcılar olarak yapmamız gereken şey değişimi yönetmek. İyi yapıldığında buna tasarım veya mimari, kötü yapıldığında ise teknik borç veya eski kod denir.

Yazdığınız kod yalnızca bir kez çalıştırılırsa ve bir dizi sabit girdi için mükemmel şekilde çalışırsa, kodun artıları ve eksileri kimsenin umurunda değildir, sonuçta, programın nihai çıktısı şirketin ilgilendiği şeydir.

Ancak bu tür şeyler asla olmayacak. Yazılımda hatalar, gereksinim değişiklikleri ve giriş değişiklikleri var Tek bir çalıştırma için çok az program yazılmıştır, bu nedenle programlar her zaman zaman içinde değişecektir. Belki siz, belki bir başkası, kodu değiştirmek ve korumaktan her zaman sorumludur.

Peki program değişiklikleri nasıl kolaylaştırılır? Arayüzleri her yere mi koyuyorsunuz? Simülasyon her yerde kullanılıyor mu? Veya zararlı bağımlılık enjeksiyonu kullanıyor musunuz? Belki belirli prosedür türleri için, bu uygulamalar yararlıdır, ancak bu tür prosedürler çok değildir. Çoğu program için, bazı esnek yöntemlerin önceden tasarlanması mühendislik tasarımından daha önemlidir.

Aksine, bileşenleri geliştirmek yerine bileşenleri değiştirmeyi önceden ayarlarsak. Ardından, ne zaman ve neyin değiştirilmesi gerektiğini anlamak için en iyi yol, bileşenin ön ayar işlevini ne zaman tamamlamadığını bilmektir.

İyi bir paket, iyi bir isim seçmekle başlar.Paketin adını bir asansör tavsiyesi olarak düşünün ve sağladığı içeriği tanımlamak için bir kelime kullanın. Ad artık gereksinimlerle eşleşmediğinde, alternatif bir ad bulmanız gerekir.

Sadelik çok önemli

"Basitlik karmaşıklıktan daha iyidir." - Python Zen, Madde 3

PEP-20'de belirtildiği gibi, basitlik karmaşıklıktan daha iyidir ve tamamen katılıyorum. Birkaç yıl önce bu tweet'i gönderdim:

Çoğu programlama dili ilk başta basitlik ister, ancak sonuçta güce teslim olur. 2 Aralık 2014

En azından o zamanlar, gözlemlerime göre, özlü olması için tasarlanmamış bir dil hiç görmemiştim. Her yeni dil, doğal basitliği için nedenler ve teşvikler sağlar. Ancak araştırmamda, basitliğin Go'nun çağdaş dillerinin temel değeri olmadığını anladım. Belki bu sadece bir alay konusu, ama bu diller ya basit olmasalar ya da olasılıkları dikkate almamışlar - basitliği temel değerleri olarak görmediler.

Sadece eski usul ol ama ne zaman modası geçmiş oluyor? Ticari yazılım geliştirme endüstrisi bu temel gerçeği neden mutlu bir şekilde unutmaya devam ediyor?

"Bir yazılım tasarımı oluşturmanın iki yolu vardır: birincisi, hataları sıfırlayacak şekilde basitleştirmektir; diğeri ise onu o kadar karmaşık hale getirmektir ki hiçbir belirgin kusur görünmez. İlk yöntem çok daha zordur. - CAR Hoare , 1980 Turing Ödülü konuşmasında "İmparatorun Eski Giysileri".

Basit kolay demek değildir, hepimiz biliyoruz. Genellikle, kullanımı kolaylaştırmak için yapımı kolay olmaktan çok daha fazla şeyin yapılması gerekir.

"Güvenilirlik için basitlik bir ön şarttır." - Edsger W Dijkstra, EWD 498, 18 Haziran 1975

Neden basitlik peşinde koşalım? Go programlarını basitleştirmek neden önemlidir? Basit, kaba değil, okunabilirlik ve sürdürülebilirlik anlamına gelir. Basit demek basit değil, güvenilir, alakalı ve anlaşılması kolay demek.

"Karmaşıklığı kontrol etmek, bilgisayar programlamanın özüdür." - Brian W. Kernighan, Yazılım Araçları (1976)

Python'un basitlik kurallarına uyup uymadığı hala tartışmalıdır, ancak Go dili temel değeri olarak basitlik konusunda ısrar ediyor. Bence herkes bu konuda hemfikir: Go söz konusu olduğunda, basit kod akıllı koddan daha mantıklıdır.

Paket seviyesi durumundan kaçının

"Anlamak belirsiz olmaktan iyidir." - Python Zen, Madde 2

Bu makalenin gerçeklikten çok Peter'ın umudu gibi olduğunu düşünüyorum.Python'da dekoratörler ve özel yöntemler dahil pek çok şey net değil. Hiç şüphe yok ki bu işlevler güçlüdür ve var olma nedenleri vardır. Her işlev, özellikle karmaşık işlevler olmak üzere, birinin önemsediği ve başarmaya çalıştığı bir şeydir. Ancak, bu özelliklerin yaygın kullanımı okuyucuların uygulama maliyetlerini tahmin etmelerini zorlaştıracaktır.

İyi haber şu ki: Go programcıları olarak bir seçeneğimiz var, kodu açıkça yazmayı seçebiliriz. Anlamak çok şey ifade edebilir, anlayışın sadece bürokratik ve uzun zarif bir ifade olduğunu düşünebilirsiniz, ancak bu sadece yüzeysel bir açıklamadır. Yalnızca sayfa sözdizimine odaklanmak, her satırın uzunluğu hakkında endişelenmek ve kasıtlı olarak ifadenin yanlış olduğunu düşünmek. Kanımca daha değerli olan kısım şudur: Anlamak eşleşme ve durumla ilgilidir.

Birleştirme, bir şeyin başka şeylere bağlı olma derecesinin bir ölçüsüdür. İkisi sıkıca bağlanırsa, birlikte hareket edeceklerdir. Birincisini etkileyen bir eylem doğrudan ikincisine yansıtılacaktır. Her vagonun birbirine bağlı olduğu, yani sıkıca bağlanmış bir tren hayal edin: motor nereye gittiğinde, vagonlar onu takip eder.

Eşleşmeyi tanımlamanın başka bir yolu da "agregasyon" kelimesidir. Uyum, ikisinin doğal kombinasyonunun derecesini ölçer. Yapışkan tartışmaları veya uyumlu ekipleri tartıştığımızda, tüm bileşenlerinin doğal olarak tasarlandığı gibi bir araya getirildiğini kastediyoruz.

Kuplaj neden önemlidir? Tıpkı bir tren gibi, bir kod parçasını değiştirmeniz gerektiğinde, onunla yakından ilgili tüm kodun değiştirilmesi gerekir. İyi bir örnek, birisinin API'sinin yeni bir sürümünü yayınlaması ve şimdi tüm kodunuzun uyumlu olmamasıdır.

API, kaçınılmaz bir bağlantı kaynağıdır, ancak daha gizli bağlantı biçimleri vardır. API imzası değişirse, ilgili çağrıların gelen ve giden verilerinin de değişeceğini herkes bilir. Fonksiyonun imzasında: Bu sınıfların değerlerini alıyorum ve diğer sınıfların değerlerini döndürüyorum. Peki ya API verileri başka yollarla iletirse? Ya bir API'yi her çağırdığınızda, sonuç, parametreler değiştirilmese bile API'ye yapılan son çağrının sonucuna dayanıyorsa?

Bu durumdur ve durum yönetimi bir bilgisayar bilimi problemidir.

paket sayacı var count int func Artış (n int) int { say + = n dönüş sayısı

Basit bir "sayaç" paketimiz olduğunu varsayarsak, sayımı artırmak için "Artış" diyebiliriz ve hatta Artış değeri sıfır olduğunda başlangıç değerini döndürebiliriz.

Kodun test edilmesi gerektiğini varsayarsak, her testten sonra sayaç nasıl sıfırlanır? Paralel olarak test etmek istediğinizi varsayalım, bu yapılabilir mi? Şimdi bir seferde birden fazla içeriği hesaplamak istediğinizi varsayalım, bu yapılabilir mi?

Hayır, cevap "count" değişkenini bir tür olarak kapsüllemektir.

paket sayacı type Counter struct { int say } func (c * Sayaç) Artış (n int) int { c.count + = n iade c.count

Şimdi bu sorunun sayaçlarla sınırlı olmadığını, uygulamanın ana iş mantığını da içerdiğini hayal edin. Ayrı ayrı test edilebilir mi? Paralel olarak test edebilir misin? Aynı anda birden fazla örnek kullanılabilir mi? Cevap hala hayır ise, bunun nedeni paketin seviye durumundadır.

Paketin seviye durumundan kaçının. Paket değişkenlerini kullanmak yerine bir sınıfın ihtiyaç duyduğu bağımlılıkları sınıfın alanları olarak sağlayarak, birleştirme ve garip işlemler azaltılabilir.

Başarısızlık planı

"Hatalar sessizce göz ardı edilmemelidir." - Python Zen, Madde 10

Bazı insanlar, istisna işlemeyi destekleyen dillerin, başarılı bir şekilde geri dönmek veya hiç geri dönmek olmayan Bushido yönergelerine uyduğunu söylüyor. İstisna tabanlı dillerde, işlevler yalnızca geçerli sonuçlar döndürür. Başarısız olursa, kontrol süreci tamamen farklı bir yaklaşım izleyecektir.

Kontrol edilmeyen istisnalar açıkça güvenli olmayan programlama modeline aittir.Hangi ifadelerin istisnalar atabileceğini bilmeden, hataların varlığında sağlam kod nasıl yazılır? Java, "kontrol edilen istisnalar" kavramını getirerek istisnaların güvensizliğini azaltmaya çalışıyor Bildiğim kadarıyla, bu yaklaşım diğer ana dillerde yeniden üretilmedi. Birçok dil istisnalar kavramını kullanır, ancak Java dışında hepsi kontrol edilmemiş istisnaları kullanır.

Go dili farklı bir yaklaşım seçti. Go programcıları, sağlam programların başarısızlıklarla ilgilenen durumlardan oluştuğuna inanır. Go dili ile ilgili tasarım alanında, güçlü programlar oluşturmak isteyen programcılar için sunucu programları, çok iş parçacıklı programlar, ağ girişi işleme, beklenmeyen veri işleme, zaman aşımları, bağlantı hataları ve veri bozulması en önemlileridir. Temel görev.

"Hata işlemenin açık olması gerektiğini ve dilin temel değeri olduğunu düşünüyorum." - Peter Bourgon, GoTime # 91

Peter'ın ifadesine katılmak istiyorum, Go'nun başarısı, büyük ölçüde hataları ele almanın açık yolundan kaynaklanmaktadır. Go programcıları, önce başarısızlık durumlarının dikkate alınması gerektiğine inanırlar. Önce "eğer ..." durumunu çözeriz. Bu şekilde, üretim ortamındaki hataları ele almak yerine, kod yazarken hataları gidermeye öncelik vereceğiz.

eğer hata! = nil { dönüş hatası

Kodun ayrıntı düzeyiyle karşılaştırıldığında, bir hata oluştuğunda her bir hata durumunu kasıtlı olarak ele almak daha değerlidir. Anahtar, her hatanın kültürel değerini açıkça ele almaktır.

Derin iç içe geçmeyi önlemek için mümkün olduğunca erken dönün

"Düzlük iç içe yerleştirmekten daha iyidir." - Python Zen, Madde 5

Bu, kontrol akışının ana biçimi olarak girintiyi kullanan bir dilden gelen akıllıca bir öneridir. Go dili için bu öneriyi nasıl yorumluyoruz? "gofmt", Go programının genel beyaz alanını kontrol eder, bu nedenle herhangi bir işlem yapılması gerekmez.

Paket adından bahsettim ve burada karmaşık paket hiyerarşisinden kaçınmak için bazı öneriler var. Deneyimlerime göre, programcılar Go kod tabanlarını alt bölümlere ayırmaya ve kategorize etmeye ne kadar çok çalışırsa, paket giriş döngüsünde çıkmaza girme olasılıkları o kadar artar.

Zen of Python'un beşinci önerisinin en iyi uygulaması, işlevlerdeki kontrol akışıyla ilgilidir. Kısacası, derin girinti gerektiren kontrol akışından kaçınmaktır.

"Görüş hattı, gözlemcinin engelsiz bakış açısını izleyen düz bir çizgidir." - - May Ryer, Kod: Mutlu yolu sol kenara hizalayın

May Ryer, bu fikri görüş alanı programlama olarak tanımlayabilir:

  • Ön koşullar yerine getirilmezse, koruma bildirimiyle mümkün olan en kısa sürede geri dönün.

  • Başarılı dönüş ifadesini koşullu bloğa değil, fonksiyonun sonuna koyun.

  • İşlevleri ve yöntemleri ayıklayarak genel girinti düzeyini azaltın.

Bu tavsiyenin anahtarı önemsediğiniz şeydir, yani fonksiyon tarafından tamamlanan fonksiyon ekranı asla aşmaz ve gözünüzün önünden kayma riskini üstlenirsiniz. Bu tarzın ek bir etkisi, ekibinizin kod lideri hakkında anlamsız tartışmalara sahip olmasına gerek olmamasıdır.

Her girintilendiğinde, programcının yığınına başka bir ön koşul eklenir ve 7 ± 2 kısa süreli bellek yuvalarından birini tüketir. Derin iç içe geçmeyi önlemek için, işlevi ekranın sol ucunda tutmak başarılı olmanın yoludur.

Yavaş hissediyorsanız, doğrulamak için karşılaştırma testlerini kullanın

"Belirsizlikle karşı karşıya kaldığınızda spekülasyon yapmayı reddedin." - Python Zen, Madde 12

Programlama matematiğe ve mantığa dayanır ve bu iki kavram nadiren "fırsat" unsurunu içerir. Ancak programcılar olarak her gün birçok tahminimiz var. Bu değişken ne yapar, bu parametre ne yapar, burada nil döndürürsem, Register'ı iki kez çağırırsam ne olur? Aslında, modern programlamada, özellikle yazılmamış kitaplıkları kullanırken çok fazla spekülasyon vardır.

"API'nin kullanımı kolay olmalı ve kötüye kullanılması kolay olmamalıdır." - Josh Bloch

Anladığım kadarıyla, programcıların tahmin yürütmekten kaçınmasına yardımcı olmanın en iyi yollarından biri, API'ler oluştururken varsayılan kullanım durumlarına odaklanmaktır. Arayanın en sık kullanılan vakaları yürütmesini mümkün olduğunca kolaylaştırın. Bununla birlikte, birçok API tasarım içeriği yazdım ve hakkında konuştum, bu nedenle 12. Madde ile ilgili yorumum şu: Performansı tahmin etmeyin.

Knuth'un önerisi hakkında ne düşünürseniz düşünün, Go dilinin başarısının itici güçlerinden biri, verimli bir şekilde uygulanmasıdır. Go'da verimli programlar yazabilirsiniz ve insanlar Git'i seçer. Performansla ilgili pek çok yanlış anlama var.İsteğim şu: Kod performans optimizasyonu ararken veya bazı dogmatik önerilerle karşılaştığınızda - erteleme yavaş, CGO pahalıdır ve atomic muteks kullanmaz, tahmin etme.

Güncel olmayan dogmalar nedeniyle kodunuzu karmaşıklaştırmayın ve yavaş hissediyorsanız, lütfen önce karşılaştırmalarla doğrulayın. Go dili, ücretsiz olarak sunulan mükemmel kıyaslama ve performans analizi araçları sağlar ve bunları darboğazlarınızı belirlemek için kullanır.

Gorutini çalıştırmadan önce durdurma mekanizmasını anlayın

Bundan bahsetmişken, PEP-20'deki değerli noktaların ortaya çıkarıldığını ve açıklamasını ona genişletmek mümkün olduğunu düşünüyorum. Bu iyi çünkü aynı zamanda yararlı bir retorik olmasına rağmen, sonunda iki farklı dilden bahsediyoruz.

"Go girin, ortada bir boşluk, ardından bir işlev çağrısı, üç tıklama, daha kısa olamaz, üç tıklama bir alt süreci başlatabilir." Rob Pike, Basitlik Karmaşık, dotGo 2015

Sonraki iki öneri, özellikle gorutinlere odaklanacağım: Goroutinler, dilin imza işlevi ve birinci sınıf eşzamanlılığa cevabımızdır. Kullanımı çok kolaydır, işlevi eşzamansız olarak başlatmak için cümlenin önüne bir kelime eklemeniz yeterlidir. Çok basit, iş parçacığı yok, yığın boyutu yok, iş parçacığı havuzu yürütme programı yok, kimlik yok ve tamamlanma durumu izleme.

Goroutin maliyeti çok düşüktür, çünkü çalışma zamanında (yönetim olmadan) küçük bir iş parçacığı havuzunda yeniden kullanılabilir, yüz binlerce hatta milyonlarca gorutini kolayca barındırabilir ve bu da rekabetçi bir eşzamanlılık modelini (örneğin İş parçacığı veya olay geri çağırma) mümkün değildir.

Ancak buna rağmen, gorutinler sıfır maliyetli değildir. 10 ^ 6 gorutin başlatıldığında, en az birkaç kilobayt yığın birikmeye başlayacaktır. Bu, tasarım gerektirdiği sürece milyonlarca gorutinin kullanılmaması gerektiği anlamına gelmez, ancak 10 ^ 6 sıralaması nedeniyle izleme çok önemlidir, her ne olursa olsun çok büyük miktarda kaynak tüketecektir.

Goroutine, Go dilinde kaynak sahipliğinin anahtarıdır. Yararlı olması için Goroutine'in bir şeyler yapması gerekir; bu, kilitler ve ağ bağlantıları, veriler içeren tamponlar ve kanal gönderenler dahil olmak üzere neredeyse sürekli olarak kaynaklara başvurduğu veya sahipliğini elinde tuttuğu anlamına gelir. Gorutin etkin olduğunda, kilit kapanır, ağ bağlantısı açık kalır, arabellek ayrılır ve kanalın alıcı ucu daha fazla veri beklemeye devam eder.

Bu kaynakları serbest bırakmanın en kolay yolu, onları gorutinin yaşam döngüsü ile ilişkilendirmektir. Gorutin çıktığında kaynaklar serbest bırakılır. Bu nedenle, bu üç harfi (git ve boşluk) yazmadan önce, gorutini açmak neredeyse önemsizdir, ancak aşağıdaki soruları yanıtladığınızdan emin olun:

  • Gorutin hangi koşullar altında durur? Gorouinte'ye Go dilinde çıkmasını söylemenin bir yolu yoktur, yani durdurma veya öldürme işlevi yoktur, bu iyi bir sebepten dolayıdır. Gorutinin durmasını emredemezsek, yolu değiştirip kibarca sormalıyız. Son yol, neredeyse her zaman kanal işleminden kaynaklanır, kanal kapatıldığında, kanaldaki menzil döngüsü çıkar. Bir kanal kapatıldığında isteğe bağlı hale gelir. Sinyali bir gorutinden diğerine ifade etmenin en iyi yolu kanalı kapatmaktır.

  • Bunun gerçekleşmesi için gerekli koşullar nelerdir? Kanal hem gorutinler arasındaki iletişim kanalı hem de tamamlanması için sinyal mekanizması ise, programcının karşılaştığı bir sonraki soru, kanalı kim ve ne zaman kapatacak?

  • Gorutinin durduğunu bilmek için hangi sinyal kullanılır? Bir gorutini durdurmak için bir sinyal verildiğinde, durdurma, gorutinin referans çerçevesine göre gelecekte bir noktada meydana gelecektir. İnsan algısı söz konusu olduğunda, hızlı olabilir, ancak bilgisayar saniyede milyarlarca talimat yürütür ve her bir gorutinin perspektifinden, komutun yürütülmesi eşzamansızdır. Çözüm genellikle bir kanal dönüş sinyali veya fan girişi gerektiren bir bekleme grubudur.

Arayana eşzamanlılık bırakın

Herhangi bir ciddi Go programı yazılırken eşzamanlılık sorunları ortaya çıkabilir. Bu bir sorunu tetikler Yazdığımız birçok kitaplık ve kod, her bağlantı veya çalışan modu için tek bir gorutin kullanma biçimine aittir. Bu gorutinlerin yaşam döngüsünü nasıl yönetirsiniz?

"net / http" iyi bir örnektir Dinleme soketine sahip sunucuyu kapatmak nispeten basittir, ancak alıcı soket tarafından oluşturulan gorutin ne olacak? "net / http", istek nesnesinde bir "bağlam" nesnesi sağlar ve bu, isteği iptal etmek ve gorutini durdurmak için dinleme kodunu işaret etmek için kullanılabilir, ancak bu görevlerin ne zaman tamamlanacağı net değildir. "İçerik İptal" i çağırmak başka bir şeydir, iptalin tamamlandığını bilmek başka bir şeydir.

"Net / http" hakkında söylemek istediğim bir şey, iyi uygulama için bir ters örnek olmasıdır. Her bağlantı "net / http.Server" türü içinde oluşturulan bir grup tarafından işlendiğinden, "net / http" paketinin dışında bulunan programlar alıcı soket tarafından oluşturulan gorutini kontrol edemez.

Bu, hala gelişmekte olan bir tasarım alanıdır. Go-kit'in "run.Group" ve Go ekibinin "ErrGroup" gibi yürütme, iptal ve bekleme gibi işlevlerle eşzamansız olarak çalışması gerekir.

Daha büyük tasarım yönergeleri, kütüphane yazarları veya eşzamansız olarak çalışan kod yazan herkes içindir, goroutinleri açma sorumluluğunu arayanlara bırakır ve işlevin nasıl açılacağını, izlenmesini ve beklemek istediklerini seçmelerine izin verir.

Paket API'sinin davranışını kilitlemek için bir test yazın

Testler, yazılımınızın ne yaptığı ve ne yapmadığıyla ilgili sözleşmelerdir. Paket düzeyinde birim testleri, paket API'sinin davranışını kilitlemelidir. Paketin kodda tamamlamayı vaat ettiği işlevleri açıklarlar. Her bir giriş düzenlenmişse Bir birim testi var, tamamlanması gereken fonksiyonu belge yerine kodda tanımlayacaksınız.

Bu sözleşmeyi beyan etmek için basitçe "go test" girin. Herhangi bir aşamada, değişiklikten önce insanların güvendiği davranışların değişiklikten sonra da geçerli olacağından son derece emin olabilirsiniz.

Test, API davranışını kilitler ve genel API'leri eklemek, değiştirmek veya kaldırmak için yapılan tüm değişiklikler, testlerinde yapılan değişiklikleri de içermelidir.

Ilımlılık bir erdemdir

Go dili, yalnızca 25 anahtar kelimeden oluşan basit bir dildir. Bazı yönlerden, dilin yerleşik özelliklerinin öne çıkmasını sağlayacaktır. Yine, bunlar dilin satış noktalarıdır: hafif eşzamanlılık ve yapılandırılmış türler.

Go dilinin tüm özelliklerini hemen denemekten kaynaklanan kafa karışıklığını hepimizin yaşadığını düşünüyorum. Kanalları mümkün olduğunca çok kullanmaya kim bu kadar hevesli olabilir? Şahsen, sonuçları test etmek zor, kırılgan ve nihayetinde çok karmaşık buluyorum, bunu sadece ben mi düşünüyorum?

Gorutinler üzerinde benzer bir deneyim yaşadım. Çalışmayı küçük birimlere ayırmaya çalışırken, bir grup yönetilemez gorutin yarattım ve sonunda çoğunun her zaman blok olduğunu, sırayla işlenmeyi beklediğini keşfettim - kod sonuçta sırayla. Koda çok fazla karmaşıklık ekledim, ancak gerçek çalışmaya neredeyse hiç fayda sağlamadı. Benzer bir deneyimi olan var mı?

Gömme konusunda da benzer deneyimlerim var Başlangıçta, bunu kalıtım olarak yanlış anladım ve sonra, çok sayıda sorumluluk üstlenen karmaşık türleri daha karmaşık devasa türlerde birleştirerek kırılgan temel sınıf sorununu yeniden yapılandırdım.

Bu en az uygulanabilir öneri olabilir ama bence çok önemli. Tavsiyeler her zaman aynıdır, her şey mütevazı olmalıdır ve Go'nun özellikleri bir istisna değildir. Yapabiliyorsanız, gorutinleri veya kanalları veya iç içe geçmiş yapıları, anonim fonksiyonları veya geçiş paketlerini takip etmeyin ve herkes için arayüzler kurmayın, aksine basit yöntemler akıllı yöntemlerden daha etkilidir.

Sürdürülebilirlik önemlidir

PEP-20'nin bu makalesi hakkında konuşmak istiyorum:

"Okunabilirlik önemlidir." - Python Zen, Madde 7

Okunabilirliğin önemi hakkında sadece Go dilinde değil, tüm programlama dillerinde çok sayıda tartışma var. Benim gibi sahnede duran ve Go dilini savunan insanlar basitlik, okunabilirlik, açıklık ve üretkenlik gibi kelimeleri kullanacaklar, ancak sonunda aynı anlama sahipler - "sürdürülebilirlik".

Asıl amacımız, sürdürülebilir kod, yani orijinal yazar bittikten sonra dayanabilecek kod yazmaktır. Kod yalnızca giriş düğümünde değil, gelecekteki değerin temeli olarak da mevcuttur. Okunabilirliğin önemli olmadığı değil, sürdürülebilirliğin daha önemli olduğu.

Go dili akıllı insanlar için optimize edilmemiştir ve minimum sayıda program satırı için optimize edilmemiştir. Diskteki kaynak kodunu optimize etmedik, programı editöre yazmak için zamanı da optimize etmedik. Buna karşılık, optimizasyon yönümüz kodu daha okunaklı hale getirmektir, çünkü kod okuyucu, kodu koruyan kişidir.

Kendiniz için bir program yazıyorsanız, onu yalnızca bir kez çalıştırmanız gerekebilir veya programın tek okuyucusu ve programın hizmet verdiği tek kişi sizsiniz. Ancak yazılım birden fazla kişinin katkıda bulunduğu bir programsa veya insanların uzun süre kullanmaya devam edeceği bir programsa, gereksinimleri, işlevleri veya işletim ortamı değişebilir ve amacınız programın sürdürülebilir olması olmalıdır. Bakım yapılamıyorsa ve yalnızca yeniden yazılabiliyorsa, bu, şirketinizin Go dilinde en son kaynak yatırımı olabilir.

Şirketten ayrıldıktan sonra, sürdürmek için çok çalıştığınız iş devam ettirilebilir mi? Gelecekte yazdığınız kodu başkalarının korumasını kolaylaştırmak için ne yapabilirsiniz?

Orijinal bağlantı: https://dave.cheney.net/2020/02/23/the-zen-of-go

Bu makale, yazarın GopherCon Israel 2020 konuşmasından derlenmiştir.

Bu makale bir CSDN çevirisidir, lütfen yeniden basımın kaynağını belirtin.

Dijital dönüşüm eş için çok mu zor? AI ve IoT sert vuruşlar yapıyor!

Bu bir mucize! 8 günde bir ürün doğdu ve bu girişim bunu yaptı

Döngüsel Zeka Yang Zhilin: "İnsan-makine bağlantısı" diyalog semantik uygulamalarında yeni bir trend olacak!

Zhou Hongyi tarafından tüm ağdan yasaklanan 360 asil general: tabandan 36 yaşına kadar olan ve net değeri yüz milyonlarca olan bir karşı saldırı!

Kubernetes'in uç bilişim alanında ayrıntılı gelişimi

Salgından sonra, küresel kripto topluluğunun koronavirüsle savaşmak için çok şey yaptığı ortaya çıktı!

Perakendecilikte "duygusal bilgi işlemin" uygulamasını ve gelişimini anlamak için bir makale

Yeni bir programcı iş ararken nasıl özgeçmiş yazmalıdır?
önceki
10 satırlık Python kodu hangi ileri teknoloji işlemlere sahip olabilir? | Güç Projesi
Sonraki
Muhabir: Birkaç röportaj sorusunu ezberledikten sonra, Java kaynak koduna aşina olduğunuzu söylemeye cesaret edebilir misiniz? Kaynak kodunu bile bilmeyen kişileri işe almıyoruz Güç Projesi
400 satırdan fazla kod! Süper ayrıntılı Rasa Çince sohbet robotu geliştirme kılavuzu | Kuvvet Projesi
Luhan'ın AI hayranları var, AI'nın yüz değiştiren dramasının etkisi neden bu kadar aptalca?
İyi programcıların hangi programlama alışkanlıkları vardır?
Döngüsel Zeka Yang Zhilin: "İnsan-makine bağlantısı", semantik diyalog uygulamalarında yeni bir trend olacak
Can sıkıcı MySQL alt veritabanı alt tablo problemini tamamen nasıl çözebilirim? Daha iyi bir veritabanı yazın
Ne mucize! 8 günde bir ürün doğdu ve bu girişim bunu yaptı
Programcılar için zorunlu bir kurs: Veri analizi için neden Python kullanmanız gerekiyor? Excel kötü mü?
Ali ve Tencent gibi büyük üreticilerden yeni hasat teklifleri Size bunları anlatması gerekiyor.
Çin'de bir ilk olan Tencent Cloud Cloud, "Aile Kovası" nı geliştirdi
@Programmer, programlama yönteminizin modası geçmiş, bulut geliştirme çağı geliyor
Ali Dharma Akademisi Aydınlatılıyor! P10 patronu size AIoT akıllı sesli etkileşim teknolojisinin nasıl oluşturulacağını öğretir
To Top