Go, also known as Golang, is a statically-typed, concurrent programming language created by Google. ClickHouse is a high-performance, column-oriented database management system that can be used for real-time data analysis.
This tutorial will provide a deep dive into how to connect to ClickHouse from a Go program, including how to perform common database operations such as SELECT and INSERT statements.
Before proceeding, it is assumed that you already have Go and ClickHouse installed on your machine. If not, you can download the latest version of Go from the official website and install it by following the instructions provided. You can also download and install ClickHouse from the official website.
To get started, we need to import the Go library for connecting to databases. The library we will be using in this tutorial is "github.com/kshvakov/clickhouse." To install it, run the following command in your terminal or command prompt:
go get github.com/kshvakov/clickhouse
import (
"github.com/kshvakov/clickhouse"
)
clickhouse.Open
db, err := clickhouse.Open("tcp://127.0.0.1:9000?database=test_db&username=default&password=")
if err != nil {
panic(err)
}
defer db.Close()
Once we have established a connection, we can start executing SQL statements against the database.
Let's start by creating a table in the database:
_, err = db.Exec(`
CREATE TABLE users (
id UInt64,
name String,
age UInt8
) ENGINE = Memory
`)
if err != nil {
panic(err)
}
In this example, we are creating a table named "users" with three columns: "id", "name", and "age". The table is stored in memory for the purpose of this tutorial, but you can change the engine to any of the available engines supported by ClickHouse, such as MergeTree, ReplacingMergeTree, or CollapsingMergeTree.
Next, let's insert some data into the "users" table:
_, err = db.Exec(`
INSERT INTO users (id, name, age)
VALUES (1, 'John Doe', 35), (2, 'Jane Doe', 32)
`)
if err != nil {
panic(err)
}
Now that we have data in the "users" table, let's retrieve it by executing a SELECT statement:
rows, err := db.Query(`
SELECT id, name, age FROM users
`)
if err != nil {
panic(err)
}
defer rows.Close
Next, we will iterate over the rows returned by the SELECT statement and print the results:
for rows.Next() {
var id uint64
var name string
var age uint8
if err := rows.Scan(&id, &name, &age); err != nil {
panic(err)
}
fmt.Printf("%d, %s, %d\n", id, name, age)
}
rows.Scan
The above code should produce the following output:
1, John Doe, 35
2, Jane Doe, 32
The complete code may look like:
package main
import (
"bufio"
"database/sql"
"fmt"
"github.com/kshvakov/clickhouse"
"os"
)
func main() {
// Connect to the ClickHouse server
dsn := "tcp://127.0.0.1:9000?debug=true"
db, err := sql.Open("clickhouse", dsn)
if err != nil {
panic(err)
}
defer db.Close()
// Create the "users" table
_, err = db.Exec(`
CREATE TABLE IF NOT EXISTS users (
id UInt64,
name String,
age UInt8
) ENGINE = Memory
`)
if err != nil {
panic(err)
}
// Insert data into the table using a bulk insert
w := bufio.NewWriter(clickhouse.NewWriteTo(
db,
"INSERT INTO users (id, name, age) VALUES",
1000,
))
defer w.Flush()
fmt.Fprintln(w, "1, 'John Doe', 35")
fmt.Fprintln(w, "2, 'Jane Doe', 32")
// Retrieve the data from the table using a SELECT statement and stream the results
rows, err := db.Query("SELECT * FROM users")
if err != nil {
panic(err)
}
defer rows.Close()
// Iterate over the rows returned by the SELECT statement and print the results
for rows.Next() {
var id uint64
var name string
var age uint8
if err := rows.Scan(&id, &name, &age); err != nil {
panic(err)
}
fmt.Printf("%d, %s, %d\n", id, name, age)
}
}
If using prepared statements, it would look like:
package main
import (
"database/sql"
"fmt"
"github.com/kshvakov/clickhouse"
)
func main() {
// Connect to the ClickHouse server
dsn := "tcp://127.0.0.1:9000?debug=true"
db, err := sql.Open("clickhouse", dsn)
if err != nil {
panic(err)
}
defer db.Close()
// Create the "users" table
_, err = db.Exec(`
CREATE TABLE IF NOT EXISTS users (
id UInt64,
name String,
age UInt8
) ENGINE = Memory
`)
if err != nil {
panic(err)
}
// Insert data into the table using a prepared statement
stmt, err := db.Prepare(`INSERT INTO users (id, name, age) VALUES (?, ?, ?)`)
if err != nil {
panic(err)
}
defer stmt.Close()
_, err = stmt.Exec(1, "John Doe", 35)
if err != nil {
panic(err)
}
_, err = stmt.Exec(2, "Jane Doe", 32)
if err != nil {
panic(err)
}
// Retrieve the data from the table using a prepared SELECT statement and retrieve the results
stmt, err = db.Prepare("SELECT * FROM users")
if err != nil {
panic(err)
}
defer stmt.Close()
rows, err := stmt.Query()
if err != nil {
panic(err)
}
defer rows.Close()
// Iterate over the rows returned by the SELECT statement and print the results
for rows.Next() {
var id uint64
var name string
var age uint8
if err := rows.Scan(&id, &name, &age); err != nil {
panic(err)
}
fmt.Printf("%d, %s, %d\n", id, name, age)
}
}
This is just a simple example of how to connect to ClickHouse and perform basic database operations using Go. You can also use this library to perform more complex operations such as transactions, bulk inserts, and more.
github.com/kshvakov/clickhouse
db.Readdb.Write
github.com/kshvakov/clickhouse