# go-oci8: a database/sql driver for Oracle that requires the client libraries

> go-oci8 is a Go database/sql driver for Oracle that binds to the OCI client through cgo, which means the Oracle client libraries have to be installed and located on the build and runtime machines before anything compiles.

**mattn/go-oci8** — Oracle driver for Go using database/sql

- Repository: https://github.com/mattn/go-oci8
- Website: https://mattn.kaoriya.net/
- Stars: 634 · Forks: 212
- Language: Go
- License: MIT
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/mattn-go-oci8

## database/sql, with Oracle's client underneath

go-oci8 is described in one line as a Golang Oracle database driver conforming to the Go database/sql interface. That phrase sets the scope precisely. It is not an ORM and not an Oracle specific abstraction layer; it registers a driver with database/sql, so you open a sql.DB, pass a data source name, and use the same interface you would use for any other SQL database. The audience is Go developers who have to talk to an existing Oracle database, most often because a company already runs Oracle and the service being written has to reach it. The repository is a single package at the root, with connection.go, connector.go, dsn.go, rows.go, statement.go and globals.go, plus c_helpers.go for the cgo boundary. The author is Yasuhiro Matsumoto, also known as mattn, and the licence is MIT. The module declares a go 1.13 baseline in go.mod, and the README asks for Go 1.9 or higher when fetching the package.

## The cgo requirement is the whole installation story

Installation is where most of the friction lives, and the README is upfront about it. You need to install either the Oracle full client or Instant Client, and you need a C or C++ compiler. The driver is not a pure Go implementation of the Oracle wire protocol; it binds to the Oracle client interface through cgo, which is why the compiler requirement exists at all. After that you install pkg-config, edit a package config file named oci8.pc to point at the client, and set the PKG_CONFIG_PATH environment variable to the location of that file. The README offers an alternative for people who do not want to deal with pkg-config: use the Go build tag noPkgConfig and set the CGO_CFLAGS and CGO_LDFLAGS environment variables yourself. That choice is a real fork in the road, because pkg-config is what makes the build portable across machines while manual flags are what make it fragile.

## Writing oci8.pc for each platform

The README gives a worked example for Windows, Linux and macOS, and the differences between them are instructive. The Windows example points the libdir at the msvc subdirectory of the Instant Client SDK and links with -loci, while the Linux example points at the client64 directory under /usr/lib/oracle and links with -lclntsh. The macOS example is different again, linking with -lclntsh and using a libdir that is the Instant Client root itself. The shared structure is the same in all three: a prefix, a libdir, an includedir, and then the Name, Description, Libs and Cflags fields that pkg-config actually reads.

```
prefix=/devel/target/XXXXXXXXXXXXXXXXXXXXXXXXXX
exec_prefix=${prefix}
libdir=C:/app/instantclient_12_2/sdk/oci/lib/msvc
includedir=C:/app/instantclient_12_2/sdk/include
```

Note the Version field in all three examples is 12.2, and the paths carry the 12_2 client directory name. That is the clearest signal in the README about which client generation these instructions were written against, and it is the first thing to check if your build fails.

## macOS needs two environment variables beyond pkg-config

On macOS the README goes further than the other two platforms. It asks you to install pkg-config with brew if it is not already there, to download the Instant Client and the SDK and unpack them, for example into the Downloads folder, and then to create a file named oci8.pc in that directory with the username placeholder replaced. The example configuration on that platform is short, with a prefixdir pointing at the unpacked Instant Client, a libdir set to that same prefixdir, and an includedir under sdk/include.

```
prefixdir=/Users/<username>/Downloads/instantclient_12_2/
libdir=${prefixdir}
includedir=${prefixdir}/sdk/include
```

Two environment variables then have to be exported, and the README suggests making them permanent by adding them to your .bashrc.

```
export LD_LIBRARY_PATH=/Users/<username>/Downloads/instantclient_12_2
export PKG_CONFIG_PATH=/Users/<username>/Downloads/instantclient_12_2
```

This is the part of the setup that catches macOS users out. The library path is what lets the dynamic loader find libclntsh at runtime, and it is separate from the build time configuration, so a program that compiled cleanly can still fail to start if the environment is not set in the process that runs it.

