9. Message Filter

Message Filter

Textio is introducing a feature that allows users to filter their messages based on specific criteria. For this feature, messages are categorized into three types: TextMessage, MediaMessage, and LinkMessage. Users can filter their messages to view only the types they are interested in.

Assignment

Your task is to implement a function that filters a slice of messages based on the message type.

Complete the filterMessages function. It should take a slice of Message interfaces and a string indicating the desired type ("text", "media", or "link"). It should return a new slice of Message interfaces containing only messages of the specified type.

Starting code

package main

type Message interface {
	Type() string
}

type TextMessage struct {
	Sender  string
	Content string
}

func (tm TextMessage) Type() string {
	return "text"
}

type MediaMessage struct {
	Sender    string
	MediaType string
	Content   string
}

func (mm MediaMessage) Type() string {
	return "media"
}

type LinkMessage struct {
	Sender  string
	URL     string
	Content string
}

func (lm LinkMessage) Type() string {
	return "link"
}

// Don't touch above this line

func filterMessages(messages []Message, filterType string) []Message {

	result:= []Message{}
	
	for _, mesType:= range messages{
		if mesType.Type() == filterType{
			result = append(result, mesType)
		}
	}
	return result
}

Go Message Filter Solution - Walkthrough

The Problem

Filter a slice of messages to only include messages of a specific type ("text", "media", or "link").

My Solution

Step-by-Step Breakdown

1

Create empty result slice

What this does:

  • Creates an empty slice that will hold Message interface types.

  • This is where we'll collect all the messages that match our filter.

2

Loop through all messages

What this does:

  • Iterates through each message in the input slice.

  • _ ignores the index (we don't need it).

  • mesType is the current message we're examining.

3

Check if message matches filter

What this does:

  • mesType.Type() calls the Type() method on the current message, returning "text", "media", or "link".

  • Compares it to the filterType parameter (the desired filter).

4

Add matching messages to result

What this does:

  • If the message type matches, add the entire message object to our result slice.

  • append(result, mesType) adds mesType to the end of result.

  • We assign back to result because append returns the updated slice.

5

Return the filtered results

What this does:

  • Returns the slice containing only messages that matched the filter.

  • If no messages matched, returns an empty slice [].

How It Works - Example Walkthrough

Let's say we call:

With these messages:

Iteration by iteration:

  • Iteration 1: TextMessage.Type() == "text" β†’ add

  • Iteration 2: MediaMessage.Type() == "media" β†’ skip

  • Iteration 3: TextMessage.Type() == "text" β†’ add

  • Iteration 4: LinkMessage.Type() == "link" β†’ skip

Return: [TextMessage, TextMessage]

Understanding the Interface

The key concept here is polymorphism through interfaces:

  • Any type that has a Type() string method is a Message.

  • TextMessage, MediaMessage, and LinkMessage all implement this.

  • We can treat them all as Message types in our function, and call Type() to distinguish them.

The Filter Pattern

This is a classic filter pattern:

Key Takeaways

  1. Start with result := []Type{} when building a filtered list.

  2. Use for _, item := range slice when you only need elements.

  3. Call methods on interface types (mesType.Type()).

  4. Use result = append(result, item) to grow slices.

  5. Filter logic: check condition, append if true, skip if false.

Common Variations

Filter with multiple conditions:

Count instead of collect:

Transform while filtering: