1. وائپر کی تعارف
گو ایپلیکیشنز میں تشکیل کے لئے ترتیب کا حل کی ضرورت کو سمجھنا
ایک مضمون اور برقرار کارروائی کے لئے توسیع اور ڈیویلپرز کو اپنے ایپلیکیشن لوجک کو کنفیگریشن سے الگ کرنا ضروری ہوتا ہے۔ یہ آپ کو کوڈ بیس بدلے بغیر ایپلیکیشن کے رویہ کو ترتیب دینے کی اجازت دیتا ہے۔ ایک کنفیگریشن حل اس تشکیل کو ممکن بناتا ہے اور کنفیگریشن ڈیٹا کی بیرونی بندش میں مدد فراہم کرتا ہے۔
گو ایپلیکیشنز اس طرح کے ایک نظام کی بہترین حالت میں فائدہ اٹھا سکتے ہیں، خاص طور پر جب وہ پیچیدگی میں بڑھتے ہیں اور مختلف اندراجی ماحولوں کا سامنا کرتے ہیں، مثلاً، ڈویلپمنٹ، اسٹیجنگ اور پروڈکشن۔ ہر اندراجی ماحول ممکن ہے کہ تصاویر کے کنکشن، اے پی آئی کی کلیدیں، پورٹ نمبرز، اور دیگر چیزوں کے لئے مختلف ترتیبات کی ضرورت ہو۔ ان قیمتوں کو ہارڈ کوڈ کرنا مسئلہ ہو سکتا ہے اور خطاء پذیر ہو سکتا ہے، چونکہ یہ مختلف کنفیگریشن کو منظم کرنے کے لئے مختلف کوڈ راستوں کا نگرانی کرتا ہے اور سینسٹو زراعی ڈیٹا کے بہران کی خطرہ بڑتی ہے۔
ویپر جیسا کنفیگریشن حل ان فکریں کو دور کرتا ہے جو دوسری طرح کے ترتیبات اور فارمیٹس کا ساتھ دیتا ہے۔
ویپر کا جائزہ اور کنفیگریشن کے انتظام میں اس کا کردار
ویپر ایک گولانگ ایپلیکیشنز کے لئے مکمل کنفیگریشن لائبریری ہے، جو تمام کنفیگریشن کی ضرورتوں کے لئے فیکٹو حل بنانے کا مقصد رکھتا ہے۔ یہ ٹویلو فیکٹر ایپ میتھوڈالوجی کی تصدیق کرتا ہے، جو محیط میں کنفیگریشن رکھنے کی تاکید کرتا ہے تاکہ اجراء کے مابین پورٹبلٹی حاصل ہو سکے۔
ویپر کا کردار کنفیگریشن کے انتظام میں درج ذیل کام کرتا ہے:
- مختلف فارمیٹس، مثل JSON، TOML، YAML، HCL، وغیرہ، میں کنفیگریشن فائلوں کو پڑھنا اور ان کو یون مارشل کرنا۔
- انوارمنٹ ویریابلز سے کنفیگریشن قیمتوں کو مستقل کرنا، اس طرح بیرونی کنفیگریشن زیر اثر ہونا۔
- کمانڈ لائن فلیگز کے ساتھ بائنڈنگ اور پڑھنا تاکہ رن ٹائم پر تشکیل کے اختیارات کو بدلیں۔
- ایپلیکیشن کے لیے معمولی اختیارات کی ڈیفالٹس کو مستقل کرنا جو خارجی طریقے سے فراہم نہیں کیے گئے ہوں۔
- کنفیگریشن فائلوں میں تبدیلیوں کی نگرانی کرنا اور لائیو ری لوڈنگ، جس سے لفت کی پیمائش ہوتی ہے اور تشکیل تبدیلیوں کی دائرہ کم کرنے کے لیے نرمی فراہم کرتا ہے۔
2. انسٹالیشن اور ترتیب
گولانگ ماڈیولز کا استعمال کرتے ہوئے ویپر کے انسٹالیشن
ویپر کو اپنے گولانگ پراجیکٹ میں شامل کرنے کے لئے، یقینی بنائیں کہ آپ کا پراجیکٹ پہلے ہی گولانگ ماڈیولز کو ڈپینڈنسی منیجمنٹ کے لئے استعمال کر رہا ہے۔ اگر آپ کے پاس پہلے ہی گولانگ پراجیکٹ ہے، تو آپ کے پراجیکٹ کی جڑ میں عام طور پر ایک go.mod
فائل ہوگی۔ اگر نہیں ہے، تو آپ وولو سیکچ کرنے کے لئے مندرجہ ذیل کمانڈ کو چلائیں:
go mod init <module-name>
<module-name>
کو آپ کے پراجیکٹ کا نام یا راستہ سے تبدیل کریں۔ جب آپ کے پراجیکٹ میں گولانگ ماڈیولز کو شروع کر دیا گیا ہو تو، آپ ویپر کو ایک ڈپینڈنسی کے طور پر شامل کرسکتے ہیں:
go get github.com/spf13/viper
یہ کمانڈ ویپر پیکیج کو فیچ کر کے اس کی ورژن کو آپ کی go.mod
فائل میں ریکارڈ کر دیتی ہے۔
گولانگ پراجیکٹ میں ویپر کی شروعات
ویپر کو آپ کے گولانگ پراجیکٹ کے اندر شروع کرنے کے لئے، آپ کو پہلے پیکیج کو امپورٹ کرنا ہوگا اور پھر ایک نیا ویپر کا مثال بنانا ہوگا یا پرمعین سنگلٹن کا استعمال کرنا ہوگا۔ نیچے دونوں کا ایک مثال دی گئی ہے:
package main
import (
"fmt"
"github.com/spf13/viper"
)
func main() {
// سنگلٹن کا استعمال کرتے ہوئے ویپر
viper.SetDefault("serviceName", "My Awesome Service")
// اختیار کے طور پر، نیا ویپر مثال بنا رہے ہیں
myViper := viper.New()
myViper.SetDefault("serviceName", "My New Service")
// سنگلٹن کا استعمال کر کے کنفیگریشن قیمت تک رسائی حاصل ہوتی ہے
serviceName := viper.GetString("serviceName")
fmt.Println("Service Name is:", serviceName)
// نیا ویپر کے استعمال کرتے ہوئے کنفیگریشن قیمت تک رسائی حاصل ہوتی ہے
newServiceName := myViper.GetString("serviceName")
fmt.Println("New Service Name is:", newServiceName)
}
اوپر دئیے گئے کوڈ میں، SetDefault
کا استعمال ایک کنفیگریشن کیلیئے ایک معمولی قیمت مقرر کرتا ہے۔ GetString
میتھڈ ایک قیمت کو واپس لاتا ہے۔ جب آپ یہ کوڈ چلاتے ہیں تو، یہ دونوں سنگلٹن انسٹنس اور نیا انسٹنس استعمال کر کے ہمارے ترتیب کے ناموں کا اشارہ کرتا ہے۔
3. کنفیگریشن فائلوں کی پڑھائی اور لکھائی
کنفیگریشن فائلوں کے ساتھ کام کرنا ویپر کی ایک بنیادی خصوصیت ہے۔ یہ آپ کی ایپلیکیشن کو اس کی کنفیگریشن کو بیرونی طریقہ سے رکھتا ہے تاکہ اسے بنایا بغیر اپ ڈیٹ کر سکے۔ نیچے، ہم مختلف کنفیگریشن فارمیٹس کی تشکیل کرنے اور ان سے کیسے پڑھا جائے اور ان میں سے کیسے لکھا جائے کا مطالعہ کریں گے۔
کنفیگری فارمیٹس (JSON، TOML، YAML، HCL، وغیرہ) کی تشکیل
Viper مختلف کنفیگری فارمیٹس (مثلاً JSON، TOML، YAML، HCL وغیرہ) کو سپورٹ کرتا ہے۔ شروع کرنے کیلئے، آپ کو وائپر کونفیگریشن فائل کا نام اور قسم تعین کرنا ہوگا:
v := viper.New()
v.SetConfigName("app") // بغیر ایکسٹینشن کے کنفیگری فائل کا نام
v.SetConfigType("yaml") // یا "json"، "toml"، "yml"، "hcl"، وغیرہ
// کنفیگری فائل تلاش کرنے کے راستے۔ اگر آپ کی کنفیگریشن فائل کی جگہ مختلف ہے، تو متعدد راستے شامل کریں
v.AddConfigPath("$HOME/.appconfig") // ٹپیکل یونکس صارف کنفیگ کی جگہ
v.AddConfigPath("/etc/appconfig/") // یونکس سسٹم وائڈ کنفیگریشن پاتھ
v.AddConfigPath(".") // کام کرنے کی ڈائریکٹری
کنفیگری فائل سے پڑھنا اور لکھنا
وائپر اسٹنس جانتا ہوا کہ کنفیگریشن فائلوں کو کہاں تلاش کرنا ہے اور کیا تلاش کرنا ہے، آپ اس سے کہہ سکتے ہیں کہ وہ کنفیگریشن پڑھے۔
if err := v.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
// کنفیگ فائل نہیں ملی؛ مطلوبہ ہو تو نظرانداز کریں یا دوسرے طریقہ سے منظوری دیں
log.Printf("کوئی کنفیگ فائل نہیں ملی۔ ابتدائی قیمتیں استعمال کر رہے ہیں، یا/اور ماحولی متغیرات.")
} else {
// کنفیگ فائل مل گئی لیکن کوئی دوسری خرابی پیش آ گئی
log.Fatalf("کنفیگ فائل پڑھنے میں خرابی، %s", err)
}
}
ترتیبات واپس کنفیگ فائل میں لکھنا ہو، یا نیا بنانا ہو، وائپر چند میتھڈز فراہم کرتا ہے۔ یہ ہے کہ آپ موجودہ کنفیگریشن فائل کو فائل میں کیسے لکھتے ہیں:
err := v.WriteConfig() // موجودہ کنفیگ کو `v.SetConfigName` اور `v.AddConfigPath` دی گئی مقرر کردہ راستہ پر لکھتا ہے
if err != nil {
log.Fatalf("کنفیگ فائل لکھنے میں خرابی، %s", err)
}
ڈیفالٹ کنفیگریشن قدریں مقرر کرنا
ڈیفالٹ قیمتیں اس صورت میں مددگار ہوتی ہیں جب کسی کو کنفیگری فائل یا ماحولی متغیرات میں کوئی کلید مقرر نہ ہوں۔
v.SetDefault("ContentDir", "content")
v.SetDefault("LogLevel", "debug")
v.SetDefault("Database.Port", 5432)
// ڈیفالٹ قیمت کے لیے زیادہ پیچیدہ ڈیٹا سٹرکچر
viper.SetDefault("Taxonomies", map[string]string{
"tag": "tags",
"category": "categories",
})
4. ماحولی متغیرات اور فلیگز کا انتظام
وائپر صرف کنفیگری فائلوں تک محدود نہیں ہے - یہ ماحولی متغیرات اور کمانڈ لائن فلیگز کو بھی انتظام کر سکتا ہے، جو ماحول کے اختصاصی ترتیبات کے ساتھ کام کرتے وقت کارآمد ثابت ہوتا ہے۔
ماحولی متغیرات اور فلیگز کو Viper سے باند کرنا
ماحولی متغیرات کو باند کرنا:
v.AutomaticEnv() // خودبخود وائپر کی کلیدوں سے ملتے جلتے ماحولی متغیرات کو تلاش کرتا ہے
v.SetEnvPrefix("APP") // دوسروں سے الگ کرنے کے لیے ماحولی متغیرات کے لیے پریفکس
v.BindEnv("port") // پورٹ ماحولی متغیر (مثلا APP_PORT) کو باند کرے
// آپ اپنے ایپ میں ماحولی متغیرات کو مختلف ناموں کے ساتھ بھی مماثل کر سکتے ہیں
v.BindEnv("database_url", "DB_URL") // یہ وائپر کو بتاتا ہے کہ "database_url" کنفیگیشن کی کی مقدار کے لیے DB_URL ماحولی متغیر کی قیمت استعمال کرے
pflag کے استعمال سے فلیگز کو باند کرنا:
var port int
// pflag کا استعمال کرتے ہوئے ایک فلیگ مقررکرنا
pflag.IntVarP(&port, "port", "p", 808, "ایپلیکیشن کے لیے پورٹ")
// فلیگ کو وائپر کی کلید سے مماثل کرنا
pflag.Parse()
if err := v.BindPFlag("port", pflag.Lookup("port")); err != nil {
log.Fatalf("کلید سے فلیگ باند کرنے میں خرابی، %s", err)
}
ماحولی اختصاصی ترتیبات کا انتظام
ایک ایپلیکیشن عموماً مختلف ماحولوں میں (ترقی، اسٹیجنگ، پروڈکشن وغیرہ) مختلف طریقے سے چلانا چاہتا ہے۔ وائپر ماحولی متغیرات سے کنفیگریشن حاصل کر سکتا ہے جو کنفیگ فائل کی ترتیبات کو ناظرانہ کرتے ہوئے ماحول کے اختصاصی ترتیبات کی اجازت دیتا ہے:
v.SetConfigName("config") // ڈیفالٹ کنفیگریشن فائل کا نام
// کنفیگریشن کو ماحولی متغیرات کی طرف سے اووررائی کیا جا سکتا ہے
// جو APP کے پریفکس کے ساتھ باقی کی کلید کو اوپر کی مقدار دیگی
v.SetEnvPrefix("APP")
v.AutomaticEnv()
// پروڈکشن ماحول میں، آپ APP_PORT ماحولی متغیر کی قیمت استعمال کر سکتے ہیں تاکہ پورٹ کی مقدار تبدیل ہو
fmt.Println(v.GetString("port")) // اگر ترتیب نہیں کی گئی ہو تو اس کی مقدار کنفیگ فائل یا ڈیفالٹ سے لی جائے گی
یاد رہے کہ آپ کو Viper کے ذریعے لوڈ ہونے والی کنفیگریشن کے اختلافات کو اپنے ایپلیکیشن کوڈ میں، ضرورت کے مطابق، منظم کرنا ہو سکتا ہے۔
5. ریموٹ کلید/مقدار اسٹور کی حمایت
Viper والد API کلید/مقدار اسٹورز جیسے etcd، Consul یا Firestore کو استعمال کرتے ہوئے اےپلیکیشن ترتیب دینے کی مضبوط حمایت فراہم کرتا ہے۔ یہ ترتیب کرتا ہے کہ ترتیبات کو وسیع انتشار یافتہ نظاموں میں مرکزی اندراج کیا جا سکے اور مستقبل میں تازہ ترتیبات کی اپ ڈیٹ ہو سکیں۔ علاوہ ازیں، Viper اہم ترتیب کے تیمنے کو رموز کاروائی کے ذریعے محفوظ کرنے کی اجازت دیتا ہے۔
Viper کو ریموٹ کلید/مقدار اسٹورز (etcd، Consul، Firestore وغیرہ) کے ساتھ متحد کرنا
Viper کو ریموٹ کلید/مقدار اسٹور کے ساتھ استعمال کرنے کے لئے، آپ کو اپنے گو اےپلیکیشن میں viper/remote
پیکیج کی خالی درآمد کرنی ہوگی۔
import _ "github.com/spf13/viper/remote"
Chaliye ایک مثال دیکھیں جہاں etcd کے ساتھ متحد ہو رہے ہیں:
import (
"log"
"github.com/spf13/viper"
_ "github.com/spf13/viper/remote"
)
func initRemoteConfig() {
viper.SetConfigType("json") // ریموٹ ترتیب فائل کی قسم سیٹ کریں
viper.AddRemoteProvider("etcd", "http://127...1:4001", "/config/myapp.json")
err := viper.ReadRemoteConfig() // ریموٹ ترتیب کو پڑھنے کی کوشش کریں
if err != nil {
log.Fatalf("ناکام ریموٹ ترتیب کو پڑھنے میں: %v", err)
}
log.Println("کامیابی سے ریموٹ ترتیب پڑھی گئی")
}
func main() {
initRemoteConfig()
// یہاں آپ کی اےپلیکیشن منطق ہوگی
}
اس مثال میں، Viper http://127...1:4001
پر چل رہے etcd سرور سے منسلک ہوتا ہے اور /config/myapp.json
پر واقع ترتیبات پڑھتا ہے۔ Consul جیسے دوسرے اسٹورز کے ساتھ کام کرتے وقت، "etcd"
کو "consul"
سے بدل دیں اور پرووائیڈر کے مخصوص پیرامیٹرات کو مطابقت سے ترتیب کریں۔
حفاظتی ترتیبات کا نظم کرنا
حساس ترتیبات، جیسے API کلید یا ڈیٹا بیس کی رازی ردیں، ہموار متن میں نہیں رکھنی چاہئیں۔ Viper محفوظ ترتیبات کو کلید/مقدار اسٹور میں رکھنا اور آپ کے اےپلیکیشن میں کھولنے کی اجازت دیتا ہے۔
اس خصوصیت کو استعمال کرنے کے لئے، یقینی بنائیں کہ محفوظ ترتیبات آپ کے کلید/مقدار اسٹور میں محفوظ ہیں۔ پھر Viper کا AddSecureRemoteProvider
استعمال کریں۔ اس کو etcd کے ساتھ استعمال کرتے ہوئے یہ ہے:
import (
"log"
"github.com/spf13/viper"
_ "github.com/spf13/viper/remote"
)
func initSecureRemoteConfig() {
const secretKeyring = "/path/to/secret/keyring.gpg" // آپ کی keyring فائل کا راستہ
viper.SetConfigType("json")
viper.AddSecureRemoteProvider("etcd", "http://127...1:4001", "/config/myapp.json", secretKeyring)
err := viper.ReadRemoteConfig()
if err != nil {
log.Fatalf("ریموٹ ترتیب کو پڑھنے میں ناکام: %v", err)
}
log.Println("کامیابی سے ریموٹ ترتیب پڑھی گئی اور ہمارے کنٹرولر کو ڈیکرپٹ کیا گیا")
}
func main() {
initSecureRemoteConfig()
// یہاں آپ کی اےپلیکیشن منطق ہوگی
}
اس مثال میں، AddSecureRemoteProvider
استعمال کیا گیا ہے، جس میں ڈیکرپشن کے لئے ضروری چابیوں کو شامل کرنے کا راستہ مخصوص کیا گیا ہے۔
6. کانفیگ تبدیلیوں کو مشاہدہ اور ہینڈل کرنا
Viper کی ایک طاقتور خصوصیت میں سے ایک ہے کہ وہ ایپلیکیشن کو دوبارہ چالو کیے بغیر تبدیل ہونے والی کانفیگ کی نظم کرنے اور اس پر پرقی کرنے کی اختیار دیتا ہے۔
کانفیگ تبدیلیوں کی مشاہدت اور دوبارہ ترتیبات کی پڑھائی
Viper fsnotify
پیکیج استعمال کرتا ہے کہ آپ کے ترتیب فائل کی تبدیلیوں کے لئے دیکھتا ہو۔ آپ ایک واچر کو ترتیب فائل کی تبدیلیوں کو ٹرگر کرنے کے لئے ترتیب کر سکتے ہیں:
import (
"log"
"github.com/fsnotify/fsnotify"
"github.com/spf13/viper"
)
func watchConfig() {
viper.WatchConfig()
viper.OnConfigChange(func(e fsnotify.Event) {
log.Printf("ترتیب فائل تبدیل ہوئی ہے: %s", e.Name)
// یہاں آپ اگر ضرورت ہو تو اپ ڈیٹڈ ترتیبات پڑھ سکتے ہیں
// سروسز کو دوبارہ ترتیب دینے یا متغیرات کو اپ ڈیٹ کرنے جیسی کوئی کارروائی کر سکتے ہیں
})
}
func main() {
viper.SetConfigName("myapp")
viper.AddConfigPath(".")
err := viper.ReadInConfig()
if err != nil {
log.Fatalf("کانفیگ فائل پڑھنے میں خرابی، %s", err)
}
watchConfig()
// یہاں آپ کی اےپلیکیشن منطق ہوگی
}
ایک چل رہی ایپلیکیشن میں تشکیلات کو اپ ڈیٹ کرنے کے ترجمہ کرنے کے لئے ٹریگرز
ایک چل رہی ایپلیکیشن میں، آپ مختلف ٹریگرز جیسے کہ سگنل، وقت کے مبنی نوکری یا API ریکویسٹ کے جواب میں تشکیلات کو اپ ڈیٹ کرنا چاہتے ہیں۔ آپ اپنی ایپلیکیشن کو وائپر کی دوبارہ پڑھی تشکیلات کے بنیاد پر اندری نیهات تازہ کرنے کے لئے سکھنحت بنا سکتے ہیں:
import (
"os"
"os/signal"
"syscall"
"time"
"log"
"github.com/spf13/viper"
)
func setupSignalHandler() {
signalChannel := make(chan os.Signal, 1)
signal.Notify(signalChannel, syscall.SIGHUP) // SIGHUP سگنل کا سننے کیلئے لسننگ
go func() {
for {
sig := <-signalChannel
if sig == syscall.SIGHUP {
log.Println("سگنل مل گیا. تشکیل دوبارہ پڑھ رہا ہے...")
err := viper.ReadInConfig() // کنفیگریشن دوبارہ پڑھیں
if err != nil {
log.Printf("کچھ بھی نہیں: %s", err)
} else {
log.Println("تشکیل کامیابی کے ساتھ دوبارہ پڑھا گیا ہے۔")
// نئی تشکیل پر اپنی ایپلیکیشن کو دوبارہ کنفیگر کریں
}
}
}
}()
}
func main() {
viper.SetConfigName("myapp")
viper.AddConfigPath(".")
err := viper.ReadInConfig()
if err != nil {
log.Fatalf("کنفیگ فائل پڑھنا: %s", err)
}
setupSignalHandler()
for {
// ایپلیکیشن کی مین لاجک
time.Sleep(10 * time.Second) // کچھ کام سمیٹ کریں
}
}
اس مثال میں، ہم نے ایک ہینڈلر سکیٹ اپ کیا ہے تاکہ SIGHUP
سگنل کے لیے سننے کیلئے۔ جب یہ موصول ہوتا ہے، تو وائپر کنفیگریشن فائل دوبارہ پڑھتا ہے اور اپلیکیشن کو پھر اپنی تشکیلات یا حالت کو ضرورت کے مطابق اپ ڈیٹ کرنا چاہئے۔
ہمیشہ یاد رکھیں کہ ان تشکیلات کا تجربہ کریں تاکہ یہ یقینی بنایا جا سکے کہ آپ کی ایپلیکیشن دینامک اپ ڈیٹس کا بہترین سرعت سے سن لیکر نمایاں ہو سکے۔