Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
I den här självstudien använder du en variantfunktionsflagga för att hantera upplevelser för olika användarsegment i ett exempelprogram, Quote of the Day. Du använder den variantfunktionsflagga som skapats i Använd variantfunktionsflaggor. Innan du fortsätter måste du skapa variantfunktionsflaggan med namnet Greeting (Hälsning ) i appkonfigurationsarkivet.
Förutsättningar
- Ett Azure-konto med en aktiv prenumeration. Skapa en kostnadsfritt.
- En App Configuration-butik, som visas i guiden för att skapa en App Configuration-butik.
- Gå 1.21 eller senare. Information om hur du installerar Go finns på sidan Go downloads (Go-nedladdningar).
- Azure App Configuration Go-provider v1.1.0 eller senare.
- Funktionshantering Go-biblioteket v1.1.0 eller senare.
- Följ självstudien Använd variantfunktionsflaggor och skapa variantfunktionsflaggan med namnet Greeting (Hälsning).
Konfigurera ett Go Gin-webbprogram
Skapa en ny katalog för Ditt Go-projekt och navigera till det:
mkdir quote-of-the-day cd quote-of-the-daySkapa en ny Go-modul:
go mod init quote-of-the-dayInstallera nödvändiga Go-paket:
go get github.com/gin-gonic/gin go get github.com/gin-contrib/sessions go get github.com/gin-contrib/sessions/cookie go get github.com/microsoft/Featuremanagement-Go/featuremanagement go get github.com/microsoft/Featuremanagement-Go/featuremanagement/providers/azappconfigSkapa en mallkatalog för dina HTML-mallar och lägg till nödvändiga HTML-filer:
mkdir templatesLägg till följande HTML-mallfiler från GitHub-lagringsplatsen och placera dem i
templateskatalogen:-
index.html- Mallen för startsidan -
login.html– Mallen för inloggningssidan
-
Skapa en fil med namnet
appconfig.gomed följande innehåll. Du kan ansluta till App Configuration-butik genom Microsoft Entra-ID, vilket rekommenderas, eller genom en anslutningssträng.package main import ( "context" "log" "os" "github.com/Azure/AppConfiguration-GoProvider/azureappconfiguration" "github.com/Azure/azure-sdk-for-go/sdk/azidentity" ) func loadAzureAppConfiguration(ctx context.Context) (*azureappconfiguration.AzureAppConfiguration, error) { // Get the endpoint from environment variable endpoint := os.Getenv("AZURE_APPCONFIG_ENDPOINT") if endpoint == "" { log.Fatal("AZURE_APPCONFIG_ENDPOINT environment variable is not set") } // Create a credential using DefaultAzureCredential credential, err := azidentity.NewDefaultAzureCredential(nil) if err != nil { log.Fatalf("Failed to create credential: %v", err) } // Set up authentication options with endpoint and credential authOptions := azureappconfiguration.AuthenticationOptions{ Endpoint: endpoint, Credential: credential, } // Set up options to enable feature flags options := &azureappconfiguration.Options{ FeatureFlagOptions: azureappconfiguration.FeatureFlagOptions{ Enabled: true, RefreshOptions: azureappconfiguration.RefreshOptions{ Enabled: true, }, }, } // Load configuration from Azure App Configuration appConfig, err := azureappconfiguration.Load(ctx, authOptions, options) if err != nil { log.Fatalf("Failed to load configuration: %v", err) } return appConfig, nil }
Använd variantfunktionsflaggan
Skapa en fil med namnet
main.gomed följande innehåll:package main import ( "context" "fmt" "log" "net/http" "strings" "github.com/Azure/AppConfiguration-GoProvider/azureappconfiguration" "github.com/gin-contrib/sessions" "github.com/gin-contrib/sessions/cookie" "github.com/gin-gonic/gin" "github.com/microsoft/Featuremanagement-Go/featuremanagement" "github.com/microsoft/Featuremanagement-Go/featuremanagement/providers/azappconfig" ) type Quote struct { Message string `json:"message"` Author string `json:"author"` } type WebApp struct { featureManager *featuremanagement.FeatureManager appConfig *azureappconfiguration.AzureAppConfiguration quotes []Quote } func main() { // Load Azure App Configuration appConfig, err := loadAzureAppConfiguration(context.Background()) if err != nil { log.Fatalf("Error loading Azure App Configuration: %v", err) } // Create feature flag provider featureFlagProvider, err := azappconfig.NewFeatureFlagProvider(appConfig) if err != nil { log.Fatalf("Error creating feature flag provider: %v", err) } // Create feature manager featureManager, err := featuremanagement.NewFeatureManager(featureFlagProvider, nil) if err != nil { log.Fatalf("Error creating feature manager: %v", err) } // Initialize quotes quotes := []Quote{ { Message: "You cannot change what you are, only what you do.", Author: "Philip Pullman", }, } // Create web app app := &WebApp{ featureManager: featureManager, appConfig: appConfig, quotes: quotes, } // Setup Gin with default middleware (Logger and Recovery) r := gin.Default() // Start server if err := r.Run(":8080"); err != nil { log.Fatalf("Failed to start server: %v", err) } fmt.Println("Starting Quote of the Day server on http://localhost:8080") fmt.Println("Open http://localhost:8080 in your browser") fmt.Println() }Aktivera konfigurations- och funktionsflaggauppdatering från Azure App Configuration med mellanprogrammet.
// Existing code // ... ... func (app *WebApp) refreshMiddleware() gin.HandlerFunc { return func(c *gin.Context) { go func() { if err := app.appConfig.Refresh(context.Background()); err != nil { log.Printf("Error refreshing configuration: %v", err) } }() c.Next() } } // The rest of existing code //... ...Konfigurera vägarna med följande innehåll:
// Existing code // ... ... func (app *WebApp) setupRoutes(r *gin.Engine) { // Setup sessions store := cookie.NewStore([]byte("secret-key-change-in-production")) store.Options(sessions.Options{ MaxAge: 3600, // 1 hour HttpOnly: true, Secure: false, // Set to true in production with HTTPS }) r.Use(sessions.Sessions("session", store)) r.Use(app.refreshMiddleware()) // Load HTML templates r.LoadHTMLGlob("templates/*.html") // Routes r.GET("/", app.homeHandler) r.GET("/login", app.loginPageHandler) r.POST("/login", app.loginHandler) r.GET("/logout", app.logoutHandler) } // Home page handler func (app *WebApp) homeHandler(c *gin.Context) { session := sessions.Default(c) username := session.Get("username") quote := app.quotes[0] var greetingMessage string var targetingContext featuremanagement.TargetingContext if username != nil { // Create targeting context for the user targetingContext = createTargetingContext(username.(string)) // Get the Greeting variant for the current user if variant, err := app.featureManager.GetVariant("Greeting", targetingContext); err != nil { log.Printf("Error getting Greeting variant: %v", err) } else if variant != nil && variant.ConfigurationValue != nil { // Extract the greeting message from the variant configuration if configValue, ok := variant.ConfigurationValue.(string); ok { greetingMessage = configValue } } } c.HTML(http.StatusOK, "index.html", gin.H{ "title": "Quote of the Day", "user": username, "greetingMessage": greetingMessage, "quote": quote, }) } func (app *WebApp) loginPageHandler(c *gin.Context) { c.HTML(http.StatusOK, "login.html", gin.H{ "title": "Login - Quote of the Day", }) } func (app *WebApp) loginHandler(c *gin.Context) { email := strings.TrimSpace(c.PostForm("email")) // Basic validation if email == "" { c.HTML(http.StatusOK, "login.html", gin.H{ "title": "Login - Quote of the Day", "error": "Email cannot be empty", }) return } if !strings.Contains(email, "@") { c.HTML(http.StatusOK, "login.html", gin.H{ "title": "Login - Quote of the Day", "error": "Please enter a valid email address", }) return } // Store email in session session := sessions.Default(c) session.Set("username", email) if err := session.Save(); err != nil { log.Printf("Error saving session: %v", err) } c.Redirect(http.StatusFound, "/") } func (app *WebApp) logoutHandler(c *gin.Context) { session := sessions.Default(c) session.Clear() if err := session.Save(); err != nil { log.Printf("Error saving session: %v", err) } c.Redirect(http.StatusFound, "/") } // Helper function to create TargetingContext func createTargetingContext(userID string) featuremanagement.TargetingContext { targetingContext := featuremanagement.TargetingContext{ UserID: userID, Groups: []string{}, } if strings.Contains(userID, "@") { parts := strings.Split(userID, "@") if len(parts) == 2 { domain := parts[1] targetingContext.Groups = append(targetingContext.Groups, domain) // Add domain as group } } return targetingContext } // The rest of existing code //... ...main.goUppdatera med följande innehåll:// Existing code // ... ... r := gin.Default() // Setup routes app.setupRoutes(r) // Start server if err := r.Run(":8080"); err != nil { log.Fatalf("Failed to start server: %v", err) } // The rest of existing code // ... ...
Skapa och köra appen
Ange miljövariabeln för autentisering och kör programmet:
go mod tidy go run .Öppna din webbläsare och gå till
http://localhost:8080. Välj Logga in längst upp till höger för att logga in som usera@contoso.com.
När du har loggat in visas ett långt hälsningsmeddelande för usera@contoso.com.
Klicka på Logga ut och logga in som userb@contoso.com. Du ser det enkla hälsningsmeddelandet.
Anmärkning
Det är viktigt för den här självstudien att använda dessa namn exakt. Så länge funktionen har konfigurerats som förväntat bör de två användarna se olika varianter.
Nästa steg
Om du vill veta mer om funktionshantering i Go fortsätter du till följande dokument: