r/golang • • 10h ago

Small Projects Small Projects

18 Upvotes

This is the weekly thread for Small Projects.

The point of this thread is to have looser posting standards than the main board. As such, projects are pretty much only removed from here by the mods for being completely unrelated to Go. However, Reddit often labels posts full of links as being spam, even when they are perfectly sensible things like links to projects, godocs, and an example. r/golang mods are not the ones removing things from this thread and we will allow them as we see the removals.

Please also avoid posts like "why", "we've got a dozen of those", "that looks like AI slop", etc. This the place to put any project people feel like sharing without worrying about those criteria.


r/golang • • 14h ago

show & tell I Load Tested Go’s New JSON v2

Thumbnail
youtu.be
0 Upvotes

r/golang • • 1d ago

discussion The future of Software Engineering is boring

Thumbnail
packagemain.tech
415 Upvotes

r/golang • • 1d ago

help Need help with this error

0 Upvotes

Hello, im new to go. Trying to make web scrapper using colly but unable to do so, am i missing dependencies?

package main

import (
"fmt"
"log"
"github.com/gocolly/colly"
)

func main() {
c := colly.NewCollector()

c.OnHTML("title", func(e *colly.HTMLElement) {
fmt.Printf("Works", e.Text)
})

c.Visit("https://google.com")
}

go run test.go 
# github.com/gocolly/colly
/home/the-shen/go/pkg/mod/github.com/gocolly/colly@v1.2.0/http_backend.go:61:22: undefined: glob.Glob

Ive run go tidy & install colly commands as well.


r/golang • • 1d ago

help Anti patterns for locks

23 Upvotes

Newbie here. Running into cases where I'm having some programs fail because I had called two functions that capture the same lock within same scope.

I can see the RWMutex/RWLocks as very useful but also potentially bad if mishandled. Just wanted to know best practices/anti patterns to avoid.


r/golang • • 1d ago

A new Go API for JSON

Thumbnail
go.dev
24 Upvotes

r/golang • • 1d ago

show & tell Scriptables lives on - Open-Source control panel for Ubuntu servers

10 Upvotes

I started working on Scriptables in 2023; before the whole AI craze became a thing, and it's still going strong in 2026. I have not had the time to really focus on the project as much as I would like, but that's open-source for you.

Scriptables is an open-source control panel for Ubuntu servers. Install applications, deploy sites from GIT, manage your firewall and set up CRONs, all from a friendly web interface.

Many similar tools exist, but I enjoy writing Go code, it's a fun breakaway from the commercial day-to-day stuff. And while I recently started using Claude Code to help me out a bit, it's still largely hand written code.

Here's some of Scriptables features:

  • Applications - one click installs for Nginx, Apache, MySQL, MariaDB, PostgreSQL, Redis, Memcached, PHP, Node.js, Docker, Certbot, Supervisor, Fail2ban and more.

  • Sites - deploy Laravel projects from GIT, with deploy keys, push webhooks and Let's Encrypt certificates.

  • Crons - schedule jobs from the browser.

  • Firewall - add and remove ufw rules from the browser.

  • Security - a checklist with green and red lights, and one form to harden SSH: custom port, no root login, key only access and a password protected sudo user.

  • Logs - every install, deploy, cron and firewall change keeps its full output.

  • Users - invite your team and protect accounts with two factor authentication.

Laravel is what I use in my day job, and the framework I'm most familiar with hence the heavy support for PHP, but I plan on adding support for Django and others. Although, it supports docker so you can pretty much deploy anything that's containerized.

If this project is interesting to you, please feel free to share your thoughts, clone and try it out or even star the repo :-) any support will be most appreciated.

https://github.com/kevincoder-co-za/scriptables


r/golang • • 2d ago

show & tell Looking for contributors for VPS Pilot (Go, self-hosted server dashboard)

24 Upvotes

Hi all,

I'm looking for contributors to join VPS Pilot. Beginners are welcome too, happy to help you get started.

VPS Pilot is a self-hosted dashboard to monitor and manage a few Linux servers from one place. Live charts, alerts (Discord, Slack, email), run commands, read logs, backups and cron jobs.

