Skip to main content

Go SDK

The InstaVM Go SDK provides a robust, type-safe interface for interacting with the InstaVM API. It features automatic session management, comprehensive error handling, and context support for cancellation and timeouts.

Installation

go get github.com/instavm/instavm-go

Quick Start

package main

import (
"context"
"fmt"
"log"

"github.com/instavm/instavm-go"
)

func main() {
// Initialize with your API key
client := instavm.New("your_api_key_here")
defer client.Close()

// Execute code
ctx := context.Background()
result, err := client.Execute(ctx, "fmt.Println(\"Hello from InstaVM!\")")
if err != nil {
log.Fatal(err)
}

fmt.Println(result.Output)
}

Client Configuration

Basic Configuration

package main

import (
"time"

"github.com/instavm/instavm-go"
)

func main() {
// Default configuration
client := instavm.New("your_api_key")

// Custom configuration
client := instavm.NewWithOptions("your_api_key", instavm.Options{
BaseURL: "https://api.instavm.io", // Custom API endpoint
Timeout: 30 * time.Second, // Request timeout
})

defer client.Close()
}

Using Environment Variables

package main

import (
"os"

"github.com/instavm/instavm-go"
)

func main() {
// Set API key via environment variable
os.Setenv("INSTAVM_API_KEY", "your_api_key")
client := instavm.New(os.Getenv("INSTAVM_API_KEY"))
defer client.Close()
}

Core Methods

Execute(ctx, command)

Execute code synchronously on a virtual machine.

package main

import (
"context"
"fmt"
"log"

"github.com/instavm/instavm-go"
)

func main() {
client := instavm.New("your_api_key")
defer client.Close()

ctx := context.Background()
result, err := client.Execute(ctx, `
import "math"

result := math.Sqrt(16)
fmt.Printf("Square root of 16 is %.1f\n", result)
`)

if err != nil {
log.Fatal(err)
}

fmt.Printf("Output: %s\n", result.Output) // Square root of 16 is 4.0
fmt.Printf("Execution time: %.3fs\n", result.ExecutionTime) // 0.123
}

UploadFile(ctx, filePath)

Upload a file to the virtual machine.

package main

import (
"context"
"fmt"
"log"

"github.com/instavm/instavm-go"
)

func main() {
client := instavm.New("your_api_key")
defer client.Close()

ctx := context.Background()

// Upload a file
result, err := client.UploadFile(ctx, "/path/to/local/file.txt")
if err != nil {
log.Fatal(err)
}

fmt.Printf("Uploaded %s, size: %d bytes\n", result.Filename, result.Size)

// Now execute code that uses the file
execResult, err := client.Execute(ctx, `
package main

import (
"fmt"
"io/ioutil"
)

func main() {
content, err := ioutil.ReadFile("file.txt")
if err != nil {
panic(err)
}
fmt.Println(string(content))
}
`)

if err != nil {
log.Fatal(err)
}

fmt.Println(execResult.Output)
}

GetUsage(ctx)

Get usage metrics for the current session.

package main

import (
"context"
"fmt"
"log"

"github.com/instavm/instavm-go"
)

func main() {
client := instavm.New("your_api_key")
defer client.Close()

ctx := context.Background()

// Execute some code first
_, err := client.Execute(ctx, "fmt.Println(\"Hello World\")")
if err != nil {
log.Fatal(err)
}

// Get usage metrics
usage, err := client.GetUsage(ctx)
if err != nil {
log.Fatal(err)
}

fmt.Printf("CPU Time: %.3fs\n", usage.CPUTime)
fmt.Printf("Memory Used: %d bytes\n", usage.MemoryUsed)
fmt.Printf("Network I/O: %d bytes\n", usage.NetworkIO)
}

Session Management

package main

import (
"context"
"fmt"
"log"

"github.com/instavm/instavm-go"
)

func main() {
client := instavm.New("your_api_key")
// Session started automatically
defer client.Close() // Always close session

ctx := context.Background()
result, err := client.Execute(ctx, "fmt.Println(\"Session managed automatically\")")
if err != nil {
log.Fatal(err)
}

fmt.Println(result.Output)
}

Manual Session Management

package main

import (
"context"
"fmt"
"log"

"github.com/instavm/instavm-go"
)

