Golang, also known as Go, is a statically typed, compiled language known for its simplicity and efficiency. One of the key features of Go is its use of interfaces.

What are Golang Interfaces?

Interfaces in Go provide a way to specify the behavior of an object. If something can do this, then it can be used here. Interfaces define a set of methods that a type should have, but they don’t describe how the methods should be implemented.

Why Use Interfaces?

Interfaces allow us to write functions that can be used with different types and are a way to achieve polymorphism in Go. They let us write code that is flexible and adaptable to different situations.

How to Define an Interface

In Go, you define an interface like this:

type VowelsFinder interface {
    FindVowels() []rune
}

Implementing an Interface

Once we have defined an interface, we can create custom types that implement the interface. Here’s an example:

type MyString string
func (ms MyString) FindVowels() []rune {
    var vowels []rune
    for _, rune := range ms {
        if rune == 'a' || rune == 'e' || rune == 'i' || rune == 'o' || rune == 'u' {
            vowels = append(vowels, rune)
        }
    }
    return vowels
}

Using an Interface

We can use interfaces to write functions that can take different types as parameters. Here’s an example:

func printVowels(vf VowelsFinder) {
    fmt.Println(vf.FindVowels())
}

Empty Interface

In Go, there is a special interface, the empty interface, which is defined as interface{}. Since there is no requirement of any methods to be implemented for this interface, all types implement the empty interface. It’s similar to Object in Java or object in C#.

var myObj interface{}
myObj = 5
fmt.Printf("%v", myObj) // prints: 5

Type Assertion

Type assertion is used extract the underlying value of the interface. Here’s an example:

var myObj interface{} = "Go"
value, ok := myObj.(string)
if ok {
    fmt.Printf("Value: %s", value) // prints: Value: Go
} else {
    fmt.Println("Not a string")
}

Type Switches

Type switches are a way to check the type of an interface. They are similar to regular switch statements, but they switch on the type of the interface.

var myObj interface{} = "Go"
switch value := myObj.(type) {
case string:
    fmt.Printf("It's a string: %s", value)
case int:
    fmt.Printf("It's an int: %d", value)
default:
    fmt.Printf("Unknown type")
}

Interface Composition

Go does not support inheritance, but it does support composition. Interfaces can be composed into other interfaces, similar to how structs can be composed of other structs.

type Reader interface {
    Read(b []byte) (n int, err error)
}

type Writer interface {
    Write(b []byte) (n int, err error)
}

// The ReadWriter interface is composed of Reader and Writer
type ReadWriter interface {
    Reader
    Writer
}

Conclusion

Interfaces are a powerful tool in Go, allowing for more flexible and adaptable code. They are a fundamental part of Go and understanding them is key to mastering the language. Whether you’re defining your own interfaces or using the ones provided by Go’s standard library, interfaces can help you write clean, idiomatic Go code. Happy coding!