gv(3go)
π gv_go β graph manipulation in go π
okay bestie, sit down, hydrate, because this is the manual page for gv β section 3go, yes the go one β and it is literally your all-access backstage pass to graph manipulation in go. no cap. π
πΈ NAME πΈ
gv_go β graph manipulation in go π¦
β¨ SYNOPSIS β¨
USAGE
USAGE
fr fr, that's the entire synopsis section. the actual menu of everything you can call lives down in COMMANDS, and it is long. pace yourself. π
π INTRODUCTION π
gv_go is a dynamically loaded extension for go that gives you access to the graph facilities of graphviz. that's the vibe. that's the whole point. π
π COMMANDS π
New graphs π±
New empty graph
four ways to start from a totally blank canvas, pick your fighter:
graph_handle gv.graph (name);
graph_handle gv.digraph (name);
graph_handle gv.strictgraph (name);
graph_handle gv.strictdigraph (name);
New graph from a dot-syntax string or file
build one straight out of a dot-syntax string, a file, or even a channel β whatever's closest:
graph_handle gv.readstring (string);
graph_handle gv.read (string filename);
graph_handle gv.read (channel);
Add new subgraph to existing graph
already got a graph and want a subgraph in it? say less:
graph_handle gv.graph (graph_handle, name);
New nodes π«Ά
Add new node to existing graph
one node, dropped into a graph you already have:
node_handle gv.node (graph_handle, name);
New edges π
Add a new edge between existing nodes
both ends already exist, so it's a simple connect:
edge_handle gv.edge (tail_node_handle, head_node_handle);
Add a new edge between an existing tail node, and a named head node which will be induced in the graph if it doesn't already exist
tail's already here, and the head gets induced into the graph if it isn't already there:
edge_handle gv.edge (tail_node_handle, head_name);
Add a new edge between an existing head node, and a named tail node which will be induced in the graph if it doesn't already exist
same energy, other direction β head exists, named tail gets induced if it's missing:
edge_handle gv.edge (tail_name, head_node_handle);
Add a new edge between named tail and head nodes which will be induced in the graph if they don't already exist
both ends named, both ends induced if they're not already there. it's giving self-sufficient:
edge_handle gv.edge (graph_handle, tail_name, head_name);
Setting attribute values βοΈ
Set value of named attribute of graph/node/edge β creating attribute if necessary
name it and it shall be set β and if that attribute doesn't exist yet, it gets created on the spot:
string gv.setv (graph_handle, attr_name, attr_value);
string gv.setv (node_handle, attr_name, attr_value);
string gv.setv (edge_handle, attr_name, attr_value);
Set value of existing attribute of graph/node/edge (using attribute handle)
this one goes through the attribute handle instead, for an attribute that already exists:
string gv.setv (graph_handle, attr_handle, attr_value);
string gv.setv (node_handle, attr_handle, attr_value);
string gv.setv (edge_handle, attr_handle, attr_value);
Getting attribute values π
Get value of named attribute of graph/node/edge
just ask for it by name:
string gv.getv (graph_handle, attr_name);
string gv.getv (node_handle, attr_name);
string gv.getv (edge_handle, attr_name);
Get value of attribute of graph/node/edge (using attribute handle)
or ask by handle, your call:
string gv.getv (graph_handle, attr_handle);
string gv.getv (node_handle, attr_handle);
string gv.getv (edge_handle, attr_handle);
Obtain names from handles
handles in, names out. so demure:
string gv.nameof (graph_handle);
string gv.nameof (node_handle);
string gv.nameof (attr_handle);
Find handles from names
names in, handles out β including subgraphs, nodes, edges and attributes:
graph_handle gv.findsubg (graph_handle, name);
node_handle gv.findnode (graph_handle, name);
edge_handle gv.findedge (tail_node_handle, head_node_handle);
attribute_handle gv.findattr (graph_handle, name);
attribute_handle gv.findattr (node_handle, name);
attribute_handle gv.findattr (edge_handle, name);
Misc graph navigators returning handles
a lil grab-bag of navigators that hand you back handles β head, tail, the graph something belongs to, and the root:
node_handle gv.headof (edge_handle);
node_handle gv.tailof (edge_handle);
graph_handle gv.graphof (graph_handle);
graph_handle gv.graphof (edge_handle);
graph_handle gv.graphof (node_handle);
graph_handle gv.rootof (graph_handle);
Obtain handles of proto node/edge for setting default attribute values
the prototype node and prototype edge β this is how you set default attribute values:
node_handle gv.protonode (graph_handle);
edge_handle gv.protoedge (graph_handle);
Iterators π
Iteration termination tests
your ok checks, one per handle type β are we done yet or nah:
bool gv.ok (graph_handle);
bool gv.ok (node_handle);
bool gv.ok (edge_handle);
bool gv.ok (attr_handle);
Iterate over subgraphs of a graph
walk the subgraphs, one by one:
graph_handle gv.firstsubg (graph_handle);
graph_handle gv.nextsubg (graph_handle, subgraph_handle);
Iterate over supergraphs of a graph (obscure and rarely useful)
going up instead of down. the original literally calls this obscure and rarely useful β so, yeah, iykyk:
graph_handle gv.firstsupg (graph_handle);
graph_handle gv.nextsupg (graph_handle, subgraph_handle);
Iterate over edges of a graph
every edge in the graph, no filter:
edge_handle gv.firstedge (graph_handle);
edge_handle gv.nextedge (graph_handle, edge_handle);
Iterate over outedges of a graph
just the outgoing ones:
edge_handle gv.firstout (graph_handle);
edge_handle gv.nextout (graph_handle, edge_handle);
Iterate over edges of a node
all the edges touching a node:
edge_handle gv.firstedge (node_handle);
edge_handle gv.nextedge (node_handle, edge_handle);
Iterate over out-edges of a node
the outgoing ones from a node:
edge_handle gv.firstout (node_handle);
edge_handle gv.nextout (node_handle, edge_handle);
Iterate over head nodes reachable from out-edges of a node
follow the out-edges, collect the heads:
node_handle gv.firsthead (node_handle);
node_handle gv.nexthead (node_handle, head_node_handle);
Iterate over in-edges of a graph
the incoming ones, graph edition:
edge_handle gv.firstin (graph_handle);
edge_handle gv.nextin (node_handle, edge_handle);
Iterate over in-edges of a node
the incoming ones, node edition:
edge_handle gv.firstin (node_handle);
edge_handle gv.nextin (graph_handle, edge_handle);
Iterate over tail nodes reachable from in-edges of a node
follow the in-edges, collect the tails:
node_handle gv.firsttail (node_handle);
node_handle gv.nexttail (node_handle, tail_node_handle);
Iterate over nodes of a graph
every node in the graph:
node_handle gv.firstnode (graph_handle);
node_handle gv.nextnode (graph_handle, node_handle);
Iterate over nodes of an edge
just the nodes attached to one edge:
node_handle gv.firstnode (edge_handle);
node_handle gv.nextnode (edge_handle, node_handle);
Iterate over attributes of a graph
all the graph's attributes:
attribute_handle gv.firstattr (graph_handle);
attribute_handle gv.nextattr (graph_handle, attr_handle);
Iterate over attributes of an edge
all an edge's attributes:
attribute_handle gv.firstattr (edge_handle);
attribute_handle gv.nextattr (edge_handle, attr_handle);
Iterate over attributes of a node
all a node's attributes:
attribute_handle gv.firstattr (node_handle);
attribute_handle gv.nextattr (node_handle, attr_handle);
Remove graph objects
bye bye graph, bye bye node, bye bye edge β and you get a bool back:
bool gv.rm (graph_handle);
bool gv.rm (node_handle);
bool gv.rm (edge_handle);
Layout π
Annotate a graph with layout attributes and values using a specific layout engine
hand it a graph and an engine name, and it'll annotate the graph with layout attributes and values:
bool gv.layout (graph_handle, string engine);
Render π¨
Render a layout into attributes of the graph
renders the layout straight into the graph's own attributes:
bool gv.render (graph_handle);
Render a layout to stdout
renders it right out to stdout, in the format you name:
bool gv.render (graph_handle, string format);
Render to an open file
you bring the already-open file, it brings the render:
bool gv.render (graph_handle, string format, channel fout);
Render a layout to an unopened file by name
not open yet? just give it the filename:
bool gv.render (graph_handle, string format, string filename);
Render to a string result
your render, handed back as a string:
string gv.renderresult (graph_handle ing, string format);
gv.renderresult (graph_handle, string format, string outdata);
Render to an open channel
render out to a named channel:
bool gv.renderchannel (graph_handle, string format, string channelname);
Render a layout to a malloc'ed string, to be free'd by the caller
ok bestie, listen closely. this one is deprecated β and the reason given is too easy to leak memory. you have been warned. π«£
it's still needed for "eval [gv::renderdata $G tk]" though, so it's not going anywhere.
string gv.renderdata (graph_handle, string format);
Writing graph back to file
write the graph back out β to a filename, or to a channel:
bool gv.write (graph_handle, string filename);
bool gv.write (graph_handle, channel);
Graph transformation tools
one transformation tool, doing its thing:
bool gv.tred (graph_handle);
π KEYWORDS π
graph, dot, neato, fdp, circo, twopi, go.
that's the whole page, bestie. go forth and graph. π
sign-off time: this was gv(3go), dated 21 March 2026. mwah. π
π¦ where this page comes from
- fedora 44: graphviz-go 14.1.4-2.fc44 Β· epl-1.0 AND cpl-1.0 AND bsd-3-clause AND mit AND gpl-3.0-or-later WITH bison-exception-2.2 AND apache-1.1 AND lgpl-2.0-or-later WITH libtool-exception AND smlnj AND hpnd-uc
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms