Read an IFC model from Go. No CGO, no IfcOpenShell, no OCCT, no Python sidecar.
One go get, one static binary.
Documentation — guides, concepts and the compatibility policy.
API reference: ifc ·
step ·
model ·
geometry
Pick goifc when deployment cost dominates and bounding numbers are good enough. Pick IfcOpenShell when the geometry has to be exact — it is the better library, and it is also a C++ toolchain, a Python runtime, and a container several times the size of the service using it. goifc is the subset you need to parse the file, walk the semantics, and tessellate enough to get numbers.
The feature-by-feature comparison is on the docs site.
go get github.com/blox-eng/goifcpackage main
import (
"bytes"
"fmt"
"os"
ifc "github.com/blox-eng/goifc"
"github.com/blox-eng/goifc/step"
)
func main() {
src, err := os.ReadFile("model.ifc")
if err != nil {
panic(err)
}
f, err := step.ParseBytes(src)
if err != nil {
panic(err)
}
a, err := ifc.Assemble(f)
if err != nil {
panic(err)
}
for i := range a.Result.Elements {
e := a.Result.Elements[i]
if e.Qto.Volume == nil {
continue // no volume for this element — see the next section
}
fmt.Printf("%s\t%.3f m³\t(%s)\n", e.Name, *e.Qto.Volume, e.QuantitySource)
}
var glb bytes.Buffer
a.Scene.WriteGLB(&glb) // proxy geometry for a viewer
}The package is named ifc, not goifc — alias the import as above.
Assemble gives you a flat list. ifc.BuildImport(f) is the other entry point:
the same elements as a parents-first tree with spatial containers, per-type
material layers and pre-baked floor plans — the call Blox actually ships. See
getting started.
Every element reports where its quantities came from — "qto" for an authored
IfcElementQuantity (net, from the modeller), "geometry" for one derived from
the proxy mesh (gross — a wall over-reports by its windows and doors), and
"none" where neither exists, never a fabricated 0.0.
That tag is the most important thing to understand before trusting a total: quantities and provenance.
The meshes are proxy geometry for visualization, not a B-rep substitute — do not clash-detect with them. The rest of the edges, stated plainly, are in limitations.
- The pipeline —
step,modelandgeometry, each usable on its own. - Sections and floor plans — cut the model with any plane, get closed 2D rings back.
- Storey plans — what
BuildImportpre-bakes perIfcBuildingStorey. - Local and world frames — meshes are local, bounding boxes are world, and mixing them is wrong without erroring.
- The
steppackage — parses any STEP file, IFC or not.
The API is unstable pre-1.0 — expect breaking changes on minor versions, and pin
a version. Used in production by Blox, whose import pipeline is the only consumer
this has been hardened against, so the well-trodden path is BuildImport on
architectural IFC exports; off that path, expect to find edges.
Both of those have a fuller answer, including the serialization contracts that hold steady even when the Go API does not, in the compatibility policy.
Issues and PRs welcome — the open issues are the roadmap. See CONTRIBUTING.md. Commits follow Conventional Commits; CI enforces it.
MIT — see LICENSE.