func main() {
client := instavm.New("your_api_key")
defer client.Close()

ctx := context.Background()

// Start session explicitly (optional, as it starts automatically)
err := client.StartSession(ctx)
if err != nil {
log.Fatal(err)
}

result, err := client.Execute(ctx, "fmt.Println(\"Manual session management\")")
if err != nil {
log.Fatal(err)
}

// Check session status
isActive := client.IsSessionActive(ctx)
fmt.Printf("Session is active: %t\n", isActive)

// Get session info
info, err := client.GetSessionInfo(ctx)
if err != nil {
log.Fatal(err)
}

fmt.Printf("Session ID: %s\n", info.SessionID)
}

Error Handling

The SDK provides specific error types for different scenarios:

package main

import (
"context"
"fmt"

"github.com/instavm/instavm-go"
)

func main() {
client := instavm.New("invalid_api_key")
defer client.Close()

ctx := context.Background()
_, err := client.Execute(ctx, "fmt.Println(\"This will fail\")")

if err != nil {
switch e := err.(type) {
case *instavm.Error:
switch e.Type {
case "AUTHENTICATION":
fmt.Println("Invalid API key provided")
case "SESSION":
fmt.Printf("Session error: %s\n", e.Message)
case "EXECUTION":
fmt.Printf("Code execution failed: %s\n", e.Message)
case "NETWORK":
fmt.Printf("Network issue: %s\n", e.Message)
case "RATE_LIMIT":
fmt.Printf("Rate limit exceeded: %s\n", e.Message)
default:
fmt.Printf("InstaVM error: %s\n", e.Message)
}
default:
fmt.Printf("Unexpected error: %v\n", err)
}
}
}

Advanced Examples

Data Processing with Goroutines

package main

import (
"context"
"fmt"
"log"
"sync"

"github.com/instavm/instavm-go"
)

func processData(client *instavm.Client, data string, wg *sync.WaitGroup) {
defer wg.Done()

ctx := context.Background()
code := fmt.Sprintf(`
package main

import (
"fmt"
"strings"
)

func main() {
data := "%s"
words := strings.Fields(data)
fmt.Printf("Data: %%s, Word count: %%d\n", data, len(words))
}
`, data)

result, err := client.Execute(ctx, code)
if err != nil {
log.Printf("Error processing data '%s': %v", data, err)
return
}

fmt.Printf("Result: %s", result.Output)
}

func main() {
client := instavm.New("your_api_key")
defer client.Close()

datasets := []string{
"Hello world from InstaVM",
"Go is a powerful programming language",
"Concurrent processing with goroutines",
}

var wg sync.WaitGroup

for _, data := range datasets {
wg.Add(1)
go processData(client, data, &wg)
}

wg.Wait()
fmt.Println("All data processed!")
}

Web Server with Gin Framework

package main

import (
"context"
"fmt"
"log"

"github.com/instavm/instavm-go"
)

func main() {
client := instavm.New("your_api_key")
defer client.Close()

ctx := context.Background()

result, err := client.Execute(ctx, `
package main

import (
"log"
"net/http"
"strconv"
"time"

"github.com/gin-gonic/gin"
)

type CalculationRequest struct {
A float64 ` + "`" + `json:"a"` + "`" + `
B float64 ` + "`" + `json:"b"` + "`" + `
Operation string ` + "`" + `json:"operation"` + "`" + `
}

type CalculationResponse struct {
Result float64 ` + "`" + `json:"result"` + "`" + `
Error string ` + "`" + `json:"error,omitempty"` + "`" + `
}

func main() {
gin.SetMode(gin.ReleaseMode)
r := gin.New()

r.POST("/calculate", func(c *gin.Context) {
var req CalculationRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, CalculationResponse{
Error: "Invalid request format",
})
return
}

var result float64
var errMsg string

switch req.Operation {
case "add":
result = req.A + req.B
case "subtract":
result = req.A - req.B
case "multiply":
result = req.A * req.B
case "divide":
if req.B != 0 {
result = req.A / req.B
} else {
errMsg = "Division by zero"
}
default:
errMsg = "Invalid operation"
}

if errMsg != "" {
c.JSON(http.StatusBadRequest, CalculationResponse{Error: errMsg})
} else {
c.JSON(http.StatusOK, CalculationResponse{Result: result})
}
})

// Start server in a goroutine
go func() {
if err := r.Run(":8080"); err != nil {
log.Printf("Server failed to start: %v", err)
}
}()

// Simulate some requests
time.Sleep(100 * time.Millisecond)

// Make test request
// Note: In a real scenario, you'd make HTTP requests from outside
fmt.Println("Web server started on :8080")
fmt.Println("Example endpoints:")
fmt.Println("POST /calculate")
fmt.Println(` + "`" + `{"a": 10, "b": 5, "operation": "add"}` + "`" + `)

time.Sleep(1 * time.Second)
}
`)

if err != nil {
log.Fatal(err)
}

fmt.Println(result.Output)
}

