Viper
Last updated
Last updated
Viper, 12-Factor uygulamaları da dahil olmak üzere Go uygulamaları için eksiksiz bir yapılandırma çözümüdür. Bir uygulama içinde çalışmak üzere tasarlanmıştır. Her türlü yapılandırma gereksinimini ve biçimini karşılayabilir.
Desteklediği yöntemler şunlardır:
varsayılanları ayarlama,
JSON, TOML, YAML, HCL, envfile ve Java properties config dosyalarından okuma,
yapılandırma dosyalarını canlı izleme ve yeniden okuma (opsiyonel),
ortam değişkenlerinden okuma,
uzak yapılandırma sistemlerinden (etcd ya da Consul) okuma ve canlı izleme,
komut-satırı flag'lerinden okuma,
buffer'dan okuma,
açık değerler atama.
Viper, tüm uygulama yapılandırma ihtiyaçlarınız için bir kayıt defteri olarak düşünülebilir.
Bu kısımda, json
tipinde bir yapılandırma dosyası üzerinden, yapılandırmamızı nasıl yönetebileceğimizi (okuma, yazma...)
göreceğiz.
Öncelikle projemizi oluşturalım.
daha sonra ihtiyacımız olduğu için main.go
ve config.json
isimli dosyalarımızı oluşturalım. Sonuç olarak projemizin içeriği aşağıdaki gibi olacak.
config.json
dosyamızda aşağıdaki gibi bir yapı oluşturalım.
Artık config.json
dosyamızı host
ve port
değerlerini okuyup yazmak için kullanabiliriz.
main.go
dosyamızın içeriği de aşağıdaki gibi olsun.
Yukarıdaki yöntem ile oluşturduğumuz yapılandırma dosyasının içeriğini artık yönetebiliriz.
Hadi nasıl okuyacağımıza bakalım.
Get()
fonksiyonu ile belirli bir anahtarın değerini okuyabiliriz. Burada dikkat edilmesi gereken nokta Get()
fonksiyonu bize any
tipinde bir değer döndürür. Döndürülen bu değeri asıl tipine çevirmeden kullanamayacağımız durumlar olabilir. Bu durumlarda type assertion yaparak değeri çıkartabiliriz ;fakat daha kolay bir yöntem olarak GetString()
fonksiyonunu kullanabiliriz
Tabi ki bu yöntem sadece string
tipi için geçerli değil, hepsine tek tek değinmek uzun süreceği için direkt olarak dönüştürebileceğimiz tiplere kısa değinelim.
Yukarıda verilen tipler için ilgili fonksiyonu Get<tip-ismi>()
yazarak bulabilirsiniz. Bu şekilde kullanamadığınız tipleri de type assertion yaparak dönüştürebilirsiniz.
Şimdi de yapılandırma dosyamızdaki bir anahtara nasıl atama yapacağımıza bakalım.
Yazdırma işleminde sonra config.json
dosyamız aşağıdaki gibi değişecektir.
Atama işlemini eğer var olmayan bir anahtar ile yapsaydık, yeni bir alan oluştururduk. Örnek:
Yapılandırma dosyamızdaki değişikliğe bakalım.
Anahtar değerinin boş olarak atanması veya silinmesi gibi işlemler uygulamanın kararsız çalışmasına neden olabileceği için bu tür fonksiyonların kullanımını engellemişler. Zaten anahtarın silinmesi için bir fonksiyon bulunmamaktadır. Bu yüzden viper paketinin kullanımı sadece Set
ve Get
işlemlerini destekler.
WriteConfig()
fonksiyonu dosyanın yazılmasında karşılaşılan hataları döndürür.
Yapılandırma dosyasının uygulamamız tarafından oluşturulmasını istediğimiz durumlar olabilir. Bu durumlarda, yukarıdaki örneklerimizde gördüğümüzün aksine yapılandırma dosyamızı okumadan önce oluşturmamız gerekir.
WriteConfig()
fonksiyonunda dikkat edilmesi gereken ayrıntı, eğer oluşturulan yapılandırma dosyası hali hazırda bulunuyorsa bu dosyanın üzerine yazar, fakat üzerine yazma işleminde belirtilmemiş olan anahtarlar eski yapılandırma dosyasındaki hali ile gelir. Yani yapılandırma dosyası tamamen sıfırdan oluşturulmaz.
Eğer yapılandırma dosyamızın oluşturulduktan sonra bir daha değiştirilmemesini ve sadece hali hazırda bulunmadığı durumlarda oluşturulmasını istersek SafeWriteConfig()
fonksiyonunu kullanabiliriz. Böylelikle yapılandırma dosyamız zaten oluşturulmuşsa bize hata döndürecektir.
Örnek olarak:
config.json
dosyamız bulunmuyorsa, atanılan değerler ile birlikte yeni bir config.json
dosyası oluşturulacaktır. Eğer config.json
dosyamız bulunuyorsa, yukarıdaki işlemler yapıldığında SafeWriteConfig()
fonksiyonu aşağıdaki gibi bir hata döndürecektir.
Eğer yapılandırma dosyamız iç içe bir yapıdan oluşuyorsa, okuma-yazma işlemlerinde alt-alana ulaşmak için .
(nokta) kullanabiliriz.
Örnek config.json dosyamız;
Okuma işlemi için,
Yazma işlemi de aynı şekilde,
Uygulamayı çalıştırdığımız sistemimizdeki ortam değişkenlerine erişmek istediğimizde, başvurabileceğimiz iki farklı yöntem var.
Bu yöntemlerden ilki kullanmak istediğimiz ortam değişkenini viper'a bildirmek. Örneğin TEST
isminde bir ortam değişkenimiz olsun ve değeri de abc
olsun. TEST
'in değerini okuyabilmek için aşağıdaki yöntemleri kullanabiliriz.
Sisteminizde TEST
isimli bir ortam değişkeni bulunmuyorsa, aşağıdaki gibi deneyebilirsiniz.
BindEnv()
fonksiyonunun hata döndürmeme şartı sadece en az bir parametre girmemizdir.
Yapılandırma dosyaların ve ortam değişkenlerinden okuma yaptığımızda, bazı anahtarlar tanımlı olmadığı için, sıfır-değerli halde gelebilir. Eğer bu istemediğimiz bir durumsa bu anahtarların varsayılan değerlerini ayarlayabiliriz. Örnek;
Gelelim kullanımına;
config.json
dosyamızda password
isimli bir alan olmadığı için varsayılan olarak ayarladığımız 1234
değeri yazdırılacaktır.
Eğer varsayılan değerler çok sayıda olacaksa, şöyle bir yöntem kullanabiliriz.
Buraya kadar olan bölümlerde Viper'ı basitçe nasıl kullanacağımızı gördük. Ölçeklenebilir bir projede sadece bu yöntemleri kullarak ilerlememiz zor olduğu için işimizi kolaylaştıracak başka çözümler gerekiyor. Proje yapımızı düzenli tutmak için, bu yöntemlerimizi daha pratik hale getirmemiz gerekiyor.
Bunun için gruplandırma yaparak, yapılandırma ayarlarımızı struct
halinde kullanabiliriz.
Örneğin aşağıdaki gibi bir yapılandırma dosyamız olsun.
Yukarıdaki json
yapısı aktarabileceğimiz struct
'ları belirleyelim.
Yukarıdaki struct
'larda dikkat edilmesi gereken ayrıntı, struct tag
'lerdeki mapstructure
anahtarıdır.
Yapılandırma dosyamızın tipi json
olduğu için mapstructure
yerine json
'da kullanabilirdik. Fakat yapılandırma dosyamızın tipi, örnek olarak json
'dan yaml
'a geçseydi, struct tag
'lerde yaml
olarak düzenleme yapmamız gerekirdi. Bu yüzden tüm desteklenen yapılandırma dosyası tiplerinde unmarshal yapabilmesi için mapstructure
olarak uyguladık.
Tabi ki bu yöntem her durumda işimizi görmeyebilir. Bazı durumlarda farklı dosya tiplerinde farklı anahtar isimlendirmeleri olabilir. Bu gibi durumlarda da dosya tipine göre struct tag
'lerini düzenlemekte fayda vardır.
Unmarshal
etmek için aşağıdaki yöntemi izleyebiliriz.
Çıktımız aşağıdaki gibi olacaktır.