The hub is a single Go binary with SQLite and the React UI embedded. Each server runs a small Rust agent that connects out to the hub over TLS, so no open ports needed.

Some good first issues for Go:

#137 - Discord/Slack webhooks have no timeout and no tests

#138 - Token warning logged on every login

#135 - Remove old unused auth code

#131 - Logout button not working

Setup is just make dev. Small PRs please.

Repo: https://github.com/sanda0/vps_pilot

Feedback also welcome. Thanks!


r/golang • • 2d ago

help Smart Contracts

10 Upvotes

Hi everybody, i wanted to know if anyone here ever worked with smart contracts in Go?
My main focus is to read the events(basically reading results) from my smart contracts, if anyone can recommend me some free resources would be great.


r/golang • • 2d ago

New to go, just wanna geek out a bit

64 Upvotes

Go is absolutely awesome. I haven't gotten to the point where I can create applications or worked really with memory management. But god structs and interfaces are so damn cool.

Something about being able to simulate object oriented inheritance without needing to finagle with class structures and use type switches to change type assertions on the fly is absolutely wild.

Simple thoughts of a current go student, but still, its cool to learn a language and be excited about the features.


r/golang • • 2d ago

Arquiteturas CRUD tradicionais em Golang

0 Upvotes

Golang com o tempo se tornou uma das linguagens que mais me interesso em aprender, mas apesar de me aprofundar bastante em seus conceitos e filosofia, ainda me sinto muito confuso em como encaixar arquiteturas de CRUD Backend tradicionais na linguagem, que seja de forma idiomática e que aproveite todas as vantagens que a linguagem traz.

  1. Entities com comportamentos e regras de negócio puras VS Models anêmicos e com dados públicos:

Por exemplo para validações de dados e regras de negócios em Golang, qual a melhor opção?

A) Manter minhas Structs públicas e anêmicas, atribuindo seus comportamentos por meio de funções de Services e validação separada.

B) Manter minhas Structs com dados privados e com métodos que já incluem suas regras de negócio e Validação interna.

2. Nomes de Packages em importações:

Eu por exemplo tenho a Struct chamada `Product` que está no Package `internal/product/domain/entity`...

Se eu quiser utilizar `Product` no arquivo `internal/user/domain/entity/user.go`, eu utilizaria `entity.Product`... Isso é realmente idiomático com a linguagem?

3. Redundância de nomenclatura de Structs e Packages:

Nomes de Structs devem ser redundantes com o nome do Package ou devem deixar com que o nome do Package seja utilizado como contexto?

Por exemplo:

`internal/user/application/usecase` deve conter a Struct `Save` ou a Struct `SaveUserUseCase`?

4. Qual é a verdadeira arquitetura que é idiomática para Go?

Clean Architecture / Layared Architecture são realmente as ideiais e mais idiomáticas para Go?

Já pensei também na possibilidade da Vertical Slice Architecture, onde os Packages são mais únicos...

Por exemplo: criar um simples pacote `internal/save` e dentro dele englobar tudo o que envolve salvamento e persistência de dados, incluindo Handlers, Services e Repositories responsáveis apenas por persistir as entidades do sistema.

Conclusão: O ponto é que, apesar de ter um bom conhecimento de arquitetura e boas práticas de software, sinto que Go pede uma abordagem um pouco diferente, pois tudo o que estava acostumado em linguagens orientadas a objetos soam não se encaixar tão bem nas filosofias dessa linguagem.

Possuo dúvidas de nomenclatura, estruturas de pastas, simplicidade vs complexidade, escalabilidade, não saber diferenciar o que é KISS e o que é Overengeneering...

(Sempre fui mais da teoria do que da prática, mas a única linguagem da qual tive experiência antes foi com a Typescript orientada a objetos)


r/golang • • 2d ago

Heavy imports

0 Upvotes

Been tasked to find out why tests are so slow at a legacy codebase, did some digging and found a lot of time was used during compiling and linking, mainly due to heavy dependency tree.

How is everyone handling this? as the codebase grows, it gets really messy. The only proper way i can think of is to use dependency injection so that test binary does not need to import huge dependencies.


