DEV Community

Pascal Lleonart
Pascal Lleonart

Posted on

Small Go interfaces example: proof of identity cards

This post is a small example for Go interfaces. It is destined for beginners.

In this tutorial we will implement a ProofOfId interface that will permit to define required methods that an object must implement to be considered as a proof of id (such as your ID card, your driving license or your passport...) and a second interface CountriesList which defines the methods required to print a list of countries.

The goal of this tutorial is to learn about how interfaces works and how it "replaces" polymorphism/inheritance in other programming languages.

Project setup

$ mkdir proof-of-identity-checker && cd proof-of-identity-checker

$ go mod init <yourname>/proof-of-identity-checker
Enter fullscreen mode Exit fullscreen mode

Then open your editor in this folder.

Defining our interfaces

Create a new interfaces.go file:

package main

import "time"

type ProofOfId interface {
    getExpDate() time.Time
    getName() string
    getObtentionDate() time.Time
}

type CountriesList interface {
    getCountries() []string
}
Enter fullscreen mode Exit fullscreen mode

So, for a ProofOfId, we except that the object has the methods getExpDate(), getName() and getObtentionDate(), and for CountriesList, we except getCountries() method.

Functions requiring our interfaces

Now we're gonna create a new file named main.go:

package main

import "time"

// check if a proof of id is valid (it checks only dates here ;))
func IdentityVerification(proof ProofOfId) bool {
    // checking if
    // `proof.getObtentionDate() < time.Now() < proof.getExpDate()`
    if proof.getExpDate().After(time.Now()) &&
        proof.getObtentionDate().Before(time.Now()) {
        return true
    } else {
        return false
    }
}

// display in the console the list of the visited countries
func DisplayVisitedCountries(countriesList CountriesList) {
    countries := countriesList.getCountries()
    println("Visited countries:")
    for i := 0; i < len(countries); i++ {
        println(countries[i])
    }
}
Enter fullscreen mode Exit fullscreen mode

For more information about date comparison: https://www.geeksforgeeks.org/how-to-compare-times-in-golang/.

Proofs of identification implementation

Identification card

Create idcard.go:

package main

import "time"

type IdCard struct {
    Name          string
    ObtentionDate time.Time
    ExpDate       time.Time
}
Enter fullscreen mode Exit fullscreen mode

So our object has the required data for our ProofOfId interface. But actually this interface defines required method so we will implement them.

// ...

func (card IdCard) getName() string {
    return card.Name
}

func (card IdCard) getExpDate() time.Time {
    return card.ExpDate
}

func (card IdCard) getObtentionDate() time.Time {
    return card.ObtentionDate
}
Enter fullscreen mode Exit fullscreen mode

Driver's license

Create driver-license.go:

package main

import "time"

type DriverLicense struct {
    Name          string
    ObtentionDate time.Time
    ExpDate       time.Time
    Enterprise    string
}
Enter fullscreen mode Exit fullscreen mode

Please note that we will store a field Enterprise as well (for the driving school's enterprise name).

There's the methods for DriverLicense:

func (license DriverLicense) getName() string {
    return license.Name
}

func (license DriverLicense) getExpDate() time.Time {
    return license.ExpDate
}

func (license DriverLicense) getObtentionDate() time.Time {
    return license.ObtentionDate
}

// this function isn't required for `ProofOfId`, but it may be useful in another context
func (license DriverLicense) getEnterprise() string {
    return license.Enterprise
}
Enter fullscreen mode Exit fullscreen mode

Passport

Create passport.go:

package main

import "time"

type Passport struct {
    Name             string
    ObtentionDate    time.Time
    ExpDate          time.Time
    VisitedCountries []string
}
Enter fullscreen mode Exit fullscreen mode

As you can see, for Passport we're going to implement our two interfaces: ProofOfId and CountriesList.

func (passport Passport) getName() string {
    return passport.Name
}

func (passport Passport) getExpDate() time.Time {
    return passport.ExpDate
}

func (passport Passport) getObtentionDate() time.Time {
    return passport.ObtentionDate
}

func (passport Passport) getCountries() []string {
    return passport.VisitedCountries
}
Enter fullscreen mode Exit fullscreen mode

Testing

Return in main.go and implement a main() function:

// ...

func main() {
    // vars init. You can note that some fields aren't defined.
    // They will contain the default value, "" for strings, etc...)
    idCard := IdCard{
        // = tomorrow
        ObtentionDate: time.Now().Add(24 * time.Hour),
        ExpDate:       time.Now().Add(24 * time.Hour),
    }
    driverLicense := DriverLicense{
        // = yesterday
        ObtentionDate: time.Now().Add(-24 * time.Hour),
        ExpDate:       time.Now().Add(24 * time.Hour),
    }
    passport := Passport{
        ObtentionDate: time.Now().Add(-24 * time.Hour),
        // one hour ago
        ExpDate:       time.Now().Add(-1 * time.Hour),
        VisitedCountries: []string{
            "France",
            "Spain",
            "Belgium",
        },
    }

    println(IdentityVerification(idCard))
    println(IdentityVerification(driverLicense))
    println(IdentityVerification((passport)))

    DisplayVisitedCountries(passport)
}
Enter fullscreen mode Exit fullscreen mode

Now you can run go run . in your cmd:

$ go run .
false
true
false
Visited countries:
France
Spain
Belgium
Enter fullscreen mode Exit fullscreen mode

Conclusion

We saw that interfaces permits to link objects between them by specifying common methods. This is really powerful.

But you can also use interfaces in other languages, like in Typescript or Java.

If you want to learn more about how to use interfaces or inheritance/polymorphism in other languages, you can watch this video from CodeAestethic: The Flaws of Inheritance.

Top comments (0)