File Processing and Analysis

package main

import (
"context"
"fmt"
"log"

"github.com/instavm/instavm-go"
)

func main() {
client := instavm.New("your_api_key")
defer client.Close()

ctx := context.Background()

// Upload a data file
uploadResult, err := client.UploadFile(ctx, "/path/to/data.csv")
if err != nil {
log.Fatal(err)
}

fmt.Printf("Uploaded %s\n", uploadResult.Filename)

// Process the CSV file
result, err := client.Execute(ctx, `
package main

import (
"encoding/csv"
"fmt"
"io"
"os"
"strconv"
)

func main() {
file, err := os.Open("data.csv")
if err != nil {
panic(err)
}
defer file.Close()

reader := csv.NewReader(file)
var sum float64
var count int

// Skip header if present
if _, err := reader.Read(); err != nil && err != io.EOF {
panic(err)
}

for {
record, err := reader.Read()
if err == io.EOF {
break
}
if err != nil {
panic(err)
}

// Assume numeric data in first column
if len(record) > 0 {
if value, err := strconv.ParseFloat(record[0], 64); err == nil {
sum += value
count++
}
}
}

if count > 0 {
average := sum / float64(count)
fmt.Printf("Processed %d records\n", count)
fmt.Printf("Sum: %.2f\n", sum)
fmt.Printf("Average: %.2f\n", average)
} else {
fmt.Println("No valid numeric data found")
}
}
`)

if err != nil {
log.Fatal(err)
}

fmt.Println(result.Output)
}

Context and Timeout Management

package main

import (
"context"
"fmt"
"log"
"time"

"github.com/instavm/instavm-go"
)

func main() {
client := instavm.New("your_api_key")
defer client.Close()

// Create context with timeout
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

// Execute long-running code with timeout
result, err := client.Execute(ctx, `
package main

import (
"fmt"
"time"
)

func main() {
fmt.Println("Starting long operation...")

for i := 0; i < 5; i++ {
time.Sleep(1 * time.Second)
fmt.Printf("Step %d/5 completed\n", i+1)
}

fmt.Println("Operation completed!")
}
`)

if err != nil {
log.Fatal(err)
}

fmt.Println(result.Output)
}

// Example with cancellation
func cancellationExample() {
client := instavm.New("your_api_key")
defer client.Close()

ctx, cancel := context.WithCancel(context.Background())

// Cancel after 3 seconds
go func() {
time.Sleep(3 * time.Second)
fmt.Println("Cancelling operation...")
cancel()
}()

_, err := client.Execute(ctx, `
package main

import (
"fmt"
"time"
)

func main() {
for i := 0; i < 10; i++ {
time.Sleep(1 * time.Second)
fmt.Printf("Working... %d\n", i)
}
}
`)

if err != nil {
fmt.Printf("Operation was cancelled: %v\n", err)
}
}

Types and Structures

ExecutionResult

type ExecutionResult struct {
Output string `json:"output"`
ExecutionTime float64 `json:"execution_time"`
Error string `json:"error,omitempty"`
SessionID string `json:"session_id,omitempty"`
}

SessionInfo

type SessionInfo struct {
SessionID string `json:"session_id"`
CreatedAt time.Time `json:"created_at"`
Status string `json:"status"`
}

UsageInfo

type UsageInfo struct {
CPUTime float64 `json:"cpu_time"`
MemoryUsed int64 `json:"memory_used"`
NetworkIO int64 `json:"network_io"`
ExecutionTime float64 `json:"execution_time"`
}

Error

type Error struct {
Type string `json:"type"`
Message string `json:"message"`
Code int `json:"code,omitempty"`
}

Performance Tips

  1. Use defer for cleanup: Always defer client.Close() to ensure sessions are closed
  2. Context management: Use contexts for timeout and cancellation control
  3. Reuse clients: Create one client instance for multiple operations
  4. Handle errors appropriately: Check error types for specific handling
  5. Use goroutines: Leverage Go's concurrency for parallel processing

Configuration Options

ParameterDefaultDescription
apiKeyRequiredYour InstaVM API key
BaseURLhttps://api.instavm.ioAPI endpoint URL
Timeout30sRequest timeout duration

Next Steps