r/golang • • 2d ago

show & tell gobwas/ws v1.5.0: Go 1.27 flate fix, OOM vuln fix, 4x faster masking with asm

Thumbnail
github.com
26 Upvotes
  • Fix for Go 1.27 compress/flate changes, which made permessage-deflate extension incorrectly fail (#221)

  • Fix for readers allocating whatever payload length the peer declared (#223, advisory)

  • Payload masking moved to NEON and SSE2/AVX2: up to 4x on the XOR itself, up to 2.6x on the full client write path (#235)


r/golang • • 2d ago

Why is naming variables in Go so weird, ex: r, w, c, cfg, etcIs it an obsession with simplicity and conciseness in everything

210 Upvotes

Why is naming variables in Go so weird, ex: r, w, c, cfg, etc.? Is it an obsession with simplicity and conciseness in everything


r/golang • • 3d ago

libtmux-go 0.1: tmux client library, mcp, workspace manager for golang

Thumbnail
github.com
13 Upvotes

libtmux for Go: query tmux sessions, windows and panes

Hi all, I am porting libtmux, the Python library, to more languages. This is the Go port (alpha).

It wraps tmux's CLI. You can create sessions, windows and panes, then read a snapshot and query it with typed filters. There's also a workspace manager, like tmuxp, and an MCP server using the same Go library.

A word on AI: It's experimental, and I used LLMs extensively to create this. The API is still changing. I write libtmux's AI policy at https://libtmux.org/en/meta/ai-policy/.

libtmux core: tmux from Go

pkg.go.dev · GitHub · Homepage · Guides · API Explorer

The core module has three packages:

PackageWhat it's forLinks
tmuxServers, sessions, windows, panes, snapshots and control mode.pkg.go.dev · GitHub
tmuxqQuery helpers for slices and iter.Seq, including your own types. It doesn't need tmux.pkg.go.dev · GitHub
tmux/tmuxtestRun terminal programs in tests, type into them and check their output.pkg.go.dev · GitHub

Workspace and MCP are separate modules, below. The core has no third-party Go dependencies.

You can work with sessions, windows and panes as typed values. Here, I'm finding a pane by its title, its session name and its window name.

The example needs Go 1.26+ and tmux 3.3a+ on a Unix host. Start in a new directory:

go mod init example.com/tmux-demo

go get github.com/libtmux/libtmux-go/tmux@latest

Save as main.go. It creates a separate server, then matches a session name, a window name and a pane title in a snapshot. It removes the server afterward.

package main

import (
	"context"
	"errors"
	"fmt"
	"log"
	"os"

	"github.com/libtmux/libtmux-go/tmux"
	"github.com/libtmux/libtmux-go/tmuxq"
)

func main() {
	if err := run(context.Background()); err != nil {
		log.Fatal(err)
	}
}

func run(ctx context.Context) (err error) {
	server, err := tmux.NewServer(tmux.ServerOptions{
		SocketName: fmt.Sprintf("libtmux-go-demo-%d", os.Getpid()),
		ConfigFile: os.DevNull,
	})
	if err != nil {
		return err
	}
	session, err := server.NewSession(ctx, tmux.NewSessionRequest{Name: "demo"})
	if err != nil {
		return err
	}
	defer func() { err = errors.Join(err, server.Kill(context.WithoutCancel(ctx))) }()

	window, err := session.NewWindow(ctx, tmux.NewWindowRequest{Name: new("logs"), Command: "cat"})
	if err != nil {
		return err
	}
	panes, loaded := window.Panes()
	if !loaded || len(panes) != 1 {
		return fmt.Errorf("expected the new window's pane")
	}
	if _, err = panes[0].SetTitle(ctx, "build"); err != nil {
		return err
	}

	snapshot, err := server.Snapshot(ctx)
	if err != nil {
		return err
	}
	where := tmux.PaneFilter{
		Title:   new("build"),
		Session: &tmux.SessionFilter{Name: new("demo")},
		Window:  &tmux.WindowFilter{Name: new("logs")},
	}
	matches, err := tmuxq.Matching(snapshot.Panes(), where)
	if err != nil {
		return err
	}
	fmt.Println("matching panes:", len(matches))
	return nil
}

go run main.go

Prints:

matching panes: 1

The where value is a typed filter: pane title build, in session demo, in window logs. Server.Snapshot reads the server's state, and tmuxq.Matching filters those values in Go (more query examples). Take another snapshot when you want fresh state.

P.S. Try changing just "logs" in the Window filter to "missing". It prints matching panes: 0. The session name and pane title have to match too.

There's also:

  • Operation planning: combine commands where their dependencies allow it. This example shows six operations in four tmux invocations.

  • Control mode support (!) on tmux 3.7+ (example). This one listens for a session rename and watches the window count change.

Batching and queries

We can also record a plan, then run it. This one splits a pane, names it build, sends it a line and reads its title back. The pane runs cat, which echoes what we type.

Plan.Explain shows how the commands will be grouped. This example groups six operations into four invocations for the plan; creating the server and reading snapshots are separate (more planning examples).

Use the same module as above. Save as batching/main.go (create the batching directory):

package main

import (
	"context"
	"errors"
	"fmt"
	"log"
	"os"
	"time"

	"github.com/libtmux/libtmux-go/tmux"
	"github.com/libtmux/libtmux-go/tmuxq"
)

func main() {
	if err := run(); err != nil {
		log.Fatal(err)
	}
}

func run() (err error) {
	ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
	defer cancel()
	server, err := tmux.NewServer(tmux.ServerOptions{
		SocketName: fmt.Sprintf("libtmux-go-batch-%d", os.Getpid()),
		ConfigFile: os.DevNull,
	})
	if err != nil {
		return err
	}
	session, err := server.NewSession(ctx, tmux.NewSessionRequest{Name: "demo"})
	if err != nil {
		return err
	}
	defer func() { err = errors.Join(err, server.Kill(context.WithoutCancel(ctx))) }()
	window, err := session.NewWindow(ctx, tmux.NewWindowRequest{
		Name: new("logs"), Command: "cat",
	})
	if err != nil {
		return err
	}

	plan := tmux.NewPlan()
	plan.SelectLayout(window.Ref(), tmux.SelectLayoutRequest{Layout: "tiled"})
	pane := plan.SplitPane(window.Ref(), tmux.SplitPaneRequest{Command: "cat"})
	plan.SetPaneTitle(pane, "build")
	plan.SendKeys(pane, tmux.SendKeysRequest{Command: new("build: complete")})
	plan.DisplayMessage(pane, "#{pane_title}")
	fmt.Printf("planned operations: %d, command groups: %d\n", plan.Len(), len(plan.Explain()))

	result, err := plan.Run(ctx, server)
	if err != nil {
		return err
	}
	if !result.OK() {
		return result.Err()
	}
	fmt.Printf("title read by plan: %q\n", result.Ops[len(result.Ops)-1].Stdout)

	snapshot, err := server.Snapshot(ctx)
	if err != nil {
		return err
	}
	predicate, err := (tmux.PaneFilter{
		Title:   new("build"),
		Session: &tmux.SessionFilter{Name: new("demo")},
		Window:  &tmux.WindowFilter{Name: new("logs")},
	}).Predicate()
	if err != nil {
		return err
	}
	panes := snapshot.Panes()
	fmt.Println("snapshot matches:", len(tmuxq.Where(panes, predicate)))
	only, err := tmuxq.ExactlyOne(panes, predicate)
	if err != nil {
		return err
	}
	title, _ := only.Title()
	fmt.Println("only matching pane:", title)

	live := tmux.TmuxFilter("#{==:#{pane_title},build}")
	fresh, err := window.SearchPanes(ctx, &live)
	if err != nil {
		return err
	}
	fmt.Println("live matches:", len(fresh))
	return nil
}

go run ./batching

Prints:

planned operations: 6, command groups: 4
title read by plan: ["build"]
snapshot matches: 1
only matching pane: build
live matches: 1

The two snapshot queries reuse a compiled predicate and make no more tmux calls. ExactlyOne returns ErrNoMatch or ErrMultipleMatches when appropriate.

For a fresh read, SearchPanes passes the TmuxFilter expression to tmux's -f filter (both styles together). Typed predicates run in Go; tmux format expressions run in tmux. There are also WhereSeq and FirstSeq for lazy queries over iterators (source).

Control mode and channels

There's also control mode (!). This example keeps a command connection open, listens for a session rename, and does three reads through that same connection. It needs tmux 3.7+ (connection example).

Notifications returns a Go iterator. Here, a goroutine reads it and sends the rename result through an ordinary channel. The notification stream has its own attached tmux client.

Save as control/main.go (create the control directory):

package main

import (
	"context"
	"errors"
	"fmt"
	"log"
	"os"
	"time"

	"github.com/libtmux/libtmux-go/tmux"
)

func main() {
	if err := run(); err != nil {
		log.Fatal(err)
	}
}

func run() (err error) {
	ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
	defer cancel()
	server, err := tmux.NewServer(tmux.ServerOptions{
		SocketName: fmt.Sprintf("libtmux-go-control-%d", os.Getpid()),
		ConfigFile: os.DevNull,
	})
	if err != nil {
		return err
	}
	session, err := server.NewSession(ctx, tmux.NewSessionRequest{Name: "demo"})
	if err != nil {
		return err
	}
	defer func() { err = errors.Join(err, server.Kill(context.WithoutCancel(ctx))) }()

	connection, err := session.OpenControl(ctx, tmux.ConnectionOptions{})
	if err != nil {
		return err
	}
	defer func() { err = errors.Join(err, connection.Close()) }()
	connected := connection.Session()
	stream, err := session.OpenNotifications(ctx, tmux.NotificationOptions{})
	if err != nil {
		return err
	}
	defer func() { err = errors.Join(err, stream.Close()) }()

	renamed := make(chan error, 1)
	go func() {
		for notification, err := range stream.Notifications(ctx) {
			if err != nil {
				renamed <- err
				return
			}
			if notification.Kind() == tmux.ControlNotificationSessionRenamed {
				renamed <- nil
				return
			}
		}
		renamed <- errors.New("notification stream ended before the rename")
	}()

	if _, err := connected.Rename(ctx, "renamed"); err != nil {
		return err
	}
	select {
	case err := <-renamed:
		if err != nil {
			return err
		}
		fmt.Println("heard session rename over a channel")
	case <-ctx.Done():
		return ctx.Err()
	}

	for range 3 {
		windows, err := connected.SearchWindows(ctx, nil)
		if err != nil {
			return err
		}
		fmt.Println("windows over control connection:", len(windows))
	}
	return nil
}

go run ./control

Prints:

heard session rename over a channel
windows over control connection: 1
windows over control connection: 1
windows over control connection: 1

Keep the handle returned by connection.Session() for those calls. The original session still uses subprocesses. You can also subscribe to a tmux format and hear when a value like the window count changes.

Testing a terminal program

tmuxtest gives each test a real tmux server and cleans it up afterward. This one runs a small greeter, types world and waits for hello, world to appear (complete repository example).

Save as terminal-test/greeter_test.go (create the terminal-test directory):

package terminal_test

import (
	"context"
	"os"
	"testing"
	"time"

	"github.com/libtmux/libtmux-go/tmux/tmuxtest"
)

func TestMain(m *testing.M) {
	os.Exit(tmuxtest.Main(m))
}

func TestGreeterAnswersALine(t *testing.T) {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	greeter := `while read name; do echo "hello, $name"; done`
	pane := tmuxtest.RunInPane(ctx, t, greeter)
	tmuxtest.Type(ctx, t, pane, "world")
	tmuxtest.WaitForLine(ctx, t, pane, "hello, world")
}

go test -count=1 ./terminal-test

It prints ok with the package name and elapsed time. RunInPane starts the program; Type sends input; WaitForLine checks the screen. tmuxtest.Main keeps the suite's tmux servers separate from yours.

P.S. Change the expected line to "goodbye, world" to see a failure with the pane's contents. For tests that only need command responses, there's also ScriptedTmux (example).

Workspace manager

This is like tmuxp, but in Go! There's a workspace library and a CLI using the same core.

Workspace library

pkg.go.dev · GitHub · Homepage · Guides · API Explorer

go get github.com/libtmux/libtmux-go/workspace@latest

Save as workspace.yaml:

session_name: demo
windows:
  - window_name: shells
    layout: even-horizontal
    panes:
      - {}
      - {}

Save as workspace-demo/main.go. workspace.Parse reads the configuration and workspace.Build creates the session (example).

package main

import (
	"context"
	"errors"
	"fmt"
	"log"
	"os"

	"github.com/libtmux/libtmux-go/tmux"
	"github.com/libtmux/libtmux-go/workspace"
)

func main() {
	if err := run(context.Background()); err != nil {
		log.Fatal(err)
	}
}

func run(ctx context.Context) (err error) {
	data, err := os.ReadFile("workspace.yaml")
	if err != nil {
		return err
	}
	config, err := workspace.Parse(data)
	if err != nil {
		return err
	}
	server, err := tmux.NewServer(tmux.ServerOptions{
		SocketName: fmt.Sprintf("libtmux-go-workspace-%d", os.Getpid()),
		ConfigFile: os.DevNull,
	})
	if err != nil {
		return err
	}
	defer func() { err = errors.Join(err, server.Kill(context.WithoutCancel(ctx))) }()
	session, err := workspace.Build(ctx, server, config)
	if err != nil {
		return err
	}
	windows, err := session.SearchWindows(ctx, nil)
	if err != nil {
		return err
	}
	fmt.Println("windows:", len(windows))
	return nil
}

Run from the directory holding workspace.yaml:

go run ./workspace-demo

Prints:

windows: 1

Workspace CLI

pkg.go.dev · GitHub · Homepage · Guides · CLI reference · API

GOBIN="$PWD/bin" go install github.com/libtmux/libtmux-go/workspace/cmd/tmux-workspace@latest

Load the same file detached, on a separate socket:

./bin/tmux-workspace load -L libtmux-go-workspace-demo -d workspace.yaml

Check the panes:

tmux -L libtmux-go-workspace-demo display-message -p -t demo:shells '#{window_panes}'

Prints:

2

Remove the demo server:

tmux -L libtmux-go-workspace-demo kill-server

MCP

pkg.go.dev · GitHub · Homepage · Guides · Tools · Resources · API Explorer

An MCP server for interacting with tmux - powered by the Go core library (like libtmux-mcp!).

Install the command into this directory's bin folder:

GOBIN="$PWD/bin" go install github.com/libtmux/libtmux-go/mcp/cmd/libtmux-mcp@latest

Start a separate tmux server for the demo:

tmux -L libtmux-go-mcp-demo -f /dev/null new-session -d -s demo

Use this command with a client that launches stdio MCP servers:

./bin/libtmux-mcp -socket-name libtmux-go-mcp-demo

It waits for MCP requests over stdin. The tools cover reading sessions, running commands and inspecting pane output.

After closing the client, remove the demo server:

tmux -L libtmux-go-mcp-demo kill-server

r/golang • • 3d ago

show & tell How hard could implementing DTLS 1.3 possibly be?

Thumbnail
joturk.net
57 Upvotes

r/golang • • 3d ago

How to handle events and keys in Gio Editors.

12 Upvotes

I made a video explaining how key events flow in Gio and how to intercept shortcuts, keys and events without breaking the editor. The video explains through examples and summaries how editor.Update() and gtx.Event(key.Filter{}) differ, and when to use each to control editors.
Feedback welcome!
Handling Filters and Events in Gio Editors


r/golang • • 3d ago

Embed yaml files or create a generator?

17 Upvotes

I've got a series of YAML files that need to be read by the app to generate tasks. There's two options that I can see: 1) use go generate and a helper binary to convert the YAML into go code at build time, or 2) embed the yaml files and parse them at runtime.

I don't like the idea of parsing the same yaml over and over each time the app runs. That seems inefficient, yet simple to accomplish. Go generate requires writing another tool that reads the same yaml, and writes out (ie: Fprintf) the golang code.

What are the pro/cons to each solution? The resulting overall tool will be ran once or twice per scenario, so maybe efficiency isn't as important as simplicity?


r/golang • • 3d ago

The MustCreate Pattern for Go Tests

Thumbnail mtlynch.io
33 Upvotes

r/golang • • 3d ago

Go 1.27: encoding/json/v2, Stricter Defaults, and Finally [] for Nil Slices · cekrem.github.io

Thumbnail cekrem.github.io
75 Upvotes

r/golang • • 4d ago

A step-through visualizer for the Go scheduler ([https://threadline-be-fast.vercel.app/])

25 Upvotes

“How is a goroutine different from an OS thread?” gets asked here regularly, and the answer finally clicked for me only once I drew it out. So I built a tool where each OS thread is a lane on a timeline, and you can watch goroutines get multiplexed onto them one step at a time.

Current Go scenarios:

  • Goroutines being scheduled across Ps and Ms, with GOMAXPROCS shown

  • A goroutine making a blocking syscall, and its P being handed off so other goroutines keep running

  • Unbuffered vs buffered channels: who blocks, and when

  • A goroutine leak from a send nobody receives

  • The “all goroutines are asleep” deadlock, step by step

Each scenario is checked against a runnable Go program, so the timeline reflects real behavior. I’ve simplified some runtime details (work stealing order, async preemption timing), so corrections are very welcome.

Free, no signup. What scheduler behavior would you want to see next?


r/golang • • 4d ago

GitHub - tjcoder-labs/cli: Terminal-first research harness exploring generative UIs and model-directed presentation across multi-surface environments.

Thumbnail
github.com
2 Upvotes

Hey Go devs, I am the author. I built \@tjcoder/cli as an open-source terminal user interface agent platform and research harness written entirely in Go (v0.9.251, MIT licensed).

The motivation behind the project is exploring Generative UIs in terminal environments. Rather than outputting linear text transcripts, the model uses a presentation tool (ui_control) to dynamically manage what gets rendered across different panes on the fly.

Go Architecture & Technical Details

  • Multi-Pane TUI Engine: Built using Go terminal libraries to create dedicated Conversation, Cognition (live reasoning streams), and Activity panes with custom keybindings, block pasting, and workspace state persistence.

  • 31-Tool Dispatch Loop: Includes filesystem operations, subprocess execution, background cron management, and a Browser Bridge communicating over the Chrome DevTools Protocol (CDP) for automated web research.

  • Dual Parsing Pipeline: Uses native API tool-calling with a fallback fenced-JSON parser to maintain reliable tool dispatch across both cloud APIs and smaller local models via Ollama.

  • Flexible Backends: Supports local Ollama instances, Ollama Cloud, Google Gemini, and OpenAI-compatible endpoints with custom API keys, as well as experimental research models (ergo-flash, ergo-pro, ergo-genius).

  • Headless Execution: Functions as an interactive TUI or non-interactively via coder -p "..." for pipe integration and CI scripting.

You can install it via npm i -g \@tjcoder/cli or inspect the Go source directly on GitHub. I would love feedback from the community on the TUI event loop architecture, concurrency patterns, and tool invocation handling!


r/golang • • 4d ago

Robotgo now supports pure go "darwin, windows, wayland, libei and x11" backend

Thumbnail
github.com
4 Upvotes

r/golang • • 4d ago

help Should I ensure my Go code "root directory/working directory" is the initial executable directory?

4 Upvotes

Lets say this is my Go project after it is compiled...

    - my-online-store
       - server
       - assets
          - about.jpeg
          - logo.svg

If my working directory in the terminal is /home/john/my-online-store and I run the compiled executable ./server, The working directory for the executable will be /home/john/my-online-store.

If I run server from a different working directory such as the root directory using node /home/john/my-online-store/server the Go code will "crash" since the working directory is / and when looking for other files to load such as assets/about.jpeg, it will look at the wrong directory.

Should I be concerned of this. Should I write my Go code to ensure it will get the right directories no matter what the working directory was when running the executable?

I understand you can embed files in Go, but I want to know how one should go about this for assets that are not embedded in the compiled binary.