a73x
high effort, low reward← Posts
Simplifying Interfaces with Function Types
Table of Contents
In Go, you can define methods on type aliases, which means that we can define a type alias of a function, and then define methods on that function.
Example
Given the following interface
type DB interface {
Get(string) (string, error)
}
You can fulfill it using a function type like this:
type GetFn func(string) (string, error)
func (f GetFn) Get(a string) (string, error) {
return f(a)
}
Now you can use GetFn whenever a DB is required:
func main() {
var storeFn DB = GetFn(func(s string) (string, error) {
return "bar", nil
})
fmt.Println(storeFn.Get("Foo")) // Outputs: bar
}
You can try this example in this [Go Playground](https://go.dev/play/p/hyBNIMblafs
How it works
In Go, interfaces are implicitly through method sets, which means any type (including a function type) that defines the required methods satisfies the interface. By defining the Get method on the GetFn type, the compiler treats GetFn as a valid implementation of the DB interface.
This flexibility allows you to use function types as lightweight, dynamic implementations of interfaces, without the need for full struct definitions.
Application
One common use case for this pattern is testing. Instead of implementing a full mock, you can use an inline function to provide test specific behavior.
func TestHandler() {
mockDB := GetFn(func(key string) (string, error) {
if key == "foo" {
return "bar", nil
}
return "", fmt.Errorf("not found")
})
result, err := mockDB.Get("foo")
fmt.Println(result, err) // Outputs: bar, <nil>
}
This approach is not limited to testing. It’s also useful for dependency injection, where you can pass in lightweight or context specific implementations of an interface.
This pattern is similar to how http.HandleFunc works. In the HTTP package, http.HandlerFunc is a function type that fulfills the http.Handler interface by implementing its ServeHTTP method. This allows functions to act as handlers, providing great flexibility in designing web servers.