Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
## Cursor Cloud specific instructions

### Repository structure

This is a **learning monorepo** of independent Go example projects. There is **no root `go.mod`** — each subdirectory is a standalone program. Seven subdirectories have their own `go.mod`; the rest are legacy GOPATH-style single-file programs.

### Go modules vs legacy directories

| Type | Directories | How to build/run |
|---|---|---|
| **go.mod projects** | `http-server`, `mongo-microservice`, `rest-kafka-mongo-microservice`, `htmx`, `ai/go-groq`, `connect-to-db-postgres`, `docker` | `cd <dir> && go build ./...` or `go run main.go` |
| **Legacy (no go.mod)** | All others (`helloworld`, `channels`, `closures`, `testing`, `benchmark`, etc.) | `cd <dir> && GO111MODULE=off go run main.go` or `GO111MODULE=off go build .` |

### Running tests

- Unit tests: `cd testing && GO111MODULE=off go test -v .`
- Benchmarks: `cd benchmark && GO111MODULE=off go test -bench=. .`

### Linting

- `go vet ./...` inside any go.mod directory
- `staticcheck ./...` (installed in `~/go/bin`) inside any go.mod directory
- For legacy directories: `cd <dir> && GO111MODULE=off go vet .`

### Running the HTTP server (primary demo app)

```
cd http-server && go run main.go
```
Listens on `:8000`. Verify with `curl http://localhost:8000/` (returns "Hello World").

### External-service-dependent projects (optional)

These projects require external services and are **not** needed for core development:

- `mongo-microservice`, `rest-kafka-mongo-microservice` — need MongoDB (`:27017`); docker-compose at `mongo-microservice/mongodb/docker-compose.yml`
- `kafka/producer`, `kafka/consumer`, `rest-kafka-mongo-microservice` — need Apache Kafka (`:9092`)
- `connect-to-db-postgres` — needs PostgreSQL (`:5432`); docker-compose at `.devcontainer/docker-compose.yml`
- `docker/*` — needs Docker daemon
- `ai/go-groq`, `htmx` — need `GROQ_API_KEY` env var

### Gotchas

- `pointers/basic/` has multiple files with `main` redeclared — this is a pre-existing repo issue. Build individual files with `GO111MODULE=off go run main.go`.
- `~/go/bin` must be on `PATH` to use `staticcheck`. It is added via `~/.bashrc`.
2 changes: 1 addition & 1 deletion ai/go-groq/go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module go-groq

go 1.22.2
go 1.22
51 changes: 27 additions & 24 deletions docker/api/main.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
package main

import (
"context"
"fmt"
"log"
"net/http"
"strconv"
"strings"

"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/client"
"golang.org/x/net/context"

//"html"
"log"
"net/http"

"github.com/gorilla/mux"

"strconv"
"strings"
)

