Managing User Data with Filtering and Aggregation in Go

Introduction

Welcome to today's lesson on applying data filtering and aggregation in a real-world scenario using a user management system in Go. We'll start by building a foundational structure that can handle basic user operations. Then, we'll expand it by introducing more advanced functionalities that allow filtering and aggregating user data.

Starter Task Methods

In our starter task, we will implement a set of functions that manage basic operations on a collection of user data, specifically handling adding new users, retrieving user profiles, and updating user profiles.

Here are the starter task methods:

  • addUser(userID string, age int, country string, subscribed bool) bool - Adds a new user with the specified attributes. The parameters are passed by value since you're providing complete new values for the addition, and there's no need to track changes after the function call. Returns true if the user was added successfully and false if a user with the same userID already exists.
  • getUser(userID string) *UserProfile - Returns a pointer to the user's profile if the user exists; otherwise, returns nil.
  • updateUser(userID string, age *int, country *string, subscribed *bool) bool - Updates the user's profile based on non-nil parameters. Differently from addUser, notice the use of pointers which allows for selective updates; by passing a nil, you indicate that a specific field should remain unchanged. Returns true if the user exists and was updated; false otherwise.

To store the user data, we will define a UserProfile struct.

Starter Task Implementation

Here is the implementation of our starter task in Go:

package main

import (
    "fmt"
)

// UserProfile struct to store user details
type UserProfile struct {
    Age        int
    Country    string
    Subscribed bool
}

// UserManager to manage user profiles
type UserManager struct {
    users map[string]UserProfile
}

// NewUserManager creates a new UserManager
func NewUserManager() *UserManager {
    return &UserManager{users: make(map[string]UserProfile)}
}

// AddUser adds a new user
func (um *UserManager) addUser(userID string, age int, country string, subscribed bool) bool {
    if _, exists := um.users[userID]; exists {
        return false
    }
    um.users[userID] = UserProfile{Age: age, Country: country, Subscribed: subscribed}
    return true
}

// GetUser retrieves a user profile
func (um *UserManager) getUser(userID string) *UserProfile {
    if user, exists := um.users[userID]; exists {
        return &user
    }
    return nil
}

// UpdateUser updates a user's profile
func (um *UserManager) updateUser(userID string, age *int, country *string, subscribed *bool) bool {
    if user, exists := um.users[userID]; exists {
        if age != nil {
            user.Age = *age
        }
        if country != nil {
            user.Country = *country
        }
        if subscribed != nil {
            user.Subscribed = *subscribed
        }
        um.users[userID] = user
        return true
    }
    return false
}

func main() {
    um := NewUserManager()
    fmt.Println(um.addUser("u1", 25, "USA", true))   // true
    fmt.Println(um.addUser("u2", 30, "Canada", false)) // true
    fmt.Println(um.addUser("u1", 22, "Mexico", true))  // false

    user := um.getUser("u1")
    if user != nil {
        fmt.Println(user.Age) // 25
    }

    fmt.Println(um.updateUser("u1", intPointer(26), nil, nil)) // true
    fmt.Println(um.updateUser("u3", intPointer(19), stringPointer("UK"), boolPointer(false))) // false
}

func intPointer(i int) *int       { return &i }
func stringPointer(s string) *string { return &s }
func boolPointer(b bool) *bool    { return &b }

The code provides a basic user management system in Go:

  • It uses the UserProfile struct to store user details such as age, country, and subscription status.
  • The UserManager struct manages user profiles in a map, with user IDs as keys.
  • The NewUserManager function initializes UserManager with an empty map of users.
  • Helper functions (intPointer, stringPointer, boolPointer) are included to allow optional parameters to be easily passed when updating user profiles.
  • In the main function, users are added, retrieved, and updated to demonstrate the functionality of the user management system.
Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal