We’re excited to announce the 1.7 series of our official Neo4j Drivers. As well as the regular improvements and new features, we’ve also introduced a new language to our driver family: Go.

Ali Ince
Ali Ince
Nov 13, 2018 · 5 min read

We’ve seen a big demand for Go over the past few years and began work on it a while back. You may have read our other blog post from earlier in the release cycle. The first release is version 1.7, which brings Go immediately in line with our other languages in terms of features (such as routing for causal clusters).

The Go driver is the first driver built on top of our C Connector, Seabolt. This provides the building blocks for the Bolt protocol and the routing logic required to effectively communicate with causal clusters. Installing a C library naturally comes with cross platform challenges and we are aware that there are several different deployment scenarios out there. For that reason, we’ve put together a few easy-to-use binary packages and are also working on alternative installation mechanisms.

In this blog post, we’ll be guiding you on how to build a simple Neo4j-backed Go application that executes a specified query against the database and prints the returned results out.

What do you need to get started?

First of all, you need to have a working cgo development environment. We also depend on pkg-config to discover Seabolt-related compiler and linker parameters.

Having sorted out these, you’ll need to have Seabolt headers and libraries installed as well. Our experimental binary packages for popular platforms can be found here — or you can simply build from source.

If you get stuck on installing any of these requirements, both neo4j-go-driver and seabolt repositories contain detailed instructions that can guide you to success.

We’ll be using dep in the next sections since it makes our lives a bit easier to manage dependencies.

Skeleton

Let’s start with some skeleton code. We are expecting the user to provide us a Bolt URI, a username and a password along with a Cypher query to execute and output its results.

The starter skeleton

When you save the above contents on your main.go file, then execute dep init && dep ensure -add github.com/neo4j/neo4j-go-driver/neo4j in the same directory where this main.go file resides. This will pull in the driver from GitHub.

Creating a driver instance

Every application requires a Driver instance. This can be created using theneo4j.NewDriver function. The function expects a bolt URI, an authentication token and an optional list of configuration functions that can tweak possible configuration options including connection pool management, trust strategy, etc.

Creating a driver instance

Each driver instance is thread-safe and holds a pool of connections that can be re-used over time. If you don’t have a good reason to do otherwise, a typical application should have a single driver instance throughout its lifetime.

Acquiring a session

In order to execute a query against the database we need a neo4j.Session instance. A session is a container for a sequence of transactions, where it borrows connections from the underlying connection pool as required and returns them back when they are no more needed. Please bear in mind that session objects are not thread-safe and should not be accessed concurrently.

Sessions can be acquired from a driver object through its Session() function. This expects an access mode, which specifies whether the intended operation is read or write, plus an optional list of bookmarks to establish the casual chain on the server.

Acquiring a session instance

Executing a query and processing results

Now that you have acquired a session, you are ready to execute Cypher queries. There are several options here. The simplest is to issue queries in auto-commit transactions with the session.Run function. This is limited to allowing only one statement per transaction, but requires least code. You can also create an explicit transaction with session.BeginTransaction and gain more control over the transaction process. Lastly, we provide transaction functions through session.ReadTransaction and session.WriteTransaction which not only hide the transaction control logic but also bring in automatic retry capabilities to overcome transient failures related to network errors or casual cluster re-elections, etc.

We’ll make use of transaction functions in this blog post, since this is our preferred means of query execution. This requires a function object that can execute the query and perform the actual record processing.

Transaction function and result processing

The transaction function can be invoked with session.ReadTransaction. Here, a transaction will be created and the function itself will be called. If this completes successfully (i.e. doesn’t return any error) then the transaction will be committed, if not it will be rolled back.

Executing the transaction function

If you’re using a write query instead of a read query then you’ll need WriteTransaction instead. The choice of function sets the access mode which is used along with the driver’s routing table to select an appropriate server for execution.

We haven’t used query parameters (passed as nil to tx.Run above) for this blog post, but parameters are expected to be of type map[string]interface{} and can be passed as follows:

tx.Run("RETURN $x", map[string]interface{}{"x": 10})

Completed source

So, here is our complete example…

Complete source code

Let’s run it

Assuming you’ve followed each step, you can simply execute the code using go run main.go. Without an argument, this will display a usage message. In order to properly execute it with a real Cypher query, other options can be provided:

go run main.go -uri bolt://localhost:7687 -username neo4j -password password -query "UNWIND RANGE(1,5) AS N RETURN N AS SEQUENCE, 'Text ' + N AS TEXT"

This should produce the following output:

SEQUENCE   TEXT      
========== ==========
1 Text1
2 Text2
3 Text3
4 Text4
5 Text5
5 records processed

What about static linking, is this possible?

Yes! As we mentioned in the introduction, we’ve been working on improving the installation options for Seabolt.

Below is a Docker file to create a statically linked executable from the source code and run it :

This file should hopefully be mostly self describing. To see it in action, save this file on your Docker-enabled computer as Dockerfile and issue the following command in the same directory:

docker image build -t neo4j-go-driver-blog-post .

This will build Seabolt and our sample executable and copy it to a Neo4j-based image, tagged as neo4j-go-driver-blog-post.

Now, fire up a new container from this image:

docker container run --name go-driver-blog-post neo4j-go-driver-blog-post

When it says that Neo4j has started, we can run our sample in another terminal:

docker container exec go-driver-blog-post /blog/sample -uri bolt://localhost:7687 -username neo4j -password neo4j -query "UNWIND RANGE(1,5) AS N RETURN N AS SEQUENCE, 'Text' + N AS TEXT"

You should see the following output (from a single executable without any external dependencies):

SEQUENCE   TEXT      
========== ==========
1 Text1
2 Text2
3 Text3
4 Text4
5 Text5
5 records processed

That’s all for now, apart from to mention that as with our other official drivers, the API is designed to be topologically agnostic — which means that you can run the above code against a casual cluster only by pointing it to a URL with a bolt+routing scheme (like bolt+routing://server1:7687).

We’ve covered most of the essential parts on how to use our new Go driver. We hope that you like it!

If you run into any issues, please feel free to ask questions on our neo4j community site or open a GitHub issue.

Neo4j Developer Blog

Developer Content around Graph Databases, Neo4j, Cypher, Data Science, Graph Analytics, GraphQL and more.

Thanks to Andrew Jefferson

Ali Ince

Written by

Ali Ince

Neo4j Developer Blog

Developer Content around Graph Databases, Neo4j, Cypher, Data Science, Graph Analytics, GraphQL and more.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade