Library / SDK
yalue/onnxruntime_go avatar
yalue/onnxruntime_go

onnxruntime_go loads ONNX models in Go by loading the runtime by hand

A Go (golang) library wrapping microsoft/onnxruntime.

731 stars91 forksGoMIT

At a glance

What is it?
The onnxruntime_go library gives Go programs access to Microsoft's ONNX Runtime by loading the shared library manually rather than linking against it, which is the trick that makes the wrapper work on Windows as well as Linux and macOS.
Who is it for?
onnxruntime_go suits a Go service that has to run an ONNX model in process, and it suits a team that has hit the Windows problem with every other ONNX binding and wants one wrapper that covers all three platforms.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 49 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The Windows problem shapes the whole design

The library seeks to provide an interface for loading and executing neural networks from Go code, while remaining as simple to use as possible, and the interesting part is the mechanism. The onnxruntime library provides a way to load and execute ONNX-format neural networks, though the library primarily supports C and C++ APIs. Several efforts exist to have written Go wrappers for it, but as far as the author can tell, none of them support Windows, and the reason given is specific: Microsoft's onnxruntime assumes the user will be using the MSVC compiler on Windows, while CGo on Windows requires using Mingw. The workaround is to manually load the onnxruntime shared library, removing any dependency on the onnxruntime source code beyond the header files. The readme notes that this approach works equally well on non-Windows systems, so the fix for a Windows problem ends up being the design everywhere.

Generics carry the tensor types

Beyond the loading mechanism, the library uses Go's addition of generics to support multiple Tensor data types, and the readme points at the NewTensor and NewEmptyTensor functions as the place to look. The effect is that the same code can handle a float32 tensor and a float64 tensor without a duplicated API, and the type parameter on the empty constructor is explicit in the example.

go
inputData := []float32{0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9}
inputShape := ort.NewShape(2, 5)
inputTensor, err := ort.NewTensor(inputShape, inputData)
defer inputTensor.Destroy()
// This hypothetical network maps a 2x5 input -> 2x3x4 output.
outputShape := ort.NewShape(2, 3, 4)
outputTensor, err := ort.NewEmptyTensor[float32](outputShape)
defer outputTensor.Destroy()

The shapes are built with a small helper, ort.NewShape, and the tensors are explicitly destroyed with a defer, which is the pattern the whole example follows. The module targets Go 1.19, which is when generics became available in the language, so the version floor is a direct consequence of the design decision rather than an accident.

Loading the runtime is a step the caller performs

Before initialising the library you have to point it at the shared library, and the example shows the recommended way, which is also the only stable one.

go
    // This line _may_ be optional; by default the library will try to load
    // "onnxruntime.dll" on Windows, and "onnxruntime.so" on any other system.
    // For stability, programs should always set this explicitly.
    ort.SetSharedLibraryPath("path/to/onnxruntime.so")

    err := ort.InitializeEnvironment()
    if err != nil {
        panic(err)
    }
    defer ort.DestroyEnvironment()

The comment is worth reading closely, because it names the default behaviour and then advises against relying on it. By default the library tries to load onnxruntime.dll on Windows and onnxruntime.so elsewhere, and for stability programs should always set the path explicitly. The environment is then initialised and destroyed with a defer, and every function in the API returns an error value, which the example omits for readability, with the note that the error will be non-nil in the case of failure. The requirements section says the same thing in prose: you need a version of Go with cgo support and a copy of the correct version of the onnxruntime shared library or DLL for your operating system and architecture.

The runtime version is pinned to the headers, and moving it is documented

