Powershell is low-key cool
Source: Dev.to
PowerShell often gets overlooked in favor of more popular shells, but it offers powerful features that can streamline local development workflows. Below is a step‑by‑step guide showing how to build a file‑watcher for Go projects using PowerShell, from basic setup to handling long‑running processes with background jobs.
What is PowerShell?
PowerShell is both a command‑line shell and a scripting language built on the .NET runtime. Unlike traditional Unix shells (e.g., Bash) that pipe plain text, PowerShell pipelines objects, allowing richer data manipulation directly in the shell.
Setting Up the Watcher Directory
# Create a directory for the watcher
mkdir watcher
PowerShell provides the New-Item cmdlet for creating items, but common aliases like mkdir are available for convenience.
# Navigate into the directory
cd watcher
# Create a placeholder Go source file
ni main.go
# Create the PowerShell script that will perform the watching
ni watcher.ps1
Adjusting the Execution Policy
PowerShell’s execution policy determines whether scripts can run. Ensure it’s set to RemoteSigned (or a less restrictive level) before proceeding.
# View the current policy
Get-ExecutionPolicy
# If needed, set it to RemoteSigned
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser -Force
Sample Go Program
Create a simple Go program that prints “Hello World”. Save this as main.go inside the watcher folder.
package main
import "fmt"
func main() {
fmt.Println("Hello World")
}
Basic Watcher Script (Synchronous)
The following PowerShell script watches all .go files in the current directory (and sub‑directories). When a change is detected, it re‑runs the Go program.
# watcher.ps1
# Path to the Go file (can be overridden later)
$path = "main.go"
Write-Host 'GoWatcher *Press CTRL+C to quit*'
$dirname = "."
$files = Get-ChildItem $dirname -Filter "*.go" -Recurse
# Initial run
go run $path
# Compute an initial signature (hash) of all Go files
$signature = $files | Get-FileHash -ErrorAction SilentlyContinue |
Sort-Object Path | Out-String
while ($true) {
$current_signature = $files | Get-FileHash -ErrorAction SilentlyContinue |
Sort-Object Path | Out-String
if ($signature -ne $current_signature) {
Write-Host 'File change detected: Restarting...'
go run $path
$signature = $current_signature
}
Start-Sleep -Milliseconds 300
}
Run the script:
.\watcher.ps1
Adding a Parameter for the File Path
Make the script more flexible by accepting the Go file path as a command‑line argument.
# watcher.ps1 (updated)
[CmdletBinding()]
Param(
[Parameter(Mandatory)]
$path
)
Write-Host 'GoWatcher *Press CTRL+C to quit*'
$dirname = "."
$files = Get-ChildItem $dirname -Filter "*.go" -Recurse
go run $path
$signature = $files | Get-FileHash -ErrorAction SilentlyContinue |
Sort-Object Path | Out-String
while ($true) {
$current_signature = $files | Get-FileHash -ErrorAction SilentlyContinue |
Sort-Object Path | Out-String
if ($signature -ne $current_signature) {
Write-Host 'File change detected: Restarting...'
go run $path
$signature = $current_signature
}
Start-Sleep -Milliseconds 300
}
Execute with the path argument:
.\watcher.ps1 -path 'main.go'
Handling Long‑Running Processes with Background Jobs
When the Go application runs a web server or another blocking operation, the watcher script would freeze. PowerShell jobs allow you to run such processes asynchronously.
Useful Job Cmdlets
# Start a background job
Start-Job -Name GoServer -ScriptBlock { ... }
# Stop a job
Stop-Job -Name GoServer
# Remove a job
Remove-Job -Name GoServer
# Retrieve job output
Receive-Job -Name GoServer
# List jobs
Get-Job -Name GoServer
Advanced Watcher with Job Management
The script below launches the Go server as a background job, restarts it on file changes, and ensures clean‑up when the watcher exits.
# watcher.ps1 (advanced version)
[CmdletBinding()]
Param(
[Parameter(Mandatory)]
$path
)
Write-Host 'GoWatcher *Press CTRL+C to quit*'
$dirname = "."
$jobname = "GoServer"
$binary = "GoApp"
function Start-ServerJob {
# Remove any existing job with the same name
Get-Job -Name $jobname -ErrorAction SilentlyContinue | Remove-Job -Force
# Start a new job that builds and runs the Go binary
$job = Start-Job -Name $jobname -ScriptBlock {
param($path, $dirname, $binary)
Set-Location $dirname
# Build the binary (adjust as needed for your project)
go build -o "bin/$binary.exe" $path
# Execute the binary
& "./bin/$binary.exe"
} -ArgumentList $path, $dirname, $binary
return $job
}
# Gather all Go source files
$files = Get-ChildItem $dirname -Filter "*.go" -Recurse
# Initial launch
$job = Start-ServerJob
# Initial signature
$signature = $files | Get-FileHash -ErrorAction SilentlyContinue |
Sort-Object Path | Out-String
try {
while ($true) {
$current_signature = $files | Get-FileHash -ErrorAction SilentlyContinue |
Sort-Object Path | Out-String
if ($signature -ne $current_signature) {
Write-Host 'File change detected: Restarting...'
# Restart the server job
$job = Start-ServerJob
$signature = $current_signature
}
Start-Sleep -Milliseconds 300
}
}
finally {
# Clean up the background job
Get-Job -Name $jobname -ErrorAction SilentlyContinue | Remove-Job -Force
# Ensure the binary process is terminated
if (Get-Process -Name $binary -ErrorAction SilentlyContinue) {
Stop-Process -Name $binary -Force
}
}
Run the advanced watcher the same way:
.\watcher.ps1 -path 'main.go'
The script now:
- Builds the Go program into an executable.
- Runs the executable as a background job.
- Detects changes to any
.gofile. - Restarts the background job when changes occur.
- Cleans up resources on termination.
Conclusion
PowerShell’s object‑oriented pipeline, built‑in aliases, and robust job system make it an excellent choice for automating development tasks such as file watching and process management. By leveraging these features, you can create lightweight, cross‑platform tooling without relying on external utilities.