func main() {
Expand All @@ -24,19 +24,19 @@ func main() {
router.HandleFunc("/containers", Containers)
router.HandleFunc("/networks", Networks)
router.HandleFunc("/swarm-nodes", SwarmNodes)
log.Fatal(http.ListenAndServe(":9090", router))
log.Fatal(http.ListenAndServe(":9090", router))

}

func Images(w http.ResponseWriter, r *http.Request) {

cli, err := client.NewEnvClient()
cli, err := newDockerClient()
if err != nil {
panic(err)
}

//List all images available locally
images, err := cli.ImageList(context.Background(), types.ImageListOptions{})
images, err := cli.ImageList(context.Background(), image.ListOptions{})
if err != nil {
panic(err)
}
Expand All @@ -49,23 +49,22 @@ func Images(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, htmlOutput)
}


func Containers(w http.ResponseWriter, r *http.Request) {

cli, err := client.NewEnvClient()
cli, err := newDockerClient()
if err != nil {
panic(err)
}

//Retrieve a list of containers
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{})
containers, err := cli.ContainerList(context.Background(), container.ListOptions{})
if err != nil {
panic(err)
}

//Iterate through all containers and display each container's properties
//fmt.Println("Image ID | Repo Tags | Size")
htmlOutput := "<html>"
htmlOutput := "<html>"
for _, container := range containers {
htmlOutput += strings.Join(container.Names, ",") + " | " + container.Image + "<br/>"
}
Expand All @@ -76,18 +75,18 @@ func Containers(w http.ResponseWriter, r *http.Request) {

func Networks(w http.ResponseWriter, r *http.Request) {

cli, err := client.NewEnvClient()
cli, err := newDockerClient()
if err != nil {
panic(err)
}

networks, err := cli.NetworkList(context.Background(), types.NetworkListOptions{})
networks, err := cli.NetworkList(context.Background(), network.ListOptions{})
if err != nil {
panic(err)
}

//List all networks
htmlOutput := "<html>"
htmlOutput := "<html>"
//fmt.Println("Network Name | ID")
for _, network := range networks {
htmlOutput += network.Name + " | " + network.ID + "<br/>"
Expand All @@ -99,18 +98,18 @@ func Networks(w http.ResponseWriter, r *http.Request) {

func SwarmNodes(w http.ResponseWriter, r *http.Request) {

cli, err := client.NewEnvClient()
cli, err := newDockerClient()
if err != nil {
panic(err)
}

swarmNodes, err := cli.NodeList(context.Background(), types.NodeListOptions{})
swarmNodes, err := cli.NodeList(context.Background(), swarm.NodeListOptions{})
if err != nil {
panic(err)
}

//List all nodes - works only in Swarm Mode
htmlOutput := "<html>"
htmlOutput := "<html>"
//fmt.Println("Name | Role | Leader | Status")
for _, swarmNode := range swarmNodes {
htmlOutput += swarmNode.Description.Hostname
Expand All @@ -119,3 +118,7 @@ func SwarmNodes(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, htmlOutput)

}

func newDockerClient() (*client.Client, error) {
return client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
}
38 changes: 20 additions & 18 deletions docker/apijson/main.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
package main

import (
"context"
"fmt"

"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
"golang.org/x/net/context"

//"html"
"log"
"net/http"
"strings"

"github.com/gorilla/mux"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/client"

"strings"
"github.com/gorilla/mux"
)

func main() {
Expand All @@ -29,31 +29,29 @@ func main() {

func Images(w http.ResponseWriter, r *http.Request) {

cli, err := client.NewEnvClient()
cli, err := newDockerClient()
if err != nil {
panic(err)
}

//List all images available locally
images, err := cli.ImageList(context.Background(), types.ImageListOptions{})
images, err := cli.ImageList(context.Background(), image.ListOptions{})
if err != nil {
panic(err)
}

fmt.Printf("%v", images)

fmt.Fprint(w, images)
}

func Containers(w http.ResponseWriter, r *http.Request) {

cli, err := client.NewEnvClient()
cli, err := newDockerClient()
if err != nil {
panic(err)
}

//Retrieve a list of containers
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{})
containers, err := cli.ContainerList(context.Background(), container.ListOptions{})
if err != nil {
panic(err)
}
Expand All @@ -71,12 +69,12 @@ func Containers(w http.ResponseWriter, r *http.Request) {

func Networks(w http.ResponseWriter, r *http.Request) {

cli, err := client.NewEnvClient()
cli, err := newDockerClient()
if err != nil {
panic(err)
}

networks, err := cli.NetworkList(context.Background(), types.NetworkListOptions{})
networks, err := cli.NetworkList(context.Background(), network.ListOptions{})
if err != nil {
panic(err)
}
Expand All @@ -94,12 +92,12 @@ func Networks(w http.ResponseWriter, r *http.Request) {

func SwarmNodes(w http.ResponseWriter, r *http.Request) {

cli, err := client.NewEnvClient()
cli, err := newDockerClient()
if err != nil {
panic(err)
}

swarmNodes, err := cli.NodeList(context.Background(), types.NodeListOptions{})
swarmNodes, err := cli.NodeList(context.Background(), swarm.NodeListOptions{})
if err != nil {
panic(err)
}
Expand All @@ -114,3 +112,7 @@ func SwarmNodes(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, htmlOutput)

}

func newDockerClient() (*client.Client, error) {
return client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
}
13 changes: 3 additions & 10 deletions docker/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"os"

"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
"github.com/docker/docker/pkg/stdcopy"
Expand All @@ -18,20 +17,14 @@ func main() {
}
cli.NegotiateAPIVersion(ctx)

// reader, err := cli.ImagePull(ctx, "go-multi-stage", types.ImagePullOptions{})
// if err != nil {
// panic(err)
// }
// io.Copy(os.Stdout, reader)

resp, err := cli.ContainerCreate(ctx, &container.Config{
Image: "go-multi-stage",
}, nil, nil, "")
}, nil, nil, nil, "")
if err != nil {
panic(err)
}

if err := cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil {
if err := cli.ContainerStart(ctx, resp.ID, container.StartOptions{}); err != nil {
panic(err)
}

Expand All @@ -44,7 +37,7 @@ func main() {
case <-statusCh:
}

out, err := cli.ContainerLogs(ctx, resp.ID, types.ContainerLogsOptions{ShowStdout: true})
out, err := cli.ContainerLogs(ctx, resp.ID, container.LogsOptions{ShowStdout: true})
if err != nil {
panic(err)
}
Expand Down
38 changes: 38 additions & 0 deletions docker/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
module github.com/donvito/learngo/docker

go 1.25.0

require (
github.com/docker/docker v28.5.2+incompatible
github.com/gorilla/mux v1.8.1
)

require (
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/containerd/errdefs v1.0.0 // indirect
github.com/containerd/errdefs/pkg v0.3.0 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/docker/go-connections v0.7.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/sys/atomicwriter v0.1.0 // indirect
github.com/moby/term v0.5.2 // indirect
github.com/morikuni/aec v1.1.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 // indirect
go.opentelemetry.io/otel v1.43.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 // indirect
go.opentelemetry.io/otel/metric v1.43.0 // indirect
go.opentelemetry.io/otel/trace v1.43.0 // indirect
golang.org/x/sys v0.42.0 // indirect
golang.org/x/time v0.15.0 // indirect
gotest.tools/v3 v3.5.2 // indirect
)
Loading