YouTube Summaries | How to Compose Interfaces in Golang
December 5th, 2023
Introduction:
The video introduces the concept of composability with interfaces in Golang, emphasizing its importance in real-life scenarios. As with all other video summaries, this is to help cement my learning after having watched the video, and I hope brings some learnings to you as well.
Use Case - Hash and Broadcast:
A common use case involves hash and broadcast with an IO reader. The following highlights the incorrect approach of using read all
directly on the reader.
// Incorrect approach
func hashAndBroadcast(reader io.Reader) {
data, err := ioutil.ReadAll(reader)
if err != nil {
return
}
hash := computeHash(data)
fmt.Println("Hash:", hash)
// Broadcasting logic
}
Interface Composability Solution:
Instead, lets look at this problem using interface composability, creating a new type, HashReader
, which embeds the io.Reader
interface and adds a hash function.
// Interface composability solution
type HashReader struct {
io.Reader
}
// Adding a hash function to HashReader
func (hr *HashReader) Hash() string {
data, _ := ioutil.ReadAll(hr.Reader)
return computeHash(data)
}
// Creating a HashReader instance
func NewHashReader(reader io.Reader) *HashReader {
return &HashReader{Reader: reader}
}
Implementation:
We then use the HashReader
in the hash and broadcast scenario, where the benefits of composability can be seen for testing and maintainability.
// Using HashReader in hash and broadcast scenario
func hashAndBroadcast(reader io.Reader) {
hashReader := NewHashReader(reader)
hash := hashReader.Hash()
fmt.Println("Hash:", hash)
// Broadcasting logic
}
Refinement with Interface Composability:
The video refines the interface composability by introducing an interface, HashReader
, with io.Reader
embedding and a hash function.
// Improved interface composability
type HashReader interface {
io.Reader
Hash() string
}
// Creating a HashReader instance
func NewHashReader(reader io.Reader) HashReader {
return &hashReaderImpl{Reader: reader}
}
// Implementation of HashReader interface
type hashReaderImpl struct {
io.Reader
}
func (hr *hashReaderImpl) Hash() string {
data, _ := ioutil.ReadAll(hr.Reader)
return computeHash(data)
}