İçerik
Bu yazımda iki modül üreteceğiz. İlki başka uygulama ya da kütüphaneler içerisinde çağırabileceğiniz bir kütüphane, ikincisi ise bunu kullanacak olan uygulama.
Bunları yaparken Go dilinin değişik özelliklerini kullanmayı öğreneceğiz.
- Bir modül oluşturmak -- İçinde diğer uygulamalardan çağırabileceğimiz fonksiyonlar olan küçük bir modül oluşturacağız.
- Kodumuzu başka bir modülden çağırmak -- Kodumuzu import edip kullanacağız.
- Hata oluşturma ve işleme -- Basit bir hata işleme tekniği göreceğiz.
- Rastgele selamlama rutini -- Go slice verileri işleyeceğiz (Go dinamik boyutlu array'ler).
- Birçok kişi için selamlama rutini -- Bir map içinde key:value çifti verileri kullanacağız.
- Test rutini eklemek -- Kodumuzu test için Go'nun unit test özelliklerini kullanacağız.
- Uygulamayı derlemek ve kurulum -- Uygulamamızı derleyip lokalde kullanmak için kurulum yapacağız.
Ön Koşullar
- Biraz programcılık bilgisi. Buradaki kod oldukça basit ama yine de fonksiyonlar, döngüler ve array'ler hakkında bilgi sahibi olmak iyi olacaktır.
- Kodunuzu yazmak için bir editör. Herhangi bir text editörü yeterli olacaktır. En popülerleri VSCode (ücretsiz), GoLand (ücretli), ve Vim (ücretsiz). Ben hem Windows hem de Linux'da VSCode kullanıyorum.
- Bir terminal. Go dilini Linux ve Mac sistemlerde terminalde , Windows'ta ise PowerShell ya da komut isteminde kullanabilirsiniz.
Başkalarının Kullanabileceği Bir Modül Oluşturma
Bir Go modülü oluşturarak başlayalım. Bir modülde yararlı fonksiyonlarınızı içeren bir ya da daha fazla paketi bir araya toplarsınız. Binlerce satır programı tek bir dosyaya koyacak halimiz yok, hem ürettiğimiz fonksiyonları daha sonra başka uygulamalarda da kullanabiliriz. Örneğin siz finansal analiler yapan fonksiyonlar içeren bir modül yazarsınız daha sonra finansal uygulamalar yapan başkaları da sizin modülünüzü kullanabilir. Go dokümanlarında bu konuda bir yazı bulunuyor, isterseniz incelersiniz.
Go kodu paketlere bölünmüştür ve bu paketler, modüller içinde gruplanır. Sizin modülünüz de kodunuzu çalıştırmak için gereken bağımlılıkları , Go versiyonu ve ihtiyaç duyulan diğer modülleri içerecek şekilde olmalıdır.
Modülünüzde yeni özellikler eklediğinizde yeni bir versiyon yayınlarsınız. Sizin modülünüzdeki fonksiyonları kullanan geliştiriciler güncel paketleri programlarına dahil edip son kullanıcı öncesi testlerini yapabilirler.
Hadi başlayalım,
1. Bir komut isteği açın ve home klasörünüze gidin
Linux veya Mac için
Windows'ta
2. Modülünüz için "selamlama" adında bir klasör oluşturun
Örneğin terminalde :
3. Go mod init komutu ile modülünüzü başlatın
go mod init komutunu modülünüzün adres bilgisini girerek çalıştırın -- Burada ornek.com/selamlama adresi kullanılmış. Eğer bir modülü başkalarının kullanabilmesi için yayınlıyorsanız bu adres Go araçları tarafından modülünüzün download edileceği (indirileceği) adres olmalıdır. Bu sizin kod deponuzdur (repository derler). Terminalde selamlama klasörü içinde şu satırı girin :
go mod init komutu klasör içinde go.mod adında bir dosya üretir, bu dosya modülünüzün bağımlılıklarını takip etmek içindir. Şimdilik dosya içinde sadece modülünüzün adı ve bunu hazırlarken kullandığınız Go versiyonu bilgisi var. Mesela bendekinin içeriği şöyle :
İleride bağımlılıklar eklediğinizde bu dosya da o bağımlılıkları içerecek şekilde büyüyecek.
4. Text editörünüzle klasörünüzde selamlama.go adında yeni bir dosya üretin
5. Aşağıdaki kodu selamlama.go dosyanızın içine yazın (kopyalayın demedim)
Bu modülünüzdeki ilk kod. Fonksiyonu çağıran koda verilen ismi içeren bir mesaj yazısı dönüyor. Sonraki adımda buradaki kodu kullanan başka bir kod yazacağız.
Bu koda bakarsak :
- İlgili fonksiyonlarımızı toplamak için selamlama paketini (package komutu ile) oluşturuyoruz
- Selamlaşmayı dönen Merhaba fonksiyonunu tanımlıyoruz.
Bu fonksiyon string tipi bir parametre alıyor. Fonksiyon ayrıca string bir değer dönüyor. Go dilinde ismi büyük harfle başlayan fonksiyonlar ancak paket dışından çağrılabilir. Bu Go'da ihraç edilen isim (exported name) olarak bilinir. Go turunda ihraç edilen isimler örneğine bakabilirsiniz.
- Selamlamanızı saklamak için mesaj değişkenini tanımlıyoruz.
Go dilinde := işareti bir değişkeni değer girerek tanımlamada kullanılır. Go eşitliğin sağ tarafındaki değerden değişkenin veri tipini tahmin eder. Uzun yolu tercih edenler şöyle de yazabilir:
var mesaj stringmesaj = fmt.Sprintf("Merhaba %v, Hoşgeldin!", isim) - fmt paketinin Sprintf() fonksiyonunu kullanarak mesajımızı oluşturuyoruz. İlk argüman formatı belirleyen string ve ikinci argüman ise mesaja enjekte edilecek olan isim değeri. Format stringinde %v ile belirtilen yere bu değer enjekte edilecek. Böylece fonksiyondan dönen selamlama yazısı oluşacak.
- Son olarak da oluşturduğumuz mesajı return komutuyla fonksiyonu çağırana geri dönüyoruz.
Kodumuzu Başka Bir Modülden Çağırmak
Önceki bölümde bir selamlama modülü oluşturduk. Bu bölümde modülümüzde tanımladığımız Merhaba() fonksiyonunu başka modülden çağıran bir kod yazacağız. Bir uygulama olarak çalışacak bir kod içerisinde selamlama modülünü kullanacağız.
1. Uygulamamız için yeni bir klasör oluşturalım
Bu klasörün adı merhaba olacak ve modülümüzü içeren selamlama klasörü ile aynı dizinde olacak. Klasör yapısı şöyle örneğin:
Örneğin selamlama klasörü içindeyseniz ,
2. Yazmakta olduğumuz kod için Go bağımlılıklarını içeren dosyayı go mod init komutuyla oluşturalım
3. Editörümüz ile klasörümüzde merhaba.go adında yeni bir dosya üretelim
4. Modülümüzdeki Merhaba fonksiyonunu kullanan ve fonksiyonun dönen değerini yazan bir kod yazalım
Bu kodda yaptıklarımız :
- Bir main paketi deklare ettik. Uygulama olarak çalışacak tüm Go programları main paketi içinde olmalıdır.
- İki tane paket import ettik (programımıza dahil ettik) : fmt ve ornek.com/selamlama paketleri. Bu programımızda bu paketlerin içindeki fonksiyonları kullanma kabiliyeti kazandırır. ornek.com/selamlama paketini import etmekle daha önce tanımladığımız modüldeki Merhaba() fonksiyonunu kullanma imkanımız olur. Ayrıca terminalde girdi/çıktı işlemleri fonksiyonlarını içeren fmt paketini de kullanacağız.
- selamlama paketinin Merhaba() fonksiyonunu kullanarak bir selamlama mesajı elde ettik.
5. ornek.com/selamlama modülünü lokaldeki klasörden kullanmak için
İlerde programınızı kullanacağınız zaman, selamlama modülünüzü belirttiğiniz adreste yayınlamanız gerekiyor ki Go araçları internette bu modülü bulup kullanabilsin. Fakat şimdilik modülümüzü henüz yayınlamadığımız için Go araçlarına modülümüzü lokalde bulacağı klasörü tarif etmemiz gerekiyor, yoksa gidip internette ornek.com/selamlama diye bir yer arayıp tabi ki bulamayacak.
Bunu yapmak için go mod edit komutu kullanılır.
5.1 merhaba klasörü içinde terminalde şu kodu çalıştırın :
/merhaba# go mod edit -replace ornek.com/selamlama=../selamlama
Bu komut go.mod dosyamıza bir satır ekleyerek ornek.com/selamlama denince modülü ../selamlama klasöründe bulacağını belirtir.
module ornek.com/merhaba
go 1.22.2
replace ornek.com/selamlama => ../selamlama
5.2 yine merhaba klasörü içinde go mod tidy komutu kullanarak uygulamamızın bağımlılıklarını selamlama modülünün bağımlılıkları ile senkronize edelim.
Bu komut girildikten sonra merhaba klasörümüzdeki go.mod dosyasına ilave bir satır daha gelir.
Bu komutla selamlama modülünün mevcut versiyonunun bağımlılıkları ile uygulamamızın bağımlılıkları senkronize ediliyor. Verilen versiyon numarası rastgele üretilmiş bir numara (şu anda modülümüzde versiyon numarası mevcut değil).
Yayınlanmış bir modülde gerçek bir versiyon numarası olur ve replace satırı olmaz. Mesela :
Modül versiyon numaralandırmaları için ilgili dokümana bakabilirsiniz.
6. Terminalde kodumuzu çalıştıralım ve görelim
Tebrikler modülümüzü tanımladık ve harici bir programda kullandık.
Hata Oluşturma ve İşleme
Hataları işlemek sağlıklı bir kodun temel özelliklerindendir. Bu bölümde selamlama modülünden hata dönen bir kod yazacağız ve onu modülü kullanan programda işleyeceğiz.
1. selamlama/selamlama.go içerisine aşağıdaki satırları ekleyelim
Bu kodda yaptıklarımız :
- Fonksiyon tanımını iki değer dönecek şekilde değiştirdik, bir string ve bir error tipi değer. Fonksiyonu çağıran kod hata olmasını test için ikinci dönen değerin olup olmadığına bakacak.
- Go standart kütüphanesi olan errors kütüphanesini import ederek errors.New() fonksiyonunu kullanma becerisi kazandık.
- Bir if bloğu ile eğer isim yerine boş string verilirse (ki zaten string bir değer de vermese daha derleme yapılırken hata verecektir) isteğin geçersiz olduğunu belirten bir hata mesajı dönecek kod yazdık. errors.New() fonksiyonu içinde sizin girdiğiniz mesajı barındıran bir hata mesajı üretir.
- Fonksiyon sağlıklı çalıştığında ise ikinci değer olarak hata olmadığını belirtmek için nil değeri döndük. Biliyorsunuz nil , yok demek , hiçbir şey demek.
2. merhaba/merhaba.go dosyamızda selamlama modülünün Merhaba() fonksiyonu hata dönerse onu işleyecek bir ilave yapalım.
Ne zaman bir program yazsam, herşey yolunda giderse sağlıklı çalışacak kısım çok az zamanımı alır. Ama iş olası hataları işleyip programın ona göre davranmasını sağlamaya gelince bazen kod 4-5 katına uzar. İşte bu da buranın örneği :
Burada yaptıklarımız :
- Log mesajını sadece öncesinde "Selamlama: " yazısı gelecek şekilde ve zaman, kaynak dosya ve satır numarası olmayacak şekilde ayarladık.
- Merhaba() fonksiyonunun ikinci return değerini de err değişkeni olacak şekilde ilave yaptık.
- Hata üretmek amacıyla Merhaba() fonksiyonuna argüman olarak boş string verdik.
- nil olmayan bir err değeri sorguladık. Bu durumda hata vardır ve devam etmenin anlamı yoktur.
- log paketinin hata mesajını yazıp programı bitiren log.Fatal() fonksiyonunu kullanarak hata durumunda programdan çıkılmasını sağladık.
3. merhaba klasöründe komut satırında merhaba.go programını çalıştırarak hata aldığımızı görelim
Bu Go dilinde genel hata işleme yöntemi : Dönen değerlerde error tipi bir değer dön ve çağıran programda onun varlığını test et.
Şimdi bir Go slice tipi veri içindeki elemanları kullanarak rastgele bir selamlama mesajı yapalım.
Rastgele Selamlama Rutini
Bu bölümde fonksiyon kodumuzu değiştirerek hep aynı şekil değil , her seferinde rastgele başka bir mesaj dönmesini sağlayacağız.
Bunu yaparken Go slice veri tipini kullanacağız. Bir slice yapı olarak bir array'e benzer ancak eleman eklemek ya da eksiltmek mümkündür. slice Go dilinin etkili veri tiplerinden biridir.
Bir slice içinde 3 değişik selamlama mesajı oluşturacağız ve rastgele birini seçerek fonksiyonumuzdan dönmesini sağlayacağız.
Bu kodda yaptıklarımız :
- Selamlama mesajı için rastgele format seçen rastgeleFormat() fonksiyonunu tanımladık. Dikkat ederseniz fonksiyon adı küçük harfle başlıyor bu durumda fonksiyonumuz sadece modül içinde kullanılabiliyor, dışarıya ihraç edilmiyor ve harici program bu fonksiyonu kullanamaz.
- rastgeleFormat() fonksiyonunda üç farklı mesaj formatı slice tipi değişken içinde tanımlanıyor. Bir slice tanımlarken köşeli parantez içinde eleman adedi girilmez. Bu Go diline bahsi geçenin bir slice olduğunu ve boyutunun değişebileceğini belirtir.
- Mesajlardan birini rastgele seçmek amacıyla math/rand paketi fonksiyonları kullanılıyor.
- Merhaba() fonksiyonu içinde rastgeleFormat() fonksiyonu çağrılarak rastgele bir selamlaşma mesajı elde ediliyor ve argümanda verilen isim o format içine enjekte ediliyor.
- Hata olup olmamasına bağlı olarak mesaj ya da bir hata daha önce olduğu gibi geri dönülüyor.
Kodu test etmek için merhaba/merhaba.go uygulama dosyamızda bu sefer bir isim vererek deneyelim.
İşte size örnek birkaç çalıştırma :
Şimdi yine bir slice kullanarak bir'den fazla kişiyi selamlayalım.
Birçok Kişi İçin Selamlama Rutini
Göreceğimiz bölümde modülümüzün koduna ilaveler yaparak bir çağrılmada birden çok kişiyi selamlama özelliği kazandıracağız. Bir başka deyişle birden çok değer ile fonksiyon çağıracağız. Fonksiyon argümanında birçok ismi alacak ve her biri için ayrı olacak şekilde birçok mesaj dönecek.
Fakat bu köklü bir değişiklik olacak. Değişimi Merhaba() fonksiyonu içinde yaparsak ve diyelim ki modülümüzü de yayınlamışsak, daha önceki şekliyle Merhaba() fonksiyonunu kullanan uygulamalar güncelleme sonrası çakılacaktır. İyisi mi bu yeni modül özelliğimiz için modüle başka bir isimde yeni bir fonksiyon ekleyelim.
1. selamlama/selamlama.go dosyamızda aşağıdaki ilaveleri yapalım
Bu kodda yaptıklarımız :
- Parametresi tek bir isim yerine bir isimler slice'ı olan Merhabalar() fonksiyonu tanımladık. Ayrıca dönen değeri de map tipi yaptık böylece verilen her isme karşı gelen mesajı ayrı ayrı bildireceğiz.
- Yeni Merhabalar() fonksiyonumuzda ortak yapılan işler için Merhaba() fonksiyonunu kullandık. Böylece aynı şeyleri tekrar yazmadık (DRY - Don't Repeat Yourself).
- Bir mesajlar map değişkeni ürettik , içinde verilen isimler ve bunlara ait olan selamlama mesajları bulunuyor. Go dilinde bir map değişken şöyle tanımlanıyor : make(map[key-tipi]değer-tipi) . Daha ayrıntılı bilgiyi Go blog sayfasında bulabilirsiniz.
- Fonksiyon argümanında verilen isimler üzerinde iterasyon yaparak her birine karşı gelen mesajı Merhaba() fonksiyonunu kullanarak elde ediyoruz, ayrıca hata olup olmadığını da kontrol ediyoruz.
- Dönen her bir mesajı map içerisine yeni bir eleman olarak ekliyoruz. Döngü için range deyimi kullandık. Bildiğimiz üzere range her iterasyonda 2 bilgi dönüyor, index ve değer. Index kullanmayacağımız için alt çizgi ile ( _ ) kullanmayacağımızı belirttik. Orada index'e bir isim verip sonradan kullanmaya da bilirdik ama Go dilinin bu alt çizgi ile ifade şekli kodu çok daha anlaşılır yapıyor.
2. merhaba/merhaba.go uygulama kodumuzu yeni fonksiyonu kullanır hale getirelim
Burada yaptıklarımız :
- 3 isimden oluşan bir isimler slice değişkeni tanımladık.
- Merhabalar() fonksiyonuna bu isimler değişkenini argüman olarak girerek çağırdık.
3. Terminalde uygulamamızı çalıştıralım
Örnek bir çıktı şöyle olabilir.
Test Rutini Eklemek
Kodumuzu artık oldukça kararlı ve istediğimiz şeyleri yapar hale getirdiğimize göre bir test ekleyelim. Programımıza ileride modifikasyonlar yaptıkça hala sağlıklı çalışıyor mu diye tek tek olası girdileri verip denemek hem zamanımızı alır , hem de bazı olasılıkları unutabiliriz. Bu bölümde Merhaba() fonksiyonumuza test rutini yazacağız.
Go'nun içinde gelen birim testleri işimizi kolaylaştırıyor. Özellikle isimlendirme kurallarını kullanmak. Go'nun testing paketi ve test komutu ile test rutinlerimizi kolayca yazabiliriz.
1. selamlama klasöründe selamlama_test.go adında yeni bir dosya ekleyelim
Bir dosya adının sonuna _test.go gelmesi Go dilinde o dosyanın bir test dosyası olduğunu gösterir.
2. selamlama_test.go dosyamıza şu kodu yazalım ve kaydedelim
Bu kodda neler yaptık :
- Test ettiğimiz dosya ile aynı paketi kullandık.
- selamlama.Merhaba() fonksiyonunu test için 2 tane fonksiyon tanımladık. Fonksiyonların isimleri yapılan testi açıklayan isimler olarak seçildi. Fonksiyonların parametresinde verilen t *testing.T parametresi testing.T tipinde, bu parametre bir hata oluşması durumunda fonksiyonumuz hata çıktısını yazarken kullanılacak.
- 2 fonksiyonumuz var
- TestMerhabaİsim() fonksiyonu modülümüzün Merhaba() fonksiyonunu bir isim girerek çağırıyor ve dönen cevapta bu ismi içeren bir selamlama mesajı olmasını ve hata olmamasını bekliyor. Eğer sonuç beklediğimiz gibi olmazsa t parametresinin Fatalf() fonksiyonunu kullanarak konsola hatayı bildiren bir mesaj yazdırıyoruz. Bu fonksiyon için Go dokümanı orjinalinde Regexp kullanılmış , ancak Türkçe karakterlerde regexp eşleşmelerini kontrol oldukça zor olduğu için ben burada strings.Contains() metodu ile dönen mesajda gönderdiğim isimin olup olmadığını kontrol ettim.
- TestMerhabaBoş() fonksiyonu ise Merhaba() fonksiyonunu isim olarak boş bir string göndererek çağırıyor. Bunun sonucunda bir mesaj dönmemesi ve hata dönmesini bekliyoruz. Beklediğimiz olmazsa yine t.Fatalf() metoduyla konsola hata mesajımızı yazdırıyoruz.
3. Terminalde go test komutu kullanarak testlerin gerçekleştirilmesi
go test komutu bulunulan klasördeki test dosyalarındaki (ismi _test.go ile biten dosyalar), test fonksiyonlarını (ismi Test ile başlayan fonksiyonlar) çalıştırır. Komutu -v opsiyonu ile kullanarak yapılan tüm testleri görebiliriz.
Denediğimizde testlerimiz başarılı (PASS) olmalıdır.
4. selamlama.Merhaba() fonksiyonunu bozarak testin hatalı olmasını sağlamak
TestMerhabaİsim() fonksiyonu Merhaba() fonksiyonunu bir isim vererek çağırıyor ve dönen cevapta o ismin olduğunu test ediyor. selamlama.Merhaba() fonksiyonunu dönen cevapta, argümanda gelen isim dönmeyecek şekilde değiştirelim.
5. Terminalde test çalıştırıp hatayı görelim
Tekrar eski haline getirip modülümüzü sağlıklı çalışır hale getirelim, artık uygulamamızı derleyip kurulumunu yapacağız.
Uygulamayı derlemek ve kurulum
Bu bölümde birkaç yeni Go komutu göreceğiz. Uygulama geliştirirken go run komutunu uygulamanın çalışmasını görmek için sık sık kullandık. Fakat halihazırda ismini yazınca direk çalışacak bir binary çalışan dosyamız yok.
Bu kısımda uygulamanızı bitirmenizi sağlayacak 2 Go komutu kullanacağız:
- go build komutu uygulamamızı ve bağımlılıklarını derlemesini yapar, dosyaları oluşturur ancak kurulumunu yapmaz.
- go install komutu paketleri derler ve kurar.
1. Terminalde merhaba klasöründe go build komutu ile tek başına çalışan uygulama dosyasını oluşturalım
2. Terminalde merhaba klasöründe çalıştırılabilir dosyayı çağırarak uygulamayı test edelim
Linux ya da Mac kullanıyorsanız :
Windows kullanıyorsanız :
Uygulamamızı çalıştırılabilir bir dosyaya derledik ancak terminalde ve klasör yolu belirterek çalıştırabiliyoruz. Kurulumunu yaparsak bunlara gerek olmadan her yerden çalışır.
3. Go'nun paketimizi kuracağı klasörün öğrenilmesi
go list komutunu kullanarak Go'nun nereye kurulum yapacağını öğrenebiliriz. merhaba klasörümüzde terminalden şu komutu girelim:
Sizdeki cevap benden farklı olabilir, uygulama kodunuzu nerede konuşlandırdığınıza göre değişir. Burada bende /root/go/bin klasöründe merhaba adında bir çalışan dosya oluşacak denmek isteniyor. Bu klasörü unutmayalım, az sonra lazım olacak.
4. Go kurulum klasörünü sisteminize kaydetmek
Kurulum yapılacak olan uygulamanızı istediğiniz yerden (başka klasörlerden) çalıştırabilmek için kurulum yapılan klasörü sisteminize kaydetmelisiniz.
- Linux ve Mac için şu komut:export PATH=$PATH:/kurulum/olacak/klasör/yolubenim örneğimde "export PATH=$PATH:/root/go/bin"
- Windows içinse:set PATH=%PATH%;C:\kurulum\olacak\klasör\yolu
Alternatif olarak eğer zaten mevcut olan bir başka klasöre Go'nun kurulum yapmasını da sağlamak için go env komutunu kullanarak GOBIN değerini değiştirebilirsiniz.
ya da
şeklinde.
5. go install komutu ile kurulumu yapmak
Şimdi terminalde go install komutu kullanarak kurulumumuzu gerçekleştirebiliriz.
Artık uygulamamızı herhangi bir yerden çalıştırabiliriz. Örnek olarak başka bir klasörden deneyelim.
Geçmiş olsun , bir modül yapalım derken bir sürü şey öğrendik. Bu yazı da bu kadar, kalın sağlıcakla..
Hiç yorum yok:
Yorum Gönder