Go 1.23.12 (CentOS Stream 9) AMI Administrator Guide
1. Quick Start Information
Connection Methods:
- Access the instance via SSH using the
ec2-useruser. Usesudoto run commands requiring root privileges. To switch to the root user, usesudo su - root.
Install Information:
- OS: CentOS Stream 9
- Go version: 1.23.12
- Go Install Directory (GOROOT):
/usr/local/go - Go Workspace (GOPATH):
$HOME/go - Environment Configuration:
/etc/profile.d/go.sh
Quick Verification Commands:
- Check Go version:
go version - Check Go location:
which go - View all environment variables:
go env - Check installed tools:
dlv version,gopls version,air -v
Development Tools Included:
- Go Compiler:
go - Go Formatter:
gofmt - Delve Debugger:
dlv(v1.26.0) - Language Server:
gopls(v0.21.0) - Hot Reload Tool:
air(v1.64.5)
Firewall Configuration:
- Please allow SSH port 22.
- For security, it is recommended to limit SSH access to trusted IPs only.
2. Overview
Welcome to this Go 1.23.12 AMI. This image is based on CentOS Stream 9 and provides a complete, production-ready development environment for building high-performance applications in Go.
This guide explains how to use this AMI and details its internal configuration.
What is Go?
Go (also known as Golang) is a statically typed, compiled programming language designed at Google. It is known for its simplicity, efficiency, and excellent support for concurrent programming. Go is widely used for building web servers, cloud services, DevOps tools, and distributed systems.
Core Features of This AMI:
- Go 1.23.12: Latest stable release with official binary distribution
- Delve Debugger: v1.26.0 for interactive debugging and troubleshooting
- gopls Language Server: v0.21.0 for IDE integration (VS Code, Vim, etc.)
- Air Hot Reload: v1.64.5 for automatic rebuild on file changes
- Global PATH Configuration: All tools accessible system-wide via
/etc/profile.d/go.sh - Sudo-Compatible: Symbolic links in
/usr/bin/for root access
Target Use Cases:
- Building RESTful APIs and microservices
- Developing CLI tools and system utilities
- Creating cloud-native applications (Kubernetes, Docker)
- Building concurrent and parallel systems
- Prototyping network services and distributed systems
3. First Launch & Verification
Step 1: Connect to Your Instance
- Launch your instance in your cloud provider's console (e.g., AWS EC2)
- Ensure SSH port 22 is allowed in your security group
- Connect via SSH:
ssh -i your-key.pem ec2-user@YOUR_PUBLIC_IP
Step 2: Verify Go Installation
Check the Go version:
go version
Expected Output:
go version go1.23.12 linux/amd64
Verify the installation path:
which go
Expected Output:
/usr/local/go/bin/go
View all Go environment variables:
go env
Key Variables:
GOROOT="/usr/local/go"
GOPATH="/home/ec2-user/go"
GOCACHE="/home/ec2-user/.cache/go-build"
Step 3: Verify Development Tools
Check Delve debugger:
dlv version
Expected Output:
Delve Debugger
Version: 1.26.0
Build: $Id: 7fd7302eab8b16d715a94af1b5dfbffc2e1359bc $
Check gopls language server:
gopls version
Expected Output:
golang.org/x/tools/gopls v0.21.0
Check Air hot reload tool:
air -v
Expected Output:
__ _ ___
/ /\ | | | |_)
/_/--\ |_| |_| \_ v1.64.5, built with Go go1.25.7
Step 4: Create and Run a Test Program
Create a simple "Hello World" program:
mkdir -p ~/hello-go
cd ~/hello-go
Create main.go:
cat > main.go << 'EOF'
package main
import "fmt"
func main() {
fmt.Println("Hello from Go 1.23.12!")
}
EOF
Run the program directly:
go run main.go
Expected Output:
Hello from Go 1.23.12!
Build an executable:
go build -o hello
./hello
Expected Output:
Hello from Go 1.23.12!
Clean up:
cd ~
rm -rf ~/hello-go
4. Architecture & Detailed Configuration
4.1. Component Locations
| Component | Installation Path | Purpose |
|---|---|---|
| Go Root (GOROOT) | /usr/local/go/ | Go compiler and standard library |
| Go Binaries | /usr/local/go/bin/ | go, gofmt, godoc |
| Go Workspace (GOPATH) | $HOME/go/ | User projects and dependencies |
| Development Tools | /usr/local/bin/ | dlv, gopls, air |
| System Symlinks | /usr/bin/ | go, gofmt (for sudo access) |
| Environment Config | /etc/profile.d/go.sh | PATH and GOPATH configuration |
4.2. Environment Configuration File
File: /etc/profile.d/go.sh
Complete Contents:
export PATH=$PATH:/usr/local/go/bin
export GOPATH=$HOME/go
export PATH=$PATH:$GOPATH/bin
How This Works:
- Line 1: Adds
/usr/local/go/binto PATH (forgo,gofmtcommands) - Line 3: Sets
GOPATHto$HOME/go(user workspace for projects) - Line 4: Adds
$GOPATH/binto PATH (for user-installed Go tools)
This file is automatically sourced when users log in via SSH. Changes take effect immediately for new sessions.
Why /etc/profile.d/:
- System-wide configuration (applies to all users)
- Survives system updates
- Standard location for custom environment scripts
4.3. Symbolic Links Configuration
All core executables are linked to /usr/bin/ for global access and sudo compatibility:
/usr/bin/go -> /usr/local/go/bin/go
/usr/bin/gofmt -> /usr/local/go/bin/gofmt
Why Symbolic Links:
- Allows
sudo goto work (sudo resets PATH) - Provides consistent command location across the system
- Standard Unix pattern for third-party binaries
4.4. GOPATH Directory Structure
After creating your first project, the GOPATH directory will have this structure:
$HOME/go/
├── bin/ # Compiled executables from 'go install'
├── pkg/ # Compiled package objects (cache)
└── src/ # Source code (deprecated in Go 1.11+, use modules instead)
Modern Go Development (Go Modules):
Since Go 1.11, projects no longer need to be inside GOPATH/src. You can create projects anywhere:
mkdir -p ~/projects/myapp
cd ~/projects/myapp
go mod init github.com/yourusername/myapp
4.5. Installation Method
This AMI uses the official Go binary distribution from https://go.dev/dl/:
- Source:
go1.23.12.linux-amd64.tar.gz - Why Official Binary: Google-compiled, thoroughly tested, zero compilation time
- Architecture: amd64 (x86_64) for maximum compatibility
No Compilation Required:
Unlike Erlang or other languages, Go is distributed as a pre-compiled binary. This means:
- Instant installation (no 15-minute build process)
- Guaranteed compatibility with official tooling
- Consistent behavior across all systems
5. How-To-Create: Building This AMI from Scratch
This section explains exactly how this AMI was created, allowing you to:
- Understand the configuration
- Reproduce the setup on other systems
- Customize the installation
Step 1: System Preparation
Update the system and install prerequisites:
# Update all packages
sudo dnf update -y
# Install wget and tar (minimal images may lack these)
sudo dnf install -y wget tar
Why These Packages:
wget: Required to download the Go binary archivetar: Required to extract the .tar.gz file
Step 2: Remove Conflicting Installations
Remove any existing Go installation from package manager:
sudo dnf remove -y golang
Why This Step:
CentOS repositories may contain outdated Go versions (e.g., Go 1.20). Removing them prevents:
- Binary conflicts (
/usr/bin/gopointing to old version) - Environment variable conflicts
- Version confusion
Step 3: Download and Install Go 1.23.12
Navigate to temporary directory:
cd /tmp
Download the official Go 1.23.12 binary:
wget https://go.dev/dl/go1.23.12.linux-amd64.tar.gz
Download Details:
- URL: https://go.dev/dl/go1.23.12.linux-amd64.tar.gz
- Size: ~68 MB
- SHA256: (Verify on https://go.dev/dl/ for security)
Extract to /usr/local:
sudo tar -C /usr/local -xzf go1.23.12.linux-amd64.tar.gz
Extraction Details:
-C /usr/local: Change to /usr/local before extracting-x: Extract files-z: Decompress gzip-f: Use file (not stdin)
Result: Creates /usr/local/go/ with the complete Go installation.
Installation Directory Structure:
/usr/local/go/
├── bin/ # Executables (go, gofmt, etc.)
├── src/ # Standard library source code
├── pkg/ # Compiled standard library
├── misc/ # Support files
└── VERSION # Version identifier
Step 4: Configure Environment Variables
Create the system-wide environment configuration file:
sudo tee /etc/profile.d/go.sh > /dev/null << 'EOF'
export PATH=$PATH:/usr/local/go/bin
export GOPATH=$HOME/go
export PATH=$PATH:$GOPATH/bin
EOF
File Breakdown:
export PATH=$PATH:/usr/local/go/bin
Adds Go binaries to PATH (go, gofmt, godoc)
export GOPATH=$HOME/go
Sets user workspace (where go install puts binaries)
export PATH=$PATH:$GOPATH/bin
Adds user-installed tools to PATH (dlv, gopls, etc.)
Activation:
For the current session:
source /etc/profile.d/go.sh
For all future sessions: Automatic (sourced at login)
Step 5: Create Global Symbolic Links
Link Go commands to /usr/bin/ for sudo access:
sudo ln -sf /usr/local/go/bin/go /usr/bin/go
sudo ln -sf /usr/local/go/bin/gofmt /usr/bin/gofmt
Why This Is Important:
When you run sudo go, the system looks in /usr/bin/ (sudo resets PATH for security). Without symlinks:
go version # Works (user PATH includes /usr/local/go/bin)
sudo go version # Fails (sudo PATH doesn't include /usr/local/go/bin)
With symlinks:
go version # Works
sudo go version # Works
Step 6: Verify Base Installation
Check version:
go version
Expected Output:
go version go1.23.12 linux/amd64
Check location:
which go
Expected Output:
/usr/local/go/bin/go
Step 7: Install Delve Debugger
Install Delve to /usr/local/bin/:
sudo GOBIN=/usr/local/bin /usr/local/go/bin/go install github.com/go-delve/delve/cmd/dlv@latest
Command Breakdown:
sudo: Run as root to write to/usr/local/bin/GOBIN=/usr/local/bin: Install binary to this directory (not$GOPATH/bin)/usr/local/go/bin/go: Use absolute path (sudo doesn't have Go in PATH yet)install: Compile and install the packagegithub.com/go-delve/delve/cmd/dlv: Package import path@latest: Use the latest version
What is Delve:
Delve is a debugger specifically designed for Go. Features:
- Set breakpoints and inspect variables
- Step through code line-by-line
- Examine goroutines and stack traces
- Attach to running processes
Why /usr/local/bin/:
- Global availability (in default PATH)
- Survives GOPATH changes
- Accessible via sudo
Verify installation:
dlv version
Expected Output:
Delve Debugger
Version: 1.26.0
Build: $Id: 7fd7302eab8b16d715a94af1b5dfbffc2e1359bc $
Step 8: Install gopls Language Server
Install gopls to /usr/local/bin/:
sudo GOBIN=/usr/local/bin /usr/local/go/bin/go install golang.org/x/tools/gopls@latest
What is gopls:
gopls (pronounced "go please") is the official Go language server implementing the Language Server Protocol (LSP). It provides:
- Code completion and IntelliSense
- Go to definition / Find references
- Real-time error checking
- Code formatting and imports organization
IDE Integration:
- VS Code: Install "Go" extension (gopls auto-detected)
- Vim/Neovim: Use vim-go or coc-go
- Emacs: Use lsp-mode with gopls
- Sublime Text: Use LSP-gopls
Verify installation:
gopls version
Expected Output:
golang.org/x/tools/gopls v0.21.0
Step 9: Install Air Hot Reload Tool
Install Air to /usr/local/bin/:
sudo GOBIN=/usr/local/bin /usr/local/go/bin/go install github.com/air-verse/air@latest
What is Air:
Air is a live reload utility for Go development. It watches your files and automatically rebuilds and restarts your application when changes are detected.
Features:
- Configurable file watch patterns
- Build error notifications
- Customizable build and run commands
- Color-coded logging
Typical Usage:
cd ~/myproject
air
Air will watch for changes and rebuild automatically.
Verify installation:
air -v
Expected Output:
__ _ ___
/ /\ | | | |_)
/_/--\ |_| |_| \_ v1.64.5, built with Go go1.25.7
Step 10: Cleanup (Optional but Recommended)
Remove the downloaded archive:
cd ~
rm -f /tmp/go1.23.12.linux-amd64.tar.gz
Space Saved: ~68 MB
This cleanup is optional for this AMI because the download is small. However, it's good practice before creating AMI snapshots.
6. Using the Development Environment
6.1. Creating a New Go Project with Modules
Create a project directory:
mkdir -p ~/projects/myapp
cd ~/projects/myapp
Initialize a Go module:
go mod init github.com/yourusername/myapp
This creates go.mod:
module github.com/yourusername/myapp
go 1.23
Create main.go:
package main
import "fmt"
func main() {
fmt.Println("Welcome to my app!")
}
Run the program:
go run .
6.2. Adding Dependencies
Add a dependency (example: Gin web framework):
go get github.com/gin-gonic/gin
This:
- Downloads the package
- Updates
go.modwith the dependency - Creates/updates
go.sumwith checksums
Use it in your code:
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
r.GET("/", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "Hello World"})
})
r.Run(":8080")
}
Install all dependencies:
go mod download
Tidy up dependencies (remove unused):
go mod tidy
6.3. Building Executables
Build for current platform:
go build -o myapp
Build with optimizations (smaller binary):
go build -ldflags="-s -w" -o myapp
Flags Explained:
-s: Omit symbol table and debug info-w: Omit DWARF symbol table
Cross-compile for different platforms:
# Linux ARM64
GOOS=linux GOARCH=arm64 go build -o myapp-arm64
# macOS Intel
GOOS=darwin GOARCH=amd64 go build -o myapp-macos
# Windows
GOOS=windows GOARCH=amd64 go build -o myapp.exe
6.4. Running Tests
Create a test file main_test.go:
package main
import "testing"
func TestExample(t *testing.T) {
if 1+1 != 2 {
t.Error("Math is broken!")
}
}
Run tests:
go test
Run with coverage:
go test -cover
Run with verbose output:
go test -v
Run specific test:
go test -run TestExample
Generate coverage report:
go test -coverprofile=coverage.out
go tool cover -html=coverage.out
6.5. Using Delve Debugger
Start debugger:
dlv debug
Common Delve commands:
(dlv) break main.main # Set breakpoint
(dlv) continue # Start/continue execution
(dlv) next # Step to next line
(dlv) step # Step into function
(dlv) print myvar # Print variable value
(dlv) goroutines # List goroutines
(dlv) exit # Quit debugger
Debug a running process:
# Get process ID
ps aux | grep myapp
# Attach debugger
sudo dlv attach <PID>
6.6. Using Air for Hot Reload
Initialize Air in your project:
cd ~/projects/myapp
air init
This creates .air.toml configuration file.
Start development with hot reload:
air
What Air Does:
- Watches for file changes (*.go, *.html, etc.)
- Rebuilds the project automatically
- Restarts the application
- Shows build errors in real-time
Customize .air.toml:
[build]
cmd = "go build -o ./tmp/main ."
bin = "tmp/main"
include_ext = ["go", "tmpl", "html"]
exclude_dir = ["tmp", "vendor"]
6.7. Formatting and Linting
Format code:
gofmt -w .
Or use goimports (install first):
go install golang.org/x/tools/cmd/goimports@latest
goimports -w .
Difference:
gofmt: Formats code onlygoimports: Formats code + manages imports (adds missing, removes unused)
Install golangci-lint (comprehensive linter):
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin
Run linter:
golangci-lint run
7. Important File Locations
| Path | Purpose | Notes |
|---|---|---|
/usr/local/go/ | Go installation | Contains bin/, src/, pkg/ |
/usr/local/go/bin/go | Go compiler | Main executable |
/usr/local/go/bin/gofmt | Code formatter | Standard formatting tool |
/usr/bin/go | Go symlink | For sudo access |
/usr/bin/gofmt | gofmt symlink | For sudo access |
/usr/local/bin/dlv | Delve debugger | Interactive debugger |
/usr/local/bin/gopls | Language server | IDE integration |
/usr/local/bin/air | Hot reload tool | Development utility |
/etc/profile.d/go.sh | Environment config | System-wide PATH setup |
$HOME/go/ | GOPATH workspace | User projects and cache |
$HOME/go/bin/ | User-installed tools | From go install |
8. Troubleshooting
Problem: go: command not found
Cause: Environment not loaded or PATH not set.
Solution:
# Source the environment file
source /etc/profile.d/go.sh
# Or log out and back in
exit
ssh -i your-key.pem ec2-user@YOUR_IP
# Verify
go version
Problem: sudo go doesn't work
Cause: Symbolic links missing or sudo PATH doesn't include Go.
Solution:
# Verify symlinks exist
ls -la /usr/bin/go
ls -la /usr/bin/gofmt
# If missing, recreate them
sudo ln -sf /usr/local/go/bin/go /usr/bin/go
sudo ln -sf /usr/local/go/bin/gofmt /usr/bin/gofmt
# Test
sudo go version
Problem: go get fails with SSL errors
Cause: CA certificates outdated or missing.
Solution:
# Update CA certificates
sudo dnf update -y ca-certificates
# Retry
go get github.com/gin-gonic/gin
Problem: Module download fails with "connection refused"
Cause: Firewall blocking Go module proxy or network issue.
Solution:
# Check proxy setting
go env GOPROXY
# Try direct mode (bypass proxy)
GOPROXY=direct go get github.com/gin-gonic/gin
# Or use alternative proxy
GOPROXY=https://goproxy.io,direct go get github.com/gin-gonic/gin
Problem: dlv or gopls not found
Cause: Tools not installed or not in PATH.
Solution:
# Verify installation
which dlv
which gopls
# If missing, reinstall
sudo GOBIN=/usr/local/bin go install github.com/go-delve/delve/cmd/dlv@latest
sudo GOBIN=/usr/local/bin go install golang.org/x/tools/gopls@latest
# Verify
dlv version
gopls version
Problem: Build fails with "cannot find package"
Cause: Dependencies not downloaded or wrong import path.
Solution:
# Download all dependencies
go mod download
# Verify go.mod exists
ls -la go.mod
# If missing, initialize module
go mod init github.com/yourusername/myapp
# Clean module cache and retry
go clean -modcache
go mod download
Problem: Air doesn't rebuild on file changes
Cause: File watch limit exceeded or wrong configuration.
Solution:
# Increase inotify watch limit
echo "fs.inotify.max_user_watches=524288" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
# Check .air.toml configuration
cat .air.toml
# Verify include_ext includes your file types
# Default: ["go", "tmpl", "tpl", "html"]
9. Advanced Topics
9.1. Goroutines and Concurrency
Go's killer feature is easy concurrency:
package main
import (
"fmt"
"time"
)
func worker(id int, jobs <-chan int, results chan<- int) {
for j := range jobs {
fmt.Printf("Worker %d processing job %d\n", id, j)
time.Sleep(time.Second)
results <- j * 2
}
}
func main() {
jobs := make(chan int, 100)
results := make(chan int, 100)
// Start 3 workers
for w := 1; w <= 3; w++ {
go worker(w, jobs, results)
}
// Send 9 jobs
for j := 1; j <= 9; j++ {
jobs <- j
}
close(jobs)
// Collect results
for a := 1; a <= 9; a++ {
<-results
}
}
9.2. Building Web APIs with Gin
Install Gin framework:
go get github.com/gin-gonic/gin
Create a REST API:
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
type User struct {
ID string `json:"id"`
Name string `json:"name"`
}
var users = []User{
{ID: "1", Name: "Alice"},
{ID: "2", Name: "Bob"},
}
func main() {
r := gin.Default()
r.GET("/users", func(c *gin.Context) {
c.JSON(http.StatusOK, users)
})
r.GET("/users/:id", func(c *gin.Context) {
id := c.Param("id")
for _, user := range users {
if user.ID == id {
c.JSON(http.StatusOK, user)
return
}
}
c.JSON(http.StatusNotFound, gin.H{"error": "User not found"})
})
r.Run(":8080")
}
9.3. Performance Profiling
Add profiling to your app:
import _ "net/http/pprof"
Run your app and collect CPU profile:
go tool pprof http://localhost:8080/debug/pprof/profile?seconds=30
Analyze memory usage:
go tool pprof http://localhost:8080/debug/pprof/heap
Generate flame graph:
go tool pprof -http=:9090 cpu.prof
9.4. Benchmarking
Create benchmark in _test.go:
func BenchmarkFibonacci(b *testing.B) {
for i := 0; i < b.N; i++ {
fibonacci(20)
}
}
Run benchmark:
go test -bench=.
With memory profiling:
go test -bench=. -benchmem
Compare benchmarks:
go test -bench=. > old.txt
# Make changes
go test -bench=. > new.txt
benchstat old.txt new.txt
9.5. Static Linking
Build fully static binary (no external dependencies):
CGO_ENABLED=0 go build -a -ldflags '-extldflags "-static"' -o myapp
Verify it's static:
ldd myapp
# Output: "not a dynamic executable"
9.6. Using Docker with Go
Create Dockerfile:
FROM golang:1.23-alpine AS builder
WORKDIR /app
COPY . .
RUN go mod download
RUN CGO_ENABLED=0 go build -o myapp
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/myapp .
CMD ["./myapp"]
Build and run:
docker build -t myapp .
docker run -p 8080:8080 myapp
10. Security Considerations
10.1. Production Security Checklist
When deploying Go applications:
- Update Dependencies: Run
go get -u ./...to update packages - Scan for Vulnerabilities: Use
govulncheckgo install golang.org/x/vuln/cmd/govulncheck@latest
govulncheck ./... - Enable HTTPS: Never run production apps over HTTP
- Validate Input: Sanitize all user inputs
- Use Environment Variables: Never hardcode secrets
- Limit SSH Access: Use key-based authentication only
- Run as Non-Root: Create dedicated service user
10.2. Firewall Best Practices
Only expose necessary ports:
# SSH (restrict to your IP)
Source: YOUR_IP/32, Port: 22
# Web application (if public)
Source: 0.0.0.0/0, Port: 443 (HTTPS)
# Do NOT expose:
# - 8080 (Development server)
# - 6060 (pprof debug port)
10.3. Running as a System Service
Create a systemd service file /etc/systemd/system/myapp.service:
[Unit]
Description=My Go Application
After=network.target
[Service]
Type=simple
User=myapp
WorkingDirectory=/home/myapp
ExecStart=/home/myapp/myapp
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
Enable and start:
sudo systemctl daemon-reload
sudo systemctl enable myapp
sudo systemctl start myapp
11. Final Notes
What You've Got
This AMI provides a complete, production-ready Go development environment:
- ✅ Go 1.23.12 official binary distribution
- ✅ Delve v1.26.0 debugger for troubleshooting
- ✅ gopls v0.21.0 language server for IDE integration
- ✅ Air v1.64.5 hot reload for rapid development
- ✅ Global PATH configuration for all users
- ✅ Sudo-compatible installation
Recommended Next Steps
-
Learn Go Basics:
- Official Tour: https://go.dev/tour/
- Go by Example: https://gobyexample.com/
-
Build a Web Service:
- Gin Framework: https://gin-gonic.com/
- Echo Framework: https://echo.labstack.com/
-
Explore Concurrency:
- Goroutines and Channels tutorial
- Concurrency patterns in Go
-
Join the Community:
- Go Forum: https://forum.golangbridge.org/
- Reddit: https://reddit.com/r/golang
- Gophers Slack: https://gophers.slack.com/
Performance Expectations
Go excels at:
- Fast compilation (~100ms for small projects)
- Low memory footprint (5-10MB for simple services)
- High throughput (handling 10,000+ req/s on modest hardware)
- Quick startup (milliseconds, not seconds)
- Easy deployment (single static binary, no runtime dependencies)
Cost Optimization
For development:
- t3.micro (1 vCPU, 1GB RAM): Sufficient for learning and small projects
- t3.small (2 vCPU, 2GB RAM): Better for web services
For production:
- t3.medium+ (2+ vCPU, 4GB+ RAM): Recommended starting point
- c5.large+: For CPU-intensive workloads
- t3.nano: Can run simple Go services (very cost-effective)
Go's efficient resource usage makes it one of the most cost-effective languages for cloud deployment.
Happy coding with Go! 🚀