From 6beea1d4127d2d51bfdc75162423407c198d19da Mon Sep 17 00:00:00 2001 From: a73x Date: Sat, 21 Dec 2024 11:53:54 +0000 Subject: add date to posts --- public/posts/2024-12-08-01 | 109 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 public/posts/2024-12-08-01 (limited to 'public/posts/2024-12-08-01') diff --git a/public/posts/2024-12-08-01 b/public/posts/2024-12-08-01 new file mode 100644 index 0000000..b8c30c1 --- /dev/null +++ b/public/posts/2024-12-08-01 @@ -0,0 +1,109 @@ + + + + + + + + + + a73x + + + + + + +
+
+
+

a73x

+ high effort, low reward +
+

[{home /} {posts /posts} {ethos /ethos}]

+

posts/2024-12-08-01.html

+ +
+ +← Posts +

Simplifying Interfaces with Function Types

+

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.

+ + + +
+ + + + -- cgit v1.2.3