A Go terminal UI for displaying network adapters in real time

Practical Box

The layout algorithm in termui arranges the widgets passed to it in a 12x12 grid. The AddRows() function in line 33 accepts layout rows created with NewRow() as arguments; their arguments in turn are columns created with NewCol(). The latter function takes the width of the column as the first argument; in Listing 2, this means all 12 of a total of 12 grid squares. The second parameter is an offset as a spacer, which remains unused here at  .

The Align() function called in line 40 builds the widget grid internally; the following Render() puts the whole thing on the screen. Now the only thing left is to intercept any events that occur – for example, if the user increases or decreases the size of the terminal window. In this case, the raster engine kicks in thanks to the /sys/wnd/resize handler in line 45. The code first uses TermWidth() to determine the new terminal width and then calls the Align() function to distribute the widgets across the available space once again. The following call to Render() refreshes the display in a smooth, single action.

Now the list box with the displayed network interfaces is originally empty, because Items – a "field" (attribute) type in Go, as part of a struct (mixed data structure) – wasn't initialized in the beginning. Line 54 now takes care of this with the handler called once per second for the /timer/1s event. It calls the AsStrings() function from the ifconfig package previously shown in Listing 1 and assigns to the list box a pre-formatted slice of strings with the network adapters and their IPs. For the refreshed list to appear on the screen, the graphic manager's Render() function must be called again.

All's Well That Ends Well

To allow the user to exit the program gracefully without the terminal getting stuck in graphics mode and becoming unusable, the handlers /sys/kbd/C-c and /sys/kbd/q in lines 59 and 62 intercept the Ctrl+C and Q keystrokes and use StopLoop() to stop the event loop, which in turn lets the blocking Loop() function in line 66 return before main() finishes.

But wait, before that happens, the defer t.Close() command, which was called previously in line 18, quickly calls the graphic manager's cleanup function, which kindly cleans up everything to leave the terminal as it was when the program started.

You can compile the program by typing:

$ go build iftop.go

If the ifconfig package from Listing 1 is correctly installed, all code will be wrapped up in a binary that clocks in at about 3MB. It contains everything, so you can just copy it to another machine with a similar operating system and launch it there if so desired.

When you finally launch the program by typing ./iftop at the command line, you will see a tidy screen with the elements shown in Figure 2: the initially empty list box at the top, and the text field at the bottom. After one second, when the timer expires for the first time, a list of the network interfaces with their IP addresses appears in the list box.

If you want to test the dynamic behavior, you can now plug a network cable into your laptop (e.g., via USB), connect it to your router, and see a new entry appear in the list box almost immediately. Conversely, an existing entry should disappear as soon as a network interface goes away (e.g., when the laptop's wireless signal is turned off).

The termui project offers a generous helping of eye candy in the terminal, from progress bars to bar and pie charts (Figure 3), and termui is not the only terminal UI framework in Go: gocui, clui, wm, tui-go, and others also vie for the developer's favor. A blog post online [4] provides an overview of the advantages and disadvantages of the individual releases. It would be quite possible to build a sophisticated terminal application like lazygit [5] with one of these frameworks or a kind of Norton Commander (also known as Midnight Commander on Linux) for retro-looking file manipulation – state-of-the-art again 35 years after MS-DOS!

Figure 3: The termui project's Demo dashboard shows what's possible.


  1. "Using the Electron Framework to Weed Out Images" by Mike Schilli, Linux Pro Magazine, issue 216, November 218, p. 46.
  2. Listings for this article: ftp://ftp.linux-magazine.com/pub/listings/linux-magazine.com/218/
  3. termui on GitHub: https://github.com/gizak/termui
  4. "Text-Based User Interfaces" by Christoph Berger: https://appliedgo.net/tui/
  5. lazygit: https://github.com/jesseduffield/lazygit

The Author

Mike Schilli works as a software engineer in the San Francisco Bay area, California. Each month in his column, which has been running since 1997, he researches practical applications of various programming languages. If you email him at mailto:mschilli@perlmeister.com he will gladly answer any questions.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

  • Sweet Dreams

    Bathtub singer Mike Schilli builds a Go tool that manages song lyrics from YAML files and helps him learn them by heart, line by line.

  • Hard Disk Dashboard

    To keep an eye on the remaining disk space during storage-intensive operations, you can check out this speedometer/odometer written in Go.

  • Monitoring Station

    With a monitoring system implemented in Go, Mike Schilli displays the Docker containers that have been launched and closed on his system.

  • Ready to Rumble

    A Go program writes a downloaded ISO file to a bootable USB stick. To prevent it from accidentally overwriting the hard disk, Mike Schilli provides it with a user interface and security checks.

  • Progress by Installments

    Desktop applications, websites, and even command-line tools routinely display progress bars to keep impatient users patient during time-consuming actions. Mike Schilli shows several programming approaches for handwritten tools.

comments powered by Disqus

Direct Download

Read full article as PDF:

Price $2.95