gv(3go)

πŸ“¦
version 14.1.4 Β· 4 versions
, in fedora 44

πŸ’… 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