Article
· 18 hr ago 5m read

The Wait Is Over: Welcome GoLang Support for InterSystems IRIS

Introduction

The InterSystems IRIS Data Platform has long been known for its performance, interoperability, and flexibility across programming languages. For years, developers could use IRIS with Python, Java, JavaScript, and .NET — but Go (or Golang) developers were left waiting.

Golang Logo

That wait is finally over.

The new go-irisnative driver brings GoLang support to InterSystems IRIS, implementing the standard database/sql API. This means Go developers can now use familiar database tooling, connection pooling, and query interfaces to build applications powered by IRIS.


Why GoLang Support Matters

GoLang is a language designed for simplicity, concurrency, and performance — ideal for cloud-native and microservices-based architectures. It powers some of the world’s most scalable systems, including Kubernetes, Docker, and Terraform.

Bringing IRIS into the Go ecosystem enables:

  • Lightweight, high-performance services using IRIS as the backend.
  • Native concurrency for parallel query execution or background processing.
  • Seamless integration with containerized and distributed systems.
  • Idiomatic database access through Go’s database/sql interface.

This integration makes IRIS a perfect fit for modern, cloud-ready Go applications.


Getting Started

1. Installation

go get github.com/caretdev/go-irisnative

2. Connecting to IRIS

Here’s how to connect using the standard database/sql API:

import (
    "database/sql"
    "fmt"
    "log"
    _ "github.com/caretdev/go-irisnative"
)

func main() {
    db, err := sql.Open("iris", "iris://_SYSTEM:SYS@localhost:1972/USER")
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()

    // Simple ping to test connection
    if err := db.Ping(); err != nil {
        log.Fatal("Failed to connect:", err)
    }

    fmt.Println("Connected to InterSystems IRIS!")
}

3. Creating a Table

Let’s create a simple demo table:

_, err = db.Exec(`CREATE TABLE IF NOT EXISTS demo (
    id INT PRIMARY KEY,
    name VARCHAR(50)
)`)
if err != nil {
    log.Fatal(err)
}
fmt.Println("Table created.")

4. Inserting Data

At this time, multi-row inserts are not supported — insert one row per call:

_, err = db.Exec(`INSERT INTO demo (id, name) VALUES (?, ?)`, 1, "Alice")
if err != nil {
    log.Fatal(err)
}

_, err = db.Exec(`INSERT INTO demo (id, name) VALUES (?, ?)`, 2, "Bob")
if err != nil {
    log.Fatal(err)
}

fmt.Println("Data inserted.")

5. Querying Data

Querying is straightforward using the database/sql interface:

rows, err := db.Query(`SELECT id, name FROM demo`)
if err != nil {
    log.Fatal(err)
}
defer rows.Close()

for rows.Next() {
    var id int
    var name string
    if err := rows.Scan(&id, &name); err != nil {
        log.Fatal(err)
    }
    fmt.Printf("ID: %d, Name: %s\n", id, name)
}

That’s all you need to perform basic SQL operations from Go.


How It Works

Under the hood, the go-irisnative driver uses the IRIS Native API for efficient, low-level communication with the database. The driver implements Go’s standard database/sql/driver interfaces, making it compatible with existing Go tools such as:

  • sqlx
  • gorm (with a custom dialect)
  • Standard Go migration tools

This gives developers a familiar API with the power and performance of native IRIS access.


Example Use Cases

  • Microservices — lightweight Go services connecting directly to IRIS.
  • Data APIs — expose REST or gRPC endpoints backed by IRIS.
  • Integration tools — bridge IRIS data with other systems in Go-based pipelines.
  • Cloud-native IRIS apps — deploy IRIS-backed Go apps on Kubernetes or Docker.

Testing with Testcontainers

If you want to run automated tests without managing a live IRIS instance, you can use testcontainers-iris-go.
It launches a temporary IRIS container for integration testing.

Example test setup:

import (
    "context"
    "database/sql"
    "flag"
    "log"
    "os"
    "testing"
    iriscontainer "github.com/caretdev/testcontainers-iris-go"
    "github.com/stretchr/testify/require"
    "github.com/testcontainers/testcontainers-go"
)

var connectionString string = "iris://_SYSTEM:SYS@localhost:1972/USER"
var container *iriscontainer.IRISContainer = nil
func TestMain(m *testing.M) {
    var (
        useContainer   bool
        containerImage string
    )
    flag.BoolVar(&useContainer, "container", true, "Use container image.")
    flag.StringVar(&containerImage, "container-image", "", "Container image.")
    flag.Parse()
    var err error
    ctx := context.Background()
    if useContainer || containerImage != "" {
        options := []testcontainers.ContainerCustomizer{
            iriscontainer.WithNamespace("TEST"),
            iriscontainer.WithUsername("testuser"),
            iriscontainer.WithPassword("testpassword"),
        }
        if containerImage != "" {
            container, err = iriscontainer.Run(ctx, containerImage, options...)
        } else {
            // or use default docker image
            container, err = iriscontainer.RunContainer(ctx, options...)
        }
        if err != nil {
            log.Println("Failed to start container:", err)
            os.Exit(1)
        }
        defer container.Terminate(ctx)
        connectionString = container.MustConnectionString(ctx)
        log.Println("Container started successfully", connectionString)
    }

    var exitCode int = 0
    exitCode = m.Run()

    if container != nil {
        container.Terminate(ctx)
    }
    os.Exit(exitCode)
}

func openDbWrapper[T require.TestingT](t T, dsn string) *sql.DB {
    db, err := sql.Open(`intersystems`, dsn)
    require.NoError(t, err)
    require.NoError(t, db.Ping())
    return db
}

func closeDbWrapper[T require.TestingT](t T, db *sql.DB) {
    if db == nil {
        return
    }
    require.NoError(t, db.Close())
}

func TestConnect(t *testing.T) {
    db := openDbWrapper(t, connectionString)
    defer closeDbWrapper(t, db)

    var (
        namespace string
        username  string
    )
    res := db.QueryRow(`SELECT $namespace, $username`)
    require.NoError(t, res.Scan(&namespace, &username))
    require.Equal(t, "TEST", namespace)
    require.Equal(t, "testuser", username)
}

This is ideal for CI/CD pipelines or unit tests, ensuring your Go application works seamlessly with IRIS in isolation.


Conclusion

GoLang support for InterSystems IRIS is here — and it’s a game-changer.
With go-irisnative, you can now build scalable, concurrent, and cloud-native applications that tap directly into the power of IRIS.

Whether you’re building microservices, APIs, or integration tools, Go gives you simplicity and performance, while IRIS gives you reliability and rich data capabilities.

👉 Try it out:

Discussion (0)1
Log in or sign up to continue