## Where to look for the SQL examples and how to debug a build failure

The README does not carry SQL examples itself, and it says where to find them instead. The GoDoc reference is the primary source, with the simple select example linked directly, and an _example directory in the repository holds more. The driver exposes the standard database/sql surface, so most of that is familiar, and the Oracle specific parts are where the examples earn their place. On the debugging side the README gives a blunt but useful instruction: if you have a build error it is normally because of a misconfiguration, and you should search closed issues for help. That is a reasonable thing to say about a cgo driver, since the failure surface is the toolchain and the client libraries rather than the driver logic. The repository layout backs this up with a .github workflow for tests, several example_sql files that exercise the standard library test suites, and test.sh plus test_cleanup.sh scripts for running them.

## A driver with an old release history and a recent commit

The release history deserves a note because the numbers and the commit dates point in different directions. The tagged releases are v0.0.9 in October 2020, v0.1.0 later that month, and v0.1.1 in January 2021, and there is nothing after that. The repository itself was last pushed to on 2026-07-08, so work has continued on the branch without a new tag. The version remains below 1.0 for a driver that people put in production paths, which in Go terms normally signals an API that may still move, though in practice the database/sql surface it exposes is narrow enough that the risk is mostly in the Oracle specific extras. The licence is MIT, which means you can vendor it inside a proprietary service without restriction, which is the usual reason teams pick a driver with a single author. The homepage is mattn.kaoriya.net, and the GoDoc badge points at the package documentation.

## Where go-oci8 is the wrong tool

The cgo dependency is the deciding factor in most evaluations. Any Go project that must cross-compile with CGO_ENABLED=0, for example into a scratch container or a serverless function, cannot use this driver, because the Oracle client is a native library and the driver is a binding to it. A container image has to carry the Instant Client, which is a licensing and image size question on its own. The second limit is the client version, since the documented configuration targets 12.2 and newer client generations with their own directory layout, so an environment on a much newer or older client needs adjusted paths, and the README does not document those. The third is that the tagged versions stop in 2021, so if you need a version with a specific fix you are tracking a branch rather than a release. The alternative to weigh is a pure Go driver for Oracle, which avoids cgo entirely and cross compiles cleanly at the cost of implementing the protocol itself and, depending on the driver, a narrower feature set. If your build pipeline already ships the Oracle client, go-oci8 is the conventional choice; if it does not, that decision is the whole evaluation.

## Conclusion

Adopt go-oci8 if your service already runs against Oracle and you want to keep the standard database/sql API instead of an Oracle specific client. Do not adopt it for a containerised build unless you accept shipping the Oracle client, because the driver links to it through cgo. Verify first which client version you have, since the documented pkg-config examples all target the 12.2 Instant Client, and note that the tagged releases stop at v0.1.1 from 2021 even though the repository was pushed to on 2026-07-08.

## FAQ

### What does go-oci8 require before it will build?

You need the Oracle full client or Instant Client installed, a C or C++ compiler, and pkg-config with an edited oci8.pc file whose location is set in PKG_CONFIG_PATH. Alternatively you can use the noPkgConfig Go build tag and set CGO_CFLAGS and CGO_LDFLAGS yourself.

### How do I install the go-oci8 package?

The README gives the fetch command as go get github.com/mattn/go-oci8, and states that Go 1.9 or higher is needed. The go.mod file in the repository declares a go 1.13 baseline.

### Where can I find SQL examples for go-oci8?

The README points to the GoDoc reference, including a simple select example, and to the _example directory in the repository for more. The driver conforms to the database/sql interface, so the usual Go database examples apply.

### Can go-oci8 be cross compiled without cgo?

The driver binds to the Oracle client interface through cgo, so it needs a C or C++ compiler and the native client libraries present at build and run time. The README does not describe a pure Go build path.

## Sources

- [License: MIT](https://github.com/mattn/go-oci8/blob/master/LICENSE)
- [mattn/go-oci8 on GitHub](https://github.com/mattn/go-oci8)
- [Project website](https://mattn.kaoriya.net/)
- [README](https://github.com/mattn/go-oci8/blob/master/README.md)
- [Releases](https://github.com/mattn/go-oci8/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/mattn-go-oci8