The version coupling is the operational fact of this library. At the time of writing it uses version 1.29.0 of the onnxruntime C API headers, and it will probably only work with version 1.29.0 of the onnxruntime shared libraries as well. The readme then explains how to move to a different version, in three steps. You replace the onnxruntime_c_api.h and onnxruntime_ep_c_api.h files with the versions for the runtime you want. You replace the test_data shared library file, which is onnxruntime.dll on Windows and onnxruntime.so or onnxruntime.dylib elsewhere. And if you care about DirectML support, you verify that the entries in the DummyOrtDMLAPI struct in onnxruntime_wrapper.c match the order in which they appear in the OrtDmlApi struct from the dml_provider_factory.h header, with a comment in the source explaining more. The repository holds exactly those header files and the wrapper C file, which is the smallest possible footprint for a binding.

GPU providers are a separate problem you have to solve first

Several accelerated execution providers, including TensorRT, CUDA and CoreML, are tested and confirmed to work with onnxruntime_go, and the requirements section has more detail on each. For CUDA you need a version of the onnxruntime shared library with CUDA support, and a CUDA version supported by the underlying version of the onnxruntime library, with the example that version 1.23.2 of the onnxruntime library only supports CUDA versions 12.x. Other execution providers have their own separate requirements, and the readme is blunt that all of these requirements are too numerous to document there, asking you to ensure you are successfully able to use your execution provider of choice in a Python script before raising issues. That is a sensible division of labour, since the provider setup problem belongs to the runtime rather than to the binding, and it means the wrapper's own issue tracker is not the place for a CUDA configuration question. The same applies to the shared library files you may need for GPU support, such as execution_providers_cuda.dll and execution_providers_shared.dll or their Linux and macOS equivalents.

Where this binding is the wrong choice

Three limits are worth naming. The first is the version coupling, which the readme is upfront about, since headers and shared library must match and the shipped ones are for 1.29.0, so a team that needs a newer runtime has to maintain the C wrapper by hand. The second is that the API surface is a thin binding rather than an ergonomic layer, so the shape of your code is dictated by the ONNX Runtime C API and the example has to cast and defer a lot, which is a cost when the runtime itself is the thing you want to think about. The third is the split of responsibility for execution providers, where the wrapper will happily load a provider you have not configured and you get a failure at run time rather than a configuration error at start-up, and the readme's answer is to prove it in Python first. None of that makes the library bad, it makes it a binding, and a Go developer who has fought with ONNX Runtime bindings on Windows before will recognise exactly what problem this one solves.

Editorial conclusion

onnxruntime_go suits a Go service that has to run an ONNX model in process, and it suits a team that has hit the Windows problem with every other ONNX binding and wants one wrapper that covers all three platforms. It is the wrong tool if you need automatic execution provider selection, because the readme asks you to prove your provider works in a Python script before filing an issue, and it is the wrong tool if you want to move beyond version 1.29.0 of the runtime, since the headers and the shared library are pinned to each other. Before using it, read the version note and decide whether you will vendor a matching runtime, and confirm your CUDA version is one the runtime supports. The last push was on 2026-09-04 and the module targets Go 1.19.

Frequently asked questions

How do I install and initialise onnxruntime_go?

You need a version of Go with cgo support and the correct onnxruntime shared library or DLL for your platform. Before initialising, call ort.SetSharedLibraryPath to point at the shared library explicitly, then call ort.InitializeEnvironment and defer ort.DestroyEnvironment. The README advises always setting the path rather than relying on the default lookup.

Which version of the ONNX Runtime does onnxruntime_go work with?

The library uses version 1.29.0 of the onnxruntime C API headers and will probably only work with version 1.29.0 of the shared libraries as well. The README describes how to switch versions by replacing the two header files and the shared library, and by checking the DummyOrtDMLAPI struct order if you use DirectML.

Does onnxruntime_go support GPU execution providers?

Several accelerated execution providers including TensorRT, CUDA and CoreML are tested and confirmed to work. For CUDA you need an onnxruntime shared library with CUDA support and a CUDA version the underlying runtime supports, for example version 1.23.2 of onnxruntime only supports CUDA 12.x.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. yalue/onnxruntime_go on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/yalue-onnxruntime-go.svg)](https://hysenlabs.com/projects/yalue-onnxruntime-go)

Was this useful?