Building Windows Services with Go: A Starting Point
A Generic Go Windows Service Template
I’m pleased to share go-windows-service.
What is go-windows-service?
The go-windows-service project is a template implementation that demonstrates how to create a proper Windows service using Go’s golang.org/x/sys/windows/svc package. Rather than being a feature-complete application, it’s designed as a reference implementation that you can clone, customize, and extend for your specific needs.
Why Use This Template?
Creating Windows services in Go can be tricky if you’re not familiar with the Windows service architecture. And let’s be honest, the Windows service API documentation sometimes feels like it was written during the Windows NT era and nobody bothered to update it since. This template handles all the boilerplate code for you - service control handlers, proper signal handling, event log integration, and all that fun stuff.
Instead of spending three days figuring out why your service won’t start (spoiler: it’s always the event log permissions), you can focus on implementing your actual business logic.
Getting Started
The project is straightforward to use:
-
Clone the repository
git clone https://gitlab.com/hocmodo/go-windows-service.git cd go-windows-service -
Build the service
go build -
Install as a Windows service
go-windows-service.exe -install -
Start the service
sc start YourServiceName
Use Cases
This template is perfect for:
- Background processing tasks - Long-running jobs that need to survive user logouts
- System monitoring agents - Services that monitor system resources or application health
- API servers - HTTP/gRPC servers that need to run as Windows services
- Data collection agents - Services that gather and forward metrics or logs
- Scheduled tasks - Jobs that need more control than Windows Task Scheduler provides
Customization
The template is designed to be easily customized. The main service logic is cleanly separated from the Windows service wrapper code, making it simple to:
- Add your own business logic in the service execution loop
- Implement configuration file reading
- Integrate with databases or message queues
- Add health check endpoints
- Implement graceful shutdown procedures
A Practical Example
Here’s a simple example of how you might extend the template to create a file monitoring service:
func (m *myService) Execute(args []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (ssec bool, errno uint32) {
// Your custom initialization
watcher := setupFileWatcher()
defer watcher.Close()
changes <- svc.Status{State: svc.Running, Accepts: cmdsAccepted}
for {
select {
case c := <-r:
switch c.Cmd {
case svc.Stop, svc.Shutdown:
// Cleanup and exit
return
}
case event := <-watcher.Events:
// Handle file system events
handleFileEvent(event)
}
}
}
Project Status
This is a template project, meaning it’s intentionally kept minimal and generic. The goal is to provide a clean starting point rather than a feature-rich framework. This approach ensures the codebase remains easy to understand and modify for your specific requirements.
Contributing and Feedback
While this is primarily a template project, contributions that improve the base structure, fix bugs, or enhance documentation are always welcome. The project is hosted on GitLab where you can report issues or submit merge requests.
Now go build something useful! Or at least something that runs in the background without crashing. We’re not picky.