Viper
Depo Adresi: spf13/viper: Go configuration with fangs (github.com)
Dokümantasyon Adresi: spf13/viper: Go configuration with fangs (github.com)
TIP
Resmi olarak Viper2 geçişi tartışılıyor. İlgilenenler için: Viper2
Kurulum
go get github.com/spf13/viperGiriş
Viper Go uygulamaları için eksiksiz bir yapılandırma dosyası çözümüdür. Neredeyse tüm türdeki yapılandırma ihtiyaçlarını ve formatlarını işleyebilir. Proje yapılandırma dosyalarını yönetmeyi kolaylaştırır ve aşağıdaki özelliklere sahiptir:
- Varsayılan değer ayarlama
- JSON, TOML, YAML, HCL, envfile, Java properties formatlarını destekler
- Yapılandırma dosyalarının gerçek zamanlı izlenmesini ve yeniden yüklenmesini destekler
- Ortam değişkenlerinden okumayı destekler
- Uzaktan yapılandırma sisteminden yapılandırma okumayı ve değişiklikleri izlemeyi destekler
- Komut satırı bayraklarını okumayı destekler
- Buffer'dan okumayı destekler
- Açıkça ayarlanmış değerleri destekler
Resmi olarak Viper tüm uygulama yapılandırma ihtiyaçlarını karşılayabilir. Geliştiriciler yalnızca uygulama oluşturmaya odaklanır. Viper yapılandırma yönetimini üstlenir. Birçok ünlü proje Viper kullanır:
DANGER
Viper yapılandırma dosyalarının şifrelenmesi ve şifresinin çözülmesinden sorumlu değildir. Yani yapılandırma dosyalarına herhangi bir güvenlik işlemi uygulamaz.
Okuma Sırası
Viper yapılandırmayı okumak için aşağıdaki önceliği kullanır:
- Açıkça ayarlanmış değer
- Komut satırı bayrağı
- Ortam değişkenleri
- Yapılandırma dosyası
- Anahtar-değer deposu
- Varsayılan değerler
TIP
Viper yapılandırmasındaki anahtarlar büyük/küçük harf duyarlı değildir. Gelecekteki tartışmalarda bu isteğe bağlı hale getirilebilir.
Varsayılan Değerler
İyi bir yapılandırma sistemi varsayılan değer ayarlamayı desteklemelidir. Her zaman gerekli olmasa da yapılandırma dosyası ayarlanmadığında çok kullanışlıdır. Aşağıda bir örnek verilmiştir:
viper.SetDefault("filePath","./dir/img/usr")
viper.SetDefault("root","123456")Yapılandırma Dosyasını Okuma
Viper çok az yapılandırma ile yapılandırma dosyasının nerede bulunacağını bilir. Viper JSON, TOML, YAML, HCL, INI, envfile ve JavaProperties dosyalarını destekler. Viper birden fazla yolu aynı anda arayabilir ancak şu anda tek bir Viper örneği yalnızca tek bir yapılandırma dosyasını destekler. Viper varsayılan olarak arama yollarını yapılandırmaz. Varsayılan kararı uygulamaya bırakır.
Aşağıda Viper ile yapılandırma dosyası okuma örneği verilmiştir. Tam bir yol belirtmenize gerek yoktur ancak kullanırken en azından bir yapılandırma dosyası sağlamalısınız:
func TestReadConfigFile(t *testing.T) {
viper.SetConfigName("config.yml") // config adında yapılandırma dosyası oku. Belirli bir dosya uzantısı ayarlanmamış
viper.SetConfigType("yaml") // Belirli bir dosya uzantısı ayarlanmadığında dosya türünü belirtmek gerekir
viper.AddConfigPath("./") // Geçerli dizinde ara
viper.AddConfigPath("$HOME/") // Değişken kullan
viper.AddConfigPath(".") // Çalışma dizininde ara
err := viper.ReadInConfig() // Yapılandırmayı oku
if err != nil {
log.Fatalln(err)
}
}Yapılandırma dosyası bulunamadı durumunu ayrı olarak işleyebilirsiniz:
if err := viper.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
// Yapılandırma dosyası bulunamadı
} else {
// Diğer hata türleri
}
}Yapılandırmaya erişmek için tüm fonksiyonlar:
Get(key string) : interface{}GetBool(key string) : boolGetFloat64(key string) : float64GetInt(key string) : intGetIntSlice(key string) : []intGetString(key string) : stringGetStringMap(key string) : map[string]interface{}GetStringMapString(key string) : map[string]stringGetStringSlice(key string) : []stringGetTime(key string) : time.TimeGetDuration(key string) : time.DurationIsSet(key string) : boolAllSettings() : map[string]interface{}
İç içe geçmiş yapılandırmalara erişirken . ayırıcı kullanılır. Örneğin:
{
"server":{
"database":{
"url": "mysql...."
}
}
}GetString("server.database.url") ile iç içe erişim yapılabilir.
Yapılandırma Dosyasına Yazma
Viper geliştiricilerin çalışma zamanında depolanan yapılandırmayı yapılandırma dosyasına yazmasını kolaylaştıran bir dizi fonksiyon sağlar:
// WriteConfig yapılandırmayı orijinal yapılandırma dosyasına yazar. Dosya yoksa hata verir. Varsa üzerine yazar.
func WriteConfig() error { return v.WriteConfig() }
// SafeWriteConfig yapılandırmayı güvenli şekilde orijinal yapılandırma dosyasına yazar. Dosya yoksa yazar. Varsa üzerine yazmaz.
func SafeWriteConfig() error { return v.SafeWriteConfig() }
// WriteConfigAs geçerli yapılandırmayı belirtilen dosyaya yazar. Dosya yoksa hata döner. Varsa üzerine yazar.
func WriteConfigAs(filename string) error { return v.WriteConfigAs(filename) }
// SafeWriteConfigAs belirtilen dosya varsa orijinal yapılandırma dosyasına yazmaz. Dosya varsa hata döner.
func SafeWriteConfigAs(filename string) error { return v.SafeWriteConfigAs(filename) }Aşağıda bazı örnekler verilmiştir:
func TestWritingConfig(t *testing.T) {
viper.WriteConfig() // Yapılandırmayı orijinal dosyaya yazar. Bu dosyalar 'viper.AddConfigPath()' ve 'viper.SetConfigName' ile tanımlanmış olmalıdır
viper.SafeWriteConfig()
viper.WriteConfigAs("/path/to/my/.config")
viper.SafeWriteConfigAs("/path/to/my/.config") // Belirtilen dosya var olduğu için hata dönecektir
viper.SafeWriteConfigAs("/path/to/my/.other_config")
}İzleme ve Yeniden Yükleme
Viper uygulamaların çalışma zamanında yapılandırma dosyasını dinamik olarak okumasına izin verir. Yani uygulamayı yeniden başlatmadan güncellenmiş yapılandırmanın etkili olmasını sağlar. Her değişikliği kaçırmez. Viper örneğine yapılandırma değişikliklerini izlemesini söylemek yeterlidir. Veya her değişiklik olduğunda çalıştırılması için Viper'a bir fonksiyon sağlayabilirsiniz:
func TestWatchingConfig(t *testing.T) {
viper.OnConfigChange(func(e fsnotify.Event) {
fmt.Println("Yapılandırma dosyası değiştirildi:", e.Name)
})
viper.WatchConfig()
}Takma Adlar
func TestAliases(t *testing.T) {
viper.RegisterAlias("a", "b")
viper.Set("a", 1)
viper.Set("b", 2) // a'nın yapılandırmasının üzerine yazacaktır
fmt.Println(viper.GetInt("a"))
}Alt Yapıları Çıkarma
Önceki bölümde iç içe geçmiş yapılandırmalara erişmek için . ayırıcı kullanıldığı belirtildi. Aslında viper.Sub() fonksiyonu ile alt yapıları çıkarmak da mümkündür. Dönüş değeri bir Viper örneğidir. Aşağıdaki örnek:
cache:
cache1:
max-items: 100
item-size: 64
cache2:
max-items: 200
item-size: 80cache1Config := viper.Sub("cache.cache1")
if cache1Config == nil { // Yoksa nil döner
panic("cache1 yapılandırması mevcut değil")
}İç İçe Ayırıcı Ayarlama
Belirtilen anahtar . içerdiğinde yanlış ayrıştırmayı önlemek için manuel olarak başka bir ayırıcı belirtmek gerekir. Örneğin:
viper.KeyDelimiter("/") // Ayırıcıyı / olarak ayarlaSerileştirme
Viper yapılandırmayı bir struct veya map'e serileştirmek için iki fonksiyon sağlar. İç içe yapıları da destekler:
Unmarshal(rawVal interface{}) : errorUnmarshalKey(key string, rawVal interface{}) : error
type config struct {
Port int
Name string
PathMap string `mapstructure:"path_map"`
}
var C config
err := viper.Unmarshal(&C)
if err != nil {
t.Fatalf("Struct'a serileştirilemiyor, %v", err)
}Serileştirme
Mevcut yapılandırmayı yapılandırma dosyasına saklamak için belirli bir formatta string'e serileştirir. Genellikle JSON, TOML, YAML, HCL, envfile, Java properties desteklenir.
TIP
Viper özel serileştirme formatlarını da destekler: Decoding custom formats with Viper - Márk Sági-Kazár (sagikazarmark.hu)
import (
yaml "gopkg.in/yaml.v2"
// ...
)
func yamlStringSettings() string {
c := viper.AllSettings()
bs, err := yaml.Marshal(c)
if err != nil {
log.Fatalf("Yapılandırma YAML olarak serileştirilemiyor: %v", err)
}
return string(bs)
}Birden Fazla Örnek
Genellikle Viper tarafından sağlanan global örnek kullanmak için yeterlidir. Ancak bir örnek yalnızca bir yapılandırma dosyasıyla eşlenebildiğinden daha fazla işlem gerçekleştirmek için birden fazla örnek oluşturabilirsiniz. Örneğin:
x := viper.New()
y := viper.New()
x.SetDefault("ContentDir", "content")
y.SetDefault("ContentDir", "foobar")
//...