diff --git a/README.md b/README.md
index 0738fbbe..2a0bd674 100644
--- a/README.md
+++ b/README.md
@@ -104,6 +104,7 @@ Wasm Workers Server focuses on simplicity. We want you to run workers (written i
| --- | --- | --- |
| Rust | ✅ | No |
| JavaScript | ✅ | No |
+| Go | ✅ | No |
| Ruby | ✅ | [Yes](https://workers.wasmlabs.dev/docs/languages/ruby#installation) |
| Python | ✅ | [Yes](https://workers.wasmlabs.dev/docs/languages/python#installation) |
| ... | ... | ... |
diff --git a/docs/docs/features/dynamic-routes.md b/docs/docs/features/dynamic-routes.md
index 55416621..c4dea997 100644
--- a/docs/docs/features/dynamic-routes.md
+++ b/docs/docs/features/dynamic-routes.md
@@ -21,6 +21,7 @@ Check these guides to understand how to read parameters in the different support
* [Dynamic routes in Rust](../languages/rust.md#dynamic-routes)
* [Dynamic routes in Python](../languages/python.md#dynamic-routes)
* [Dynamic routes in Ruby](../languages/ruby.md#dynamic-routes)
+* [Dynamic routes in Go](../languages/go.md#dynamic-routes)
## Dynamic routes and folders
diff --git a/docs/docs/features/environment-variables.md b/docs/docs/features/environment-variables.md
index b46d13c6..4df03032 100644
--- a/docs/docs/features/environment-variables.md
+++ b/docs/docs/features/environment-variables.md
@@ -22,6 +22,7 @@ Then, you can read them in your worker:
* [Read environment variables in Rust](../languages/rust.md#read-environment-variables)
* [Read environment variables in Python](../languages/python.md#read-environment-variables)
* [Read environment variables in Ruby](../languages/ruby.md#read-environment-variables)
+* [Read environment variables in Go](../languages/go.md#read-environment-variables)
## Inject existing environment variables
diff --git a/docs/docs/features/key-value.md b/docs/docs/features/key-value.md
index ac0c8874..f077183d 100644
--- a/docs/docs/features/key-value.md
+++ b/docs/docs/features/key-value.md
@@ -20,6 +20,7 @@ The worker may access all the data and perform changes over it. Then, a new K/V
* [Add a K/V store to Rust workers](../languages/rust.md#add-a-key--value-store)
* [Add a K/V store to Python workers](../languages/python.md#add-a-key--value-store)
* [Add a K/V store to Ruby workers](../languages/ruby.md#add-a-key--value-store)
+* [Add a K/V store to Go workers](../languages/go.md#add-a-key--value-store)
## Limitations
diff --git a/docs/docs/get-started/quickstart.md b/docs/docs/get-started/quickstart.md
index 77de0384..92ee3e12 100644
--- a/docs/docs/get-started/quickstart.md
+++ b/docs/docs/get-started/quickstart.md
@@ -63,5 +63,6 @@ Now you got the taste of Wasm Workers, it's time to create your first worker:
* [Create your first Rust worker](../languages/rust.md)
* [Create your first Python worker](../languages/python.md)
* [Create your first Ruby worker](../languages/ruby.md)
+* [Create your first Go worker](../languages/go.md)
And if you are curious, here you have a guide about [how it works](./how-it-works.md).
\ No newline at end of file
diff --git a/docs/docs/languages/go.md b/docs/docs/languages/go.md
new file mode 100644
index 00000000..9cac573c
--- /dev/null
+++ b/docs/docs/languages/go.md
@@ -0,0 +1,331 @@
+---
+sidebar_position: 5
+---
+
+# Go
+
+Go workers are compiled into a WASI module using [TinyGo](https://tinygo.org/docs/guides/webassembly/). Then, they are loaded by Wasm Workers Server and start processing requests.
+
+## Your first Go worker
+
+Workers can be implemented either as an [http.Handler](https://pkg.go.dev/net/http#Handler) or an [http.HandlerFunc](https://pkg.go.dev/net/http#HandlerFunc).
+
+In this example, the worker will get a request and print all the related information.
+
+1. Create a new Go mod project
+
+ ```
+ go mod init workers-in-go
+ ```
+
+1. Add the Wasm Workers Server Go dependency
+
+ ```
+ go get -u github.com/vmware-labs/wasm-workers-server/kits/go/worker
+ ```
+
+1. Create a `worker.go` file with the following contents:
+
+ ```go title="worker.go"
+ package main
+
+ import (
+ "net/http"
+
+ "github.com/vmware-labs/wasm-workers-server/kits/go/worker"
+ )
+
+ func main() {
+ worker.ServeFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("x-generated-by", "wasm-workers-server")
+ w.Write([]byte("Hello wasm!"))
+ })
+ }
+ ```
+
+1. Additionally, you can now go further add all the information from the received `http.Request`:
+
+ ```go title="worker.go"
+ package main
+
+ import (
+ "fmt"
+ "io"
+ "net/http"
+
+ "github.com/vmware-labs/wasm-workers-server/kits/go/worker"
+ )
+
+ func main() {
+ worker.ServeFunc(func(w http.ResponseWriter, r *http.Request) {
+ var payload string
+
+ reqBody, err := io.ReadAll(r.Body)
+ if err != nil {
+ panic(err)
+ }
+ r.Body.Close()
+
+ if len(reqBody) == 0 {
+ payload = "-"
+ } else {
+ payload = string(reqBody)
+ }
+
+ body := fmt.Sprintf(""+
+ "
"+
+ "This page was generated by a Go file running in WebAssembly."+
+ "
"+
+ ""+
+ "", r.URL.String(), r.Method, r.UserAgent(), payload)
+
+ w.Header().Set("x-generated-by", "wasm-workers-server")
+ w.Write([]byte(body))
+ })
+ }
+ ```
+
+1. In this case, you need to compile the project to Wasm ([WASI](https://wasi.dev/)). To do this, make sure you have installed the TinyGo compiler by following the steps [here](https://tinygo.org/getting-started/install/):
+
+ ```bash
+ tinygo build -o worker.wasm -target wasi worker.go
+ ```
+
+1. Run your worker with `wws`. If you didn't download the `wws` server yet, check our [Getting Started](../get-started/quickstart.md) guide.
+
+ ```bash
+ wws .
+
+ ⚙️ Loading routes from: .
+ 🗺 Detected routes:
+ - http://127.0.0.1:8080/worker
+ => worker.wasm (name: default)
+ 🚀 Start serving requests at http://127.0.0.1:8080
+ ```
+
+1. Finally, open in your browser.
+
+## Add a Key / Value store
+
+Wasm Workers allows you to add a Key / Value store to your workers. Read more information about this feature in the [Key / Value store](../features/key-value.md) section.
+
+To add a KV store to your worker, follow these steps:
+
+1. Create a new Go project:
+
+ ```bash
+ go mod init worker-kv
+ ```
+
+1. Add the Wasm Workers Server Go dependency
+
+ ```
+ go get -u github.com/vmware-labs/wasm-workers-server/kits/go/worker
+ ```
+
+1. Create a `worker-kv.go` file with the following contents:
+
+ ```go title="worker-kv.go"
+ package main
+
+ import (
+ "net/http"
+
+ "github.com/vmware-labs/wasm-workers-server/kits/go/worker"
+ )
+
+ func main() {
+ worker.ServeFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("x-generated-by", "wasm-workers-server")
+ w.Write([]byte("Hello wasm!"))
+ })
+ }
+ ```
+
+1. Then, let's read a value from the cache and update it:
+
+ ```go title="worker-kv.go"
+ package main
+
+ import (
+ "fmt"
+ "net/http"
+ "strconv"
+
+ "github.com/vmware-labs/wasm-workers-server/kits/go/worker"
+ )
+
+ func main() {
+ worker.ServeFunc(func(w http.ResponseWriter, r *http.Request) {
+ cache, _ := r.Context().Value(worker.CacheKey).(map[string]string)
+
+ var countNum uint32
+
+ if count, ok := cache["counter"]; ok {
+ n, _ := strconv.ParseUint(count, 10, 32)
+ countNum = uint32(n)
+ }
+
+ body := fmt.Sprintf(""+
+ ""+
+ "
Key / Value store in Go
"+
+ "
Counter: %d
"+
+ "
This page was generated by a Wasm module built from Go.
"+
+ "", countNum)
+
+ cache["counter"] = fmt.Sprintf("%d", countNum+1)
+
+ w.Header().Set("x-generated-by", "wasm-workers-server")
+ w.Write([]byte(body))
+ })
+ }
+ ```
+
+1. Compile the project to Wasm ([WASI](https://wasi.dev/)):
+
+ ```bash
+ tinygo build -o worker-kv.wasm -target wasi worker-kv.go
+ ```
+
+1. Create a `worker-kv.toml` file with the following content. Note the name of the TOML file must match the name of the worker. In this case we have `worker-kv.wasm` and `worker-kv.toml` in the same folder:
+
+ ```toml title="worker-kv.toml"
+ name = "workerkv"
+ version = "1"
+
+ [data]
+ [data.kv]
+ namespace = "workerkv"
+ ```
+
+1. Run your worker with `wws`. If you didn't download the `wws` server yet, check our [Getting Started](../get-started/quickstart.md) guide.
+
+ ```bash
+ wws .
+
+ ⚙️ Loading routes from: .
+ 🗺 Detected routes:
+ - http://127.0.0.1:8080/worker-kv
+ => worker-kv.wasm (name: default)
+ 🚀 Start serving requests at http://127.0.0.1:8080
+ ```
+
+1. Finally, open in your browser.
+
+## Dynamic routes
+
+You can define [dynamic routes by adding route parameters to your worker files](../features/dynamic-routes.md) (like `[id].wasm`). To read them in Go, follow these steps:
+
+1. Use the `worker.ParamsKey` context value to read in the passed in parameters:
+
+ ```go title="main.go"
+ package main
+
+ import (
+ "fmt"
+ "net/http"
+
+ "github.com/vmware-labs/wasm-workers-server/kits/go/worker"
+ )
+
+ func main() {
+ worker.ServeFunc(func(w http.ResponseWriter, r *http.Request) {
+ params, _ := r.Context().Value(worker.ParamsKey).(map[string]string)
+ ...
+ })
+ }
+ ```
+
+1. Then, you can read the values as follows:
+
+ ```go title="main.go"
+ package main
+
+ import (
+ "fmt"
+ "net/http"
+
+ "github.com/vmware-labs/wasm-workers-server/kits/go/worker"
+ )
+
+ func main() {
+ worker.ServeFunc(func(w http.ResponseWriter, r *http.Request) {
+ params, _ := r.Context().Value(worker.ParamsKey).(map[string]string)
+ id := "the value is not available"
+
+ if val, ok := params["id"]; ok {
+ id = val
+ }
+
+ w.Header().Set("x-generated-by", "wasm-workers-server")
+ w.Write([]byte(fmt.Sprintf("Hey! The parameter is: %s", id)))
+ })
+ }
+ ```
+
+## Read environment variables
+
+Environment variables are configured [via the related TOML configuration file](../features/environment-variables.md). These variables are accessible via `os.Getenv` in your worker. To read them, just use the same name you configured in your TOML file:
+
+```toml title="envs.toml"
+name = "envs"
+version = "1"
+
+[vars]
+MESSAGE = "Hello 👋! This message comes from an environment variable"
+```
+
+Now, you can read the `MESSAGE` variable using the [`os.Getenv`](https://pkg.go.dev/os#Getenv) function:
+
+```go title="envs.go"
+package main
+
+import (
+ "fmt"
+ "net/http"
+ "os"
+
+ "github.com/vmware-labs/wasm-workers-server/kits/go/worker"
+)
+
+func main() {
+ worker.ServeFunc(func(w http.ResponseWriter, r *http.Request) {
+ body := fmt.Sprintf("The message is: %s", os.Getenv("MESSAGE"))
+
+ w.Header().Set("x-generated-by", "wasm-workers-server")
+ w.Write([]byte(body))
+ })
+}
+
+```
+
+If you prefer, you can configure the environment variable value dynamically by following [these instructions](../features/environment-variables.md#inject-existing-environment-variables).
+
+## Other examples
+
+* [Basic](https://github.com/vmware-labs/wasm-workers-server/tree/main/examples/go-basic)
+* [Counter](https://github.com/vmware-labs/wasm-workers-server/tree/main/examples/go-kv)
+
+The Go kit was originally authored by Mohammed Nafees ([@mnafees](https://github.com/mnafees))
diff --git a/docs/src/components/HomepageFeatures/index.js b/docs/src/components/HomepageFeatures/index.js
index 0bfce5bc..42b4e46a 100644
--- a/docs/src/components/HomepageFeatures/index.js
+++ b/docs/src/components/HomepageFeatures/index.js
@@ -17,7 +17,7 @@ const FeatureList = [
emoji: "⚙️",
description: (
<>
- Create workers in different languages like JavaScript, Ruby, Python and Rust thanks to WebAssembly.
+ Create workers in different languages like JavaScript, Ruby, Python, Rust and Go thanks to WebAssembly.
>
),
},
diff --git a/docs/src/css/custom.css b/docs/src/css/custom.css
index 4b3844ec..08b1d584 100644
--- a/docs/src/css/custom.css
+++ b/docs/src/css/custom.css
@@ -99,4 +99,8 @@ a.menu__link[href*="languages/ruby"]::before {
a.menu__link[href*="languages/rust"]::before {
background-image: url(/img/languages/rust.svg);
-}
\ No newline at end of file
+}
+
+a.menu__link[href*="languages/go"]::before {
+ background-image: url(/img/languages/go.svg);
+}
diff --git a/docs/static/img/languages/go.svg b/docs/static/img/languages/go.svg
new file mode 100644
index 00000000..a17ee14f
--- /dev/null
+++ b/docs/static/img/languages/go.svg
@@ -0,0 +1,8 @@
+
\ No newline at end of file
diff --git a/examples/go-basic/main.go b/examples/go-basic/main.go
new file mode 100644
index 00000000..fbc6673b
--- /dev/null
+++ b/examples/go-basic/main.go
@@ -0,0 +1,59 @@
+package main
+
+import (
+ "fmt"
+ "io"
+ "net/http"
+
+ "github.com/vmware-labs/wasm-workers-server/kits/go/worker"
+)
+
+func main() {
+ worker.ServeFunc(func(w http.ResponseWriter, r *http.Request) {
+ var payload string
+
+ reqBody, err := io.ReadAll(r.Body)
+ if err != nil {
+ panic(err)
+ }
+ r.Body.Close()
+
+ if len(reqBody) == 0 {
+ payload = "-"
+ } else {
+ payload = string(reqBody)
+ }
+
+ body := fmt.Sprintf(""+
+ ""+
+ "Wasm Workers Server"+
+ ""+
+ ""+
+ ""+
+ ""+
+ ""+
+ ""+
+ ""+
+ "