windigo keeps the shape of Win32 while speaking Go
Windows API and GUI in idiomatic Go.
At a glance
- What is it?
- windigo is an MIT licensed Go binding to the Windows API and the Win32 GUI, written entirely in pure Go with native syscalls and no CGo, and its explicit design rule is that a C tutorial should be translatable to Go almost line for line.
- Who is it for?
- windigo fits a Go developer who has to talk to Windows, either to build a native desktop tool or to script an existing machine, and who wants the API to look like the documentation they already know rather than like a Go reinterpretation of it. It does not fit a cross-platform project, because there is no non-Windows target at all, and it does not fit a team that expects a maintained upstream of the Windows API itself, since windigo is hand maintained against a moving system.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Familiarity is the design goal
Windigo is described as Win32 API and GUI in idiomatic Go, and the interesting sentence in the README is about who it is for. It is designed to be familiar to C and C++ Win32 programmers, using the same concepts and an API as close as possible to the original Win32 API, and the stated payoff is that most C and C++ Win32 tutorials and examples can be translated to Go.
That is a real constraint, and it explains the shape of the library. When a Go binding decides to be idiomatic, it renames things, it hides handles behind structs, it returns errors where the C API returns BOOL, and an experienced Win32 programmer has to relearn the vocabulary. Windigo does the opposite on purpose. The win package keeps names like HKEY_CURRENT_USER and RegOpenKeyEx, the co package holds the constants with their original names, and the examples read like the Microsoft documentation.
The one concession to Go is the error handling, and even that is visible in the examples: the code calls RegOpenKeyEx and discards the error with an underscore in the assignment, with a note in the README that error checking is omitted for brevity in the examples.
The project is also explicit about its provenance. It has been handwritten since 2019, and the README states in bold that LLM-generated pull requests are not welcome. For a library that is a large hand-maintained transcription of an API, that policy is a design decision about how the surface is kept consistent rather than an accident.
Pure Go, with no CGo in the build
The README highlights that Windigo is written 100 per cent in pure Go and that CGo is not used, just native syscalls.
That choice has consequences that matter more for a library like this than they would for most. CGo would mean a C toolchain in the build environment, and it would restrict cross compilation, since a CGo build for a target needs a cross C compiler. With native syscalls the package builds the same way any Go package does, so a Windows binary can be produced from any machine that has Go installed, with no additional toolchain.
It also means the package is a first class citizen of the Go ecosystem, with no cgo build tags, no special linker requirements and no performance cliff at the boundary. The cost is that every API call has to be written by hand against the syscall interface, which is precisely why the coverage numbers in the README matter and why the project has been at it since 2019.
The Go version is stated in two places. The README says Windigo is based in Go 1.20, so it can be built in Windows 7 and above, and the go.mod file in the repository declares go 1.20 with no dependencies at all, which is the correct arrangement for a package that talks to the system directly.
The coverage table is the honest measure of the library
The README publishes a table of what has been implemented, and the numbers are large enough to be the reason to trust the library and large enough to show where the gaps are.
| Native FFI item | Count |
| - | -: |
| Handles | 32 |
| Structs | 213 |
| Functions | 706 |
| COM interfaces | 85 |
| COM methods | 561 |
| Const types | 446 |
| Const values | 11,316 |Read the two ends of that table together. Eleven thousand constant values and four hundred and forty six constant types mean the library is not a thin veneer over a few calls; it carries the numeric vocabulary of the Windows API, which is where most of the documentation of a Win32 call actually lives. Against that, seven hundred and six functions is a substantial but clearly finite surface, since the Windows API contains many thousands of functions.
COM is the other axis. Eighty-five interfaces and five hundred and sixty one methods mean the Component Object Model is supported at a level that lets a Go program talk to a COM server, which is how a large part of the Windows ecosystem is addressed.
The project also publishes a lines of code badge reading 59.3k, which is a fair indicator of the maintenance effort behind those numbers.
The GUI example shows the conventions in one page
The README's GUI example creates a window programmatically, handles a button click and uses a minimal.syso resource from the resources folder. Three conventions are worth noticing before you write a line of your own.
The first is the thread lock. The example calls runtime.LockOSThread() with the comment that Windows GUI is single-threaded, which is not optional decoration: a Go program that moves a window between OS threads will produce confusing failures.
The second is the options pattern, where each control is created through a constructor that takes an options struct, and the options are built with a fluent chain:
wnd := ui.NewMain( // create the main window
ui.OptsMain().
Title("Hello you").
Center(true).
Size(ui.Dpi(340, 80)).
ClassIconId(101), // ID of icon resource, see _resources folder
)The third is DPI awareness. Sizes and positions go through ui.Dpi and ui.DpiX rather than raw pixel numbers, so a window stays correct on a scaled display, which is a detail that separates a library written with the modern Windows in mind from one written years ago.
Events are attached the same way, through an On method that takes the message name and a closure, and the handler in the example ends with a MessageBox call through the co constants. The final build step is documented as well, with the -H=windowsgui linker flag that suppresses the console window.
go build -trimpath -ldflags "-s -w -H=windowsgui"Registry, processes and screenshots show the win package
Three shorter examples cover the parts of the API that a Go program on Windows is most likely to need, and they are the clearest illustration of the win package's style.
The registry example opens a key with RegOpenKeyEx, reads one value with RegQueryValueEx and enumerates the rest with RegEnumValue, and it shows the type extraction pattern that the library uses throughout. A registry value is returned as a variant, and the code asks it for the type it actually is with a checked conversion, so a string value and a DWORD value are both handled by the same enumeration loop.
The process example takes a toolhelp snapshot and lists what it finds:
hSnap, _ := win.CreateToolhelp32Snapshot(co.TH32CS_SNAPPROCESS, 0)
defer hSnap.CloseHandle()
processes, _ := hSnap.EnumProcesses()
for _, nfo := range processes {
println("PID:", nfo.Th32ProcessID, "name:", nfo.SzExeFile())
}The screenshot example is the most involved of the set and is worth reading as a map of the GDI path. It gets the screen size with GetSystemMetrics, obtains a device context, creates a compatible bitmap and a compatible memory device context, selects the bitmap into it, blits the screen with BitBlt, fills in a BITMAPINFOHEADER, allocates global memory with GlobalAlloc, locks it with GlobalLockSlice, and reads the pixels with GetDIBits. It then writes the file header, the info header and the pixel data to a BMP by hand with FileOpen and Write.
That last part is the clearest illustration of the library's philosophy: where Windows provides a structure, the library wraps it, and where the API is a sequence of steps, the example shows the steps.
MIT, a monthly-ish release line, and an explicit contribution policy
The licence is MIT, with the LICENSE.md file at the repository root, and the package is published on pkg.go.dev under github.com/rodrigocfd/windigo.
The release history shows a project shipping on a regular cadence. The recent tags are v0.2.7 on 2026-09-01, v0.2.6 on 2026-07-01 and v0.2.5 on 2026-03-01, so minor releases land every couple of months. The version numbers stay in the 0.x range, which by Go convention says the API is not yet considered stable, which is an honest signal for a hand-written transcription of a very large API surface.
The repository is not archived and the last push was on 2026-10-12, so the work is current.
The repository layout mirrors the API layers. The co/ directory holds the constants, win/ holds the API functions and types, ui/ holds the GUI widgets, wstr/ handles wide strings, x/ holds extensions and internal/ holds the shared internals, with the example resources in the _resources/ folder.
The contribution policy deserves a mention in its own right, because it is unusual and because it says something about the shape of the project. The README states that the library is handwritten and that LLM-generated pull requests are not welcome. For a project whose value is a consistent, faithful transcription of an API, that is a defensible position, and a contributor should read it before sending a patch.
The alternative, and when the Win32 shape is the wrong shape
The realistic alternative is to call the Windows API directly with the standard library's own syscall helpers, or to use a cross-platform GUI toolkit and accept that it does not look like Win32.
Calling the API yourself is what Windigo is automating. Doing it by hand means resolving the function address, declaring the argument types, marshalling strings and structures correctly and handling the calling convention, for every call you need. It is entirely doable, it is what the Go standard library helpers are for, and it is a reasonable choice for a program that needs three or four calls. It stops being reasonable when the program needs a window, a device context and a bitmap, because then you are writing a GUI framework.
The cross-platform toolkit is the other direction, and its cost is different. Such a toolkit gives you a consistent API on every platform, but a Windows program built with one will look and behave like a Windows program written with it rather than like a native Win32 application, and the native controls, the message loop semantics and the look of the system are the things you cannot get back.
So the choice is between Go conventions and Windows conventions, and Windigo sits firmly on the Windows side by design. The cost of that choice is that a Go developer who has only written Go code will find the API unfamiliar, and the benefit is that a developer who has written Win32 code will find it immediately familiar, and can translate an example from the Microsoft documentation without relearning anything.
Editorial conclusion
windigo fits a Go developer who has to talk to Windows, either to build a native desktop tool or to script an existing machine, and who wants the API to look like the documentation they already know rather than like a Go reinterpretation of it. It does not fit a cross-platform project, because there is no non-Windows target at all, and it does not fit a team that expects a maintained upstream of the Windows API itself, since windigo is hand maintained against a moving system. Before adopting it, check that the Win32 calls you need are in the coverage table, remember that the GUI thread must be locked with runtime.LockOSThread, and read the maintainer's stated policy on contributions before you send a pull request.
Frequently asked questions
How do I install windigo?
The documented command is go get -u github.com/rodrigocfd/windigo. The module declares Go 1.20 with no dependencies, and the README states it can be built in Windows 7 and above.
Does windigo use CGo?
No. The README states that Windigo is written 100 per cent in pure Go, with CGo not used, just native syscalls, which means no C toolchain is required to build it.
How much of the Windows API is covered?
The README publishes the counts: 32 handles, 213 structs, 706 functions, 85 COM interfaces, 561 COM methods, 446 const types and 11,316 const values.
What do I need to know to build a window with windigo?
The example calls runtime.LockOSThread() because Windows GUI is single-threaded, creates controls with an options pattern through ui.NewMain and the Opts builders, and sizes and positions them with ui.Dpi and ui.DpiX so they scale with the display.
What licence and release cadence does windigo have?
It is MIT licensed, with the LICENSE.md file at the repository root, and the recent tags are v0.2.7 on 2026-09-01, v0.2.6 on 2026-07-01 and v0.2.5 on 2026-03-01, with the last push on 2026-10-12.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/rodrigocfd-windigo)Was this useful?