Api Server
mkdir go-api
cd go-api
# Initialize golang module
go mod init go-api
# Install gin-gonic package
go get -u github.com/gin-gonic/gin
touch main.go
// main.go
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
// listen and serve on 0.0.0.0:8080
r.Run()
}
# Start api server
go run .
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
[GIN-debug] GET /ping --> main.main.func1 (3 handlers)
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
[GIN-debug] Listening and serving HTTP on :8080
# Test
curl localhost:8080/ping
{"message":"pong"}⏎
Testing
Unit Testing
package main
import (
"net/http"
"net/http/httptest"
"testing"
)
func TestPingRoute(t *testing.T) {
r := setupRouter()
w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "/ping", nil)
r.ServeHTTP(w, req)
if w.Code != 200 {
t.Errorf("Expected status code 200, but got %d", w.Code)
}
expected := `{"message":"pong"}`
if w.Body.String() != expected {
t.Errorf("Expected body to be %s, but got %s", expected, w.Body.String())
}
}
# Execute tests
❯ go test .
ok go-api 0.317s
Benchmark Testing
# Execute tests in benchmark mode
❯ go test -bench=. -count 2
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
[GIN-debug] GET /ping --> go-api.setupRouter.func1 (3 handlers)
[GIN] 2024/03/19 - 21:21:17 | 200 | 46.125µs | | GET "/ping"
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
[GIN-debug] GET /ping --> go-api.setupRouter.func1 (3 handlers)
[GIN] 2024/03/19 - 21:21:17 | 200 | 2.375µs | | GET "/ping"
PASS
ok go-api 0.132s
Performance Testing
Pre-requiresite
- Install Grafana K6 toolchain
Test script
mkdir tests/performance
touch tests/performance/main.js
// main.js
import http from 'k6/http';
import { check } from 'k6';
export default function () {
const res = http.get('http://localhost:8080/ping');
check(res, {
'is status 200': (r) => r.status === 200,
});
}
Start api server in window 1 -
go run .
Run performance tests
❯ k6 run tests/performance/main.js
/\ |‾‾| /‾‾/ /‾‾/
/\ / \ | |/ / / /
/ \/ \ | ( / ‾‾\
/ \ | |\ \ | (‾) |
/ __________ \ |__| \__\ \_____/ .io
execution: local
script: tests/performance/main.js
output: -
scenarios: (100.00%) 1 scenario, 1 max VUs, 10m30s max duration (incl. graceful stop):
* default: 1 iterations for each of 1 VUs (maxDuration: 10m0s, gracefulStop: 30s)
✓ is status 200
checks.........................: 100.00% ✓ 1 ✗ 0
data_received..................: 141 B 82 kB/s
data_sent......................: 84 B 49 kB/s
http_req_blocked...............: avg=839µs min=839µs med=839µs max=839µs p(90)=839µs p(95)=839µs
http_req_connecting............: avg=256µs min=256µs med=256µs max=256µs p(90)=256µs p(95)=256µs
http_req_duration..............: avg=708µs min=708µs med=708µs max=708µs p(90)=708µs p(95)=708µs
{ expected_response:true }...: avg=708µs min=708µs med=708µs max=708µs p(90)=708µs p(95)=708µs
http_req_failed................: 0.00% ✓ 0 ✗ 1
http_req_receiving.............: avg=37µs min=37µs med=37µs max=37µs p(90)=37µs p(95)=37µs
http_req_sending...............: avg=53µs min=53µs med=53µs max=53µs p(90)=53µs p(95)=53µs
http_req_tls_handshaking.......: avg=0s min=0s med=0s max=0s p(90)=0s p(95)=0s
http_req_waiting...............: avg=618µs min=618µs med=618µs max=618µs p(90)=618µs p(95)=618µs
http_reqs......................: 1 581.733566/s
iteration_duration.............: avg=1.66ms min=1.66ms med=1.66ms max=1.66ms p(90)=1.66ms p(95)=1.66ms
iterations.....................: 1 581.733566/s
running (00m00.0s), 0/1 VUs, 1 complete and 0 interrupted iterations
default ✓ [======================================] 1 VUs 00m00.0s/10m0s 1/1 iters, 1 per VU