Golang Program to Create an Interface Named Mailer that Defines a Send Method


In this article we are going to create an interface named mailer that defines a send method using interfaces embedding as well as Function as parameter. Interface in go language is a collection of methods that define a set of behavior.

Algorithm

Create a Mailer interface with a Send function that accepts two parameters: the recipient's email address and the email body. If an error occurs during the sending procedure, the Send method should return an error.

Example 1

  • Make structs that represent various mailer implementations, such as SmtpMailer, SendGridMailer, and so on.

  • Implement the Send function for each mailer struct in accordance with their email sending logic.

  • Make a new struct named MailerFacade that has the Mailer interface.

  • This type serves as a container for the many mailer implementations.

  • Create instances of the mailer implementations in the main programme and wrap them in MailerFacade instances.

  • Save the MailerFacade instances in a Mailer interface slice. Iterate through the slice, calling the Send method on each mailer with the recipient's email address and the email body as arguments.

Example 2

  • Create functions that describe various email sending or writing logic, such as SendSMTPMail, SendSendGridMail, and so on.

  • Check that these methods have the same signature as the Mailer interface's Send method.

  • Create a slice of functions in the main programme, each having the same signature as the Send method.

  • Fill the slice with functions that reflect various email sending or writing logic.

  • Iterate across the slice, calling each function with the recipient's email address and email body as parameters.

Example 1

His Example allows interfaces to embed other interfaces, which make the embedded interface to inherit all the methods from the embedded interface. The code below defines multiple mailer implementations that satisfy the mailer interface. The main function creates the instances of the mailer and wraps them with a facade that iterates over a slice of the mailer function to send mails..

package main

import "fmt"

type Mailer interface {
   Send(string, string) error
}

type SmtpMailer struct{}

func (s *SmtpMailer) Send(to, body string) error {
   fmt.Printf("Sending SMTP mail to: %s\nBody: %s\n", to, body)
   return nil
}

type SendGridMailer struct{}

func (s *SendGridMailer) Send(to, body string) error {
   fmt.Printf("Sending SendGrid mail to: %s\nBody: %s\n", to, body)
   return nil
}

type FileMailer struct{}

func (f *FileMailer) Send(to, body string) error {
   fmt.Printf("Writing mail to file for: %s\nBody: %s\n", to, body)
   return nil
}

type MailerFacade struct {
   Mailer
}

func main() {
   smtpMailer := &SmtpMailer{}
   sendGridMailer := &SendGridMailer{}
   fileMailer := &FileMailer{}

   smtpMailerFacade := MailerFacade{smtpMailer}
   sendGridMailerFacade := MailerFacade{sendGridMailer}
   fileMailerFacade := MailerFacade{fileMailer}

   mailers := []Mailer{&smtpMailerFacade, &sendGridMailerFacade, &
fileMailerFacade}

   for _, mailer := range mailers {
      err := mailer.Send("emil@example.com", "Hello, World!")
      if err != nil {
         fmt.Printf("Error sending mail: %v\n", err)
      }
   }
}

Output

Sending SMTP mail to: email@example.com 
Body: Hello, World! 
Sending SendGrid mail to: email@example.com 
Body: Hello, World! 
Writing mail to file for: email@example.com
Body: Hello, World!

Example 2

In this example, we are going to use a slice of function in go language to choose different mail sending implementations. By this method we can easily swap between different mail sending techniques. The code below defines multiple functions representing different mailers and a main function that iterates over a slice of mailer function and calls each of them to write the sending mail to a file.

package main

import "fmt"

type Mailer interface {
   Send(to, body string) error
}

func SendSMTPMail(to, body string) error {
   fmt.Printf("Sending SMTP mail to: %s\nBody: %s\n", to, body)
   return nil
}

func SendSendGridMail(to, body string) error {
   fmt.Printf("Sending SendGrid mail to: %s\nBody: %s\n", to, body)
   return nil
}

func WriteMailToFile(to, body string) error {
   fmt.Printf("Writing mail to file for: %s\nBody: %s\n", to, body)
   return nil
}

func main() {
   mailers := []func(string, string) error{
      SendSMTPMail,
      SendSendGridMail,
      WriteMailToFile,
   }

   for _, mailer := range mailers {
      err := mailer("email@example.com", "Hello, World!")
      if err != nil {
         fmt.Printf("Error sending mail: %v\n", err)
      }
   }
}

Output

Sending SMTP mail to: email@example.com 
Body: Hello, World! 
Sending SendGrid mail to: email@example.com 
Body: Hello, World! 
Writing mail to file for: email@example.com
Body: Hello, World!

Conclusion

In this article we have discussed how we can create an interface named mailer that defines a send method, by using interface we have defined a common contract for different mailer implementations. Here we have discussed two methods including embedding interfaces and a main method.

Updated on: 13-Jul-2023

36 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements