<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Frédéric G. MARAND</title>
    <description>The latest articles on DEV Community by Frédéric G. MARAND (@fgm).</description>
    <link>https://dev.to/fgm</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F81110%2Fb73d0c89-d368-4dbb-9e8f-24c0cb2f8650.jpg</url>
      <title>DEV Community: Frédéric G. MARAND</title>
      <link>https://dev.to/fgm</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fgm"/>
    <language>en</language>
    <item>
      <title>CLI commands with google/subcommands</title>
      <dc:creator>Frédéric G. MARAND</dc:creator>
      <pubDate>Sun, 06 Mar 2022 14:04:50 +0000</pubDate>
      <link>https://dev.to/fgm/cli-commands-with-googlesubcommands-272</link>
      <guid>https://dev.to/fgm/cli-commands-with-googlesubcommands-272</guid>
      <description>&lt;p&gt;How to create CLI programs with multiple commands, flags and subcommands, and do it fast and simply?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/google/subcommands"&gt;google/subcommands&lt;/a&gt; makes it a breeze. Let us see how.&lt;/p&gt;

&lt;p&gt;(original location: &lt;a href="https://osinet.fr/go/en/articles/cli-google-subcommands/"&gt;https://osinet.fr/go/en/articles/cli-google-subcommands/&lt;/a&gt;)&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem scope
&lt;/h2&gt;

&lt;p&gt;First, let us agree on the topics covered here.&lt;/p&gt;

&lt;p&gt;Any Go program is - at least in concept - run from a command line, whether it be an actual shell command line or some automation tool, using the &lt;code&gt;execve(2)&lt;/code&gt; system call.&lt;/p&gt;

&lt;p&gt;To define the specific words used in this tutorial, let us consider a typical *NIX command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker -D container inspect -s some_container
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;docker&lt;/code&gt; is the &lt;em&gt;program&lt;/em&gt;, or &lt;em&gt;application&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-D&lt;/code&gt; is a &lt;em&gt;global flag&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;container&lt;/code&gt; is a &lt;em&gt;root&lt;/em&gt; or &lt;em&gt;top-level command&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;inspect&lt;/code&gt; is a &lt;em&gt;subcommand&lt;/em&gt; of the &lt;code&gt;container&lt;/code&gt; command; more generally, it is
also a &lt;em&gt;command&lt;/em&gt; too, but a level 2 one.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-s&lt;/code&gt; is a &lt;em&gt;local flag&lt;/em&gt; for the &lt;code&gt;container&lt;/code&gt; subcommand&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;some_container&lt;/code&gt; is an &lt;em&gt;argument&lt;/em&gt; to the &lt;code&gt;inspect&lt;/code&gt; subcommand&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In order to interpret that kind of structure, Go code needs to work from a single global variable, &lt;code&gt;os.Args&lt;/code&gt;, the first element of which contains the absolute path to the program being run, while the other elements are copies of the arguments passed when starting the program.&lt;/p&gt;

&lt;p&gt;To avoid having to redo that kind of very formalized work in every other program, various libraries/modules exist, with the most popular being:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Module&lt;/th&gt;
&lt;th&gt;☆&lt;/th&gt;
&lt;th&gt;⑂&lt;/th&gt;
&lt;th&gt;Direct deps.&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/spf13/cobra"&gt;spf13/cobra&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;25400&lt;/td&gt;
&lt;td&gt;2200&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/urfave/cli"&gt;urfave/cli&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;17400&lt;/td&gt;
&lt;td&gt;1500&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/alecthomas/kingpin"&gt;alecthomas/kingpin&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;3200&lt;/td&gt;
&lt;td&gt;240&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/google/subcommands"&gt;google/subcommands&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;594&lt;/td&gt;
&lt;td&gt;51&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The first three libraries are by far the best known and the richest in terms of functionality, but that comes with multiple dependencies, sometimes quite a lot (3136 for Cobra 1.3). While this is easily justified in humongous projects like &lt;a href="https://github.com/moby/moby/blob/master/cli/cobra.go"&gt;Docker&lt;/a&gt; or &lt;a href="https://github.com/kubernetes/kubernetes/blob/master/go.mod#L74"&gt;Kubernetes&lt;/a&gt;, such a complexity is not as acceptable for typical projects like microservices or &lt;a href="https://pragprog.com/titles/bhcldev/small-sharp-software-tools/"&gt;small, sharp tools&lt;/a&gt; for the CLI.&lt;/p&gt;

&lt;p&gt;This is where google/subcommands shines, providing support for most commonly needed command creation tools without requiring any dependency, in a single module around 500 lines only, very easy to use in any application and with a negligible size cost even for the tiniest projects. This tutorial is about how to use it from the simplest to the most advanced scenario.&lt;/p&gt;

&lt;p&gt;All along the successive refinement levels in this demo, we are going to be adding features to the same example code, which you can find on &lt;a href="https://github.com/fgm/subcommands_demo"&gt;https://github.com/fgm/subcommands_demo&lt;/a&gt;, with every branch matching the eponymous section in this tutorial, containing 100% of the source code for the level being discussed, as well as a &lt;code&gt;Makefile&lt;/code&gt; configured to demonstrate just the specifics of that level.&lt;/p&gt;

&lt;p&gt;This tutorial covers 100% of the functionality in google/subcommands, hence its overall length ; you will however be able to create a complete application as early as level 1.2 : later levels describe features meant for projects ever more complex and demanding.&lt;/p&gt;

&lt;h2&gt;
  
  
  Level 1 : simple commands
&lt;/h2&gt;

&lt;p&gt;We shall start by creating a couple of &lt;em&gt;top-level commands&lt;/em&gt;, laying out our code in two directories: the project root and &lt;code&gt;cmd/&lt;/code&gt;, with the following main files :&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;Contents&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;go.mod&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;the module description file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;main.go&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;the program entry point&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Makefile&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;the build tasks file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cmd/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;the commands directory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cmd/root.go&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;the code running the commands&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;A word of advice:&lt;/strong&gt; in each branch, the &lt;code&gt;make&lt;/code&gt; command runs a different default sequence of tasks, meant to illustrate the changes brought by the current branch: you might wish to use that command on your own machine any time you change branch, to see the impact the code changes actually have.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.1 Enabling builtin commands
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;The code for that level is available on &lt;a href="https://github.com/fgm/subcommands_demo/tree/level1.1-builtin_commands"&gt;level1.1-builtin_commands&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;At this step, the code is just made up of two files: the application entry point in &lt;code&gt;main.go&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;sts&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Runs the designated command on the CLI&lt;/span&gt;
    &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sts&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;       &lt;span class="c"&gt;// Returns the command result to the program caller&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;…and the code triggering execution of the commands, in &lt;code&gt;cmd/root.go&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Execute sets up the command chain and runs it.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitStatus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CommandsCommand&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="c"&gt;// Implement "commands"&lt;/span&gt;
        &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FlagsCommand&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;    &lt;span class="c"&gt;// Implement "flags"&lt;/span&gt;
        &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HelpCommand&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;     &lt;span class="c"&gt;// Implement "help"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code registers the three optional commands provided by &lt;code&gt;subcommands&lt;/code&gt; proper, which enables listing existing commands and flags, as well as providing CLI help, then it parses global flags and ends up passing control to the actual command selected by the CLI arguments, and returning its result.&lt;/p&gt;

&lt;p&gt;Our application scaffold is now ready and supports commands &lt;code&gt;commands&lt;/code&gt;, &lt;code&gt;flags&lt;/code&gt;, et &lt;code&gt;help&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ go run . help
Usage: subcommands_demo &amp;lt;flags&amp;gt; &amp;lt;subcommand&amp;gt; &amp;lt;subcommand args&amp;gt;

      Subcommands:
      commands         list all command names
      flags            describe all known top-level flags
      help             describe subcommands and their syntax
$
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now create our first custom commands.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.2 Writing custom commands
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;The code for that level is available on [level1.2-custom_commands](&lt;a href="https://github.com/fgm/subcommands_demo/tree/level1.2-custom_commands"&gt;https://github.com/fgm/subcommands_demo/tree/level1.2-custom_commands&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The best practices with custom commands is to have one file per command. This eases code navigation and comparison of commands between each other to ensure consistency of practices. We shall therefore add two files, one for each of the two top-level commands we are adding:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;Contents&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cmd/top1.go&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;the &lt;code&gt;top1&lt;/code&gt; command, showing a fixed message&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cmd/top2.go&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;the &lt;code&gt;top2&lt;/code&gt; command, showing a message based on the CLI arguments&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For google/subcommands, a command is provided by a variable, the type of which  implements the &lt;a href="https://pkg.go.dev/github.com/google/subcommands#Command"&gt;subcommands.Command&lt;/a&gt; interface. Our two files will therefore be very similar to each other, based on the structure in file &lt;code&gt;cmd/top2.go&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;top2&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;top2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"top2"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;top2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Synopsis&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"top2 is an example top-level custom command with arguments"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;top2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Usage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s arg1 arg2 ..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;top2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SetFlags&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FlagSet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;top2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FlagSet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitStatus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Notice how the command line arguments are taken on the flag set, not on the variadic.&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"In %s %v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Args&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitSuccess&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For now, &lt;code&gt;top2&lt;/code&gt; just implements &lt;code&gt;subcommands.Command&lt;/code&gt; and does nothing more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;top2.Name()&lt;/code&gt; returns the name of the command&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;top2.Synopsis&lt;/code&gt; returns a single-line summary of the command description&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;top2.Usage()&lt;/code&gt; returns an example of how to use the command, and may spread
over multiple text lines. The returned value is used by the &lt;code&gt;help&lt;/code&gt; builtin command.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;top2.SetFlags()&lt;/code&gt; defines the &lt;em&gt;local flags&lt;/em&gt; on the command: none for now.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;top2.Execute()&lt;/code&gt; is the actual command implementation.

&lt;ul&gt;
&lt;li&gt;the &lt;code&gt;context.Context&lt;/code&gt; arguments supports passing context values, and using
timeout and cancellation capabilities, which will be available to subcommands,
just like in a &lt;code&gt;http.Handler&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;flag.FlagSet&lt;/code&gt; holds the &lt;em&gt;local&lt;/em&gt; flag definitions, actual values, and
the command arguments.&lt;/li&gt;
&lt;li&gt;when running that method, the name of the program, the global flags, as
well as the command local flags have been parsed, and &lt;code&gt;fs.Args()&lt;/code&gt; holds
the command arguments with no extras.&lt;/li&gt;
&lt;li&gt;if we run the program as &lt;code&gt;demo top2 hello world&lt;/code&gt;, &lt;code&gt;fs.Args()&lt;/code&gt; will contain
&lt;code&gt;[]string{"hello", "world"}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;the third parameter is not used in this scenario.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that we have created our &lt;em&gt;two&lt;/em&gt; commands, we can register all &lt;em&gt;three&lt;/em&gt; of them with google/subcommands: &lt;code&gt;top1&lt;/code&gt;, &lt;code&gt;top2&lt;/code&gt;, and a &lt;code&gt;1&lt;/code&gt; &lt;em&gt;alias&lt;/em&gt; for &lt;code&gt;top1&lt;/code&gt;. We can perform this by adding instances of the commands to the &lt;code&gt;subcommands.Register&lt;/code&gt;&lt;br&gt;
call besides &lt;code&gt;commands&lt;/code&gt;, &lt;code&gt;flags&lt;/code&gt; and &lt;code&gt;help&lt;/code&gt;, in &lt;code&gt;root.go&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitStatus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CommandsCommand&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;   &lt;span class="c"&gt;// Implement "commands"&lt;/span&gt;
        &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FlagsCommand&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;      &lt;span class="c"&gt;// Implement "flags"&lt;/span&gt;
        &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HelpCommand&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;       &lt;span class="c"&gt;// Implement "help"&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;top1&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;                         &lt;span class="c"&gt;// Our first top-level command, without args&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;top2&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;                         &lt;span class="c"&gt;// Our second top-level command, with args&lt;/span&gt;
        &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Alias&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;top1&lt;/span&gt;&lt;span class="p"&gt;{}),&lt;/span&gt; &lt;span class="c"&gt;// An alias for our top1 command&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once this is done, our program supports these two commands, as well as a &lt;code&gt;"1"&lt;/code&gt; alias for command &lt;code&gt;top1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Many applications will not anything more when it comes to commands handling.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ go run . commands
commands
flags
help
top1
top2
1
$ go run . top2 hello world
In top2 [hello world]
$
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1.3 Passing non-CLI arguments to commands
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;The code for that level is available on &lt;a href="https://github.com/fgm/subcommands_demo/tree/level1.3-non_cli_arguments"&gt;level1.3-non_cli_arguments&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the previous example, the &lt;code&gt;top2&lt;/code&gt; command takes arguments passed from the CLI.&lt;/p&gt;

&lt;p&gt;Command code may however need extra arguments passed to all commands regardless of the CLI arguments, like a logger, an authentication service, etc.&lt;/p&gt;

&lt;p&gt;That is where the variadic argument to &lt;code&gt;subcommands.Execute&lt;/code&gt; enters into play, taking any number of values of any type, to be received by the &lt;code&gt;Command.Execute()&lt;/code&gt; implementations on their variadic parameter. We shall be using it to pass two values :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitStatus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;/* ...snip... */&lt;/span&gt;
    &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"meaning"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here they are handled in &lt;code&gt;top1&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;top1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FlagSet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitStatus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// The variadic arguments are the ones passed to subcommands.Execute().&lt;/span&gt;
    &lt;span class="c"&gt;// Unlike the CLI args, they are always a []interface{}.&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"In %s.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Non-CLI args: %#v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitSuccess&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ go run . top1
In top1.
Non-CLI args: []interface {}{"meaning", 42}
$
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The salient issue here is how, as a command author, you need to coordinates the types and order of values passed in that variadic arguments, since they are passed as &lt;code&gt;interface{}&lt;/code&gt; (aka &lt;code&gt;any&lt;/code&gt; starting with Go 1.18), which will usually mean a type assertion in the &lt;code&gt;Execute&lt;/code&gt; method to get a ready-to-use value.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.4 Grouping commands
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;The code for that level is available on &lt;a href="https://github.com/fgm/subcommands_demo/tree/level1.4-command_groups"&gt;level1.4-command_groups&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When a project starts to grow and get ever more commands, grouping them by purpose may  become useful. This is what the second, &lt;code&gt;string&lt;/code&gt;, parameter of &lt;code&gt;subcommands.Register&lt;/code&gt; is for. We use it in &lt;code&gt;root.go&lt;/code&gt;, to associate each registered command to a given &lt;a href="https://pkg.go.dev/github.com/google/subcommands#CommandGroup"&gt;subcommands.Group&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this example, we shall separate commands provided by google/subcommands, in the &lt;code&gt;help&lt;/code&gt; group, from our custom commands, in the &lt;code&gt;top&lt;/code&gt; group.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitStatus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
        &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;
    &lt;span class="p"&gt;}{&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"help"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CommandsCommand&lt;/span&gt;&lt;span class="p"&gt;()},&lt;/span&gt;  &lt;span class="c"&gt;// Implement "commands"&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"help"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FlagsCommand&lt;/span&gt;&lt;span class="p"&gt;()},&lt;/span&gt;     &lt;span class="c"&gt;// Implement "flags"&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"help"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HelpCommand&lt;/span&gt;&lt;span class="p"&gt;()},&lt;/span&gt;      &lt;span class="c"&gt;// Implement "help"&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"top"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;top1&lt;/span&gt;&lt;span class="p"&gt;{}},&lt;/span&gt;                         &lt;span class="c"&gt;// Our first top-level command, without args&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"top"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;top2&lt;/span&gt;&lt;span class="p"&gt;{}},&lt;/span&gt;                         &lt;span class="c"&gt;// Our second top-level command, with args&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"top"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Alias&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;top1&lt;/span&gt;&lt;span class="p"&gt;{})},&lt;/span&gt; &lt;span class="c"&gt;// An alias for our top1 command&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;help&lt;/code&gt; command now displays our commands in these two different groups :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ go run . help
Usage: subcommands_demo &amp;lt;flags&amp;gt; &amp;lt;subcommand&amp;gt; &amp;lt;subcommand args&amp;gt;

Subcommands for help:
        commands         list all command names
        flags            describe all known top-level flags
        help             describe subcommands and their syntax

Subcommands for top:
        top1, 1          top1 is an example top-level custom command without arguments
        top2             top2 is an example top-level custom command with arguments
$
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1.5 Adding global or local flags
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;The code for that level is available on &lt;a href="https://github.com/fgm/subcommands_demo/tree/level1.5-flags"&gt;level1.5-flags&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Many programs use a few &lt;em&gt;global&lt;/em&gt; flags, like a boolean &lt;code&gt;-v&lt;/code&gt; used to increase the verbosity of all commands ; and some also use &lt;em&gt;local&lt;/em&gt; flags allowing individual commands to adjust their own behaviour.&lt;/p&gt;

&lt;p&gt;Let us start with the typical global boolean &lt;code&gt;-v&lt;/code&gt; flag, and implementing it in our two existing commands. We can do this with the stdlib package &lt;code&gt;flag&lt;/code&gt;, with which google/subcommands has a hidden integration.&lt;/p&gt;

&lt;p&gt;To make sure that flag will be available to all commands and subcommands, we add its value to the context. Following best Go practices, we define an &lt;a href="https://medium.com/@matryer/context-keys-in-go-5312346a868d"&gt;unexported specific context key type&lt;/a&gt;, and a variable of that type, in our &lt;code&gt;root.go&lt;/code&gt; file :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;verboseKey&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;VerboseKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;verboseKey&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, in our &lt;code&gt;Execute&lt;/code&gt; function, we define that the flag, parse the program CLI arguments, and add the parsed flag value to the context using that key :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitStatus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;/* ...snip... */&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;verbose&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Be more verbose"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;VerboseKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Commands can now fetch the flag value from the context, as in this example taken from &lt;code&gt;top1.go&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;top1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FlagSet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitStatus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VerboseKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"In %s.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since we defined the flag type as boolean, and the key is of a unique unexported type, there can be no collision on the context value even in a large program, which means the type assertion will never fail.&lt;/p&gt;

&lt;p&gt;For that &lt;em&gt;global&lt;/em&gt; flag, we did not knowingly use google/subcommands at all, and it is correctly recognized by builtin command &lt;code&gt;flags&lt;/code&gt;, but does not appear in the builtin help provided by the &lt;code&gt;help&lt;/code&gt; command :&lt;/p&gt;

&lt;p&gt;&lt;a id="level15-help"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ go run . help
Usage: subcommands_demo &amp;lt;flags&amp;gt; &amp;lt;subcommand&amp;gt; &amp;lt;subcommand args&amp;gt;

Subcommands for help:
        commands         list all command names
        flags            describe all known top-level flags
        help             describe subcommands and their syntax

Subcommands for top:
        top1, 1          top1 is an example top-level custom command without arguments
        top2             top2 is an example top-level custom command with arguments


Use "subcommands_demo flags" for a list of top-level flags
$ go run . flags
  -v    Be more verbose
$
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let us define a &lt;em&gt;local&lt;/em&gt; flag on command &lt;code&gt;top1&lt;/code&gt;. Since that flag will be specific to the command, it will be listed after the command name in the command line arguments, preventing a simple use of the &lt;code&gt;flag&lt;/code&gt; package procedural API like we just did for global flags.&lt;/p&gt;

&lt;p&gt;Local flags are defined on each command by implementing their &lt;code&gt;SetFlags&lt;/code&gt; method to store the parsed flag value on a command instance field.&lt;/p&gt;

&lt;p&gt;To that effect, we shall add a field to the &lt;code&gt;top1&lt;/code&gt; type implementing our command, in the &lt;code&gt;top1.go&lt;/code&gt; file, to store the parsed flag value, which will be a &lt;code&gt;string&lt;/code&gt; field in this example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;top1&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We then implement the &lt;code&gt;top1.SetFlags&lt;/code&gt; method to define that flag and store its parsed value on the command instance :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;top1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SetFlags&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FlagSet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StringVar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"prefix"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Add a prefix to the result"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;top1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FlagSet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitStatus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VerboseKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"In %s.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;": "&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitSuccess&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;help&lt;/code&gt; command is now aware of our local flag :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ go run . help top1
top1  -prefix string
        Add a prefix to the result
$
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When &lt;code&gt;subcommands.Execute&lt;/code&gt; prepares to invoke our &lt;code&gt;top1&lt;/code&gt; command instance, it starts by creating a new empty &lt;code&gt;flag.FlagSet&lt;/code&gt; from the remaining arguments on the current one, which it passed to the &lt;code&gt;SetFlags&lt;/code&gt; method on the command instance. That defines flags pointing to fields on said command instance, so that parsing will field values on it. These fields are thereafter available on the instance&lt;br&gt;
when eventually running the &lt;code&gt;top1.Execute&lt;/code&gt; method, allowing the method code to access their values as plain typed fields on the method receiver, as demonstrated on line 40 for &lt;code&gt;cmd.prefix&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ go run . top1 -prefix today
today: hello
$
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another possible mechanism enabled by this process would be for the method implementation to just drop the flag, not pointing it anywhere, then extract the value from the &lt;code&gt;fs *FlagSet&lt;/code&gt; argument in &lt;code&gt;top1.Execute&lt;/code&gt;, as done below, but that leads to code which is much less readable than the recommended method above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;top1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SetFlags&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FlagSet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"prefix"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Add a prefix to the result"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;top1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FlagSet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitStatus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lookup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"prefix"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stringer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;": "&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitSuccess&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1.6 Labeling flags as important
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;The code for that level is available on &lt;a href="https://github.com/fgm/subcommands_demo/tree/level1.6-important_flags"&gt;level1.6-important_flags&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Some flags may be frequently used, making them worthy of being reported in the &lt;code&gt;help&lt;/code&gt; command output.&lt;/p&gt;

&lt;p&gt;Let us describe our &lt;code&gt;-v&lt;/code&gt; global flag as an important one, and our code also include an unimportant boolean &lt;code&gt;-debug&lt;/code&gt; flag. We can inform google/subcommands of that difference when declaring the flags in our &lt;code&gt;root.go&lt;/code&gt; file :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitStatus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;/* ...snip... */&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;debug&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"debug"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Show debug information"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;verbose&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Be more verbose"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ImportantFlag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"v"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without the &lt;code&gt;subcommands.ImportantFlag("v")&lt;/code&gt; statement, the &lt;code&gt;help&lt;/code&gt; command does not document any top-level flag, as we saw in the &lt;a href="//./#level15-help"&gt;level1.5 example&lt;/a&gt; above, where the help command mentions that top-level flags exist, but does not list any.&lt;/p&gt;

&lt;p&gt;When we add this statement, however, the now &lt;em&gt;important&lt;/em&gt; &lt;code&gt;-v&lt;/code&gt; flag is included in the &lt;code&gt;help&lt;/code&gt; output, while the ordinary &lt;code&gt;-debug&lt;/code&gt; flag remains unlisted.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ go run . help
Usage: subcommands_demo &amp;lt;flags&amp;gt; &amp;lt;subcommand&amp;gt; &amp;lt;subcommand args&amp;gt;

Subcommands for help:
        commands         list all command names
        flags            describe all known top-level flags
        help             describe subcommands and their syntax

Subcommands for top:
        top1, 1          top1 is an example top-level custom command without arguments
        top2             top2 is an example top-level custom command with arguments


Top-level flags (use "subcommands_demo flags" for a full list):
  -v=false: Be more verbose
$
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both flags are listed indiscriminately by command &lt;code&gt;flags&lt;/code&gt;, since its express purpose is to document flags  :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ go run . flags
  -debug
        Show debug information
  -v    Be more verbose
$
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With all the features we have now examined, google/subcommands covers the needs of most small applications. Later levels will mostly be relevant for more complex projects, especially those which require unit testing coverage for commands themselves, instead of just requiring it for the service-level code the commands call upon, which is a more frequent requirement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Level 2 : Reusing command code
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;The code for that level is available on &lt;a href="https://github.com/fgm/subcommands_demo/tree/level2.1-reuse"&gt;level2.1-reuse&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Until this point we have been using one defined type per command, not counting aliases, as suggested by the minimal  &lt;a href="https://pkg.go.dev/github.com/google/subcommands#section-readme"&gt;documentation&lt;/a&gt; provided by the google/subcommands repository. Doing so allows storing command-specific properties of commands, like local flags, on the instance of that type which is registered with google/subcommands.&lt;/p&gt;

&lt;p&gt;In practice, however, many commands either do not use any flag, or share whichever flags they use ; and repeating identical code for each of these types is not entirely satisfying. But there is no actual need to use different types for different commands, especially if they share the same structure.&lt;/p&gt;

&lt;p&gt;The main reason for different types is the &lt;code&gt;Command.Execute&lt;/code&gt; method, which has to differ for each command since commands implement different features. Sharing types means using different methods for each command instance.&lt;/p&gt;

&lt;p&gt;Various techniques are available for that purpose. For example, using a single &lt;code&gt;top&lt;/code&gt; type, its &lt;code&gt;Execute&lt;/code&gt; method could look up a property on the command instance to select and invoke a concrete runner function, as in this fragment :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// In top.go&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// ...shared fields&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="c"&gt;// command name&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Add the Name, Synopsis, and SetFlags methods to implement subcommands.Command.&lt;/span&gt;

&lt;span class="c"&gt;// NewTop replaces both NewTop1 and NewTop2.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;NewTop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FlagSet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"top1"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;Top1Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// A function in top1.go&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"top2"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
      &lt;span class="n"&gt;Top2Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// A function in top2.go&lt;/span&gt;
    &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unexpected command %s, should never happen"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// In root.go,&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitStatus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
        &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;
    &lt;span class="p"&gt;}{&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"help"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CommandsCommand&lt;/span&gt;&lt;span class="p"&gt;()},&lt;/span&gt;    &lt;span class="c"&gt;// Implement "commands"&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"help"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FlagsCommand&lt;/span&gt;&lt;span class="p"&gt;()},&lt;/span&gt;       &lt;span class="c"&gt;// Implement "flags"&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"help"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HelpCommand&lt;/span&gt;&lt;span class="p"&gt;()},&lt;/span&gt;        &lt;span class="c"&gt;// Implement "help"&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"top"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NewTop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"top1"&lt;/span&gt;&lt;span class="p"&gt;)},&lt;/span&gt;                    &lt;span class="c"&gt;// Our first top-level command, without args&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"top"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NewTop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"top2"&lt;/span&gt;&lt;span class="p"&gt;)},&lt;/span&gt;                    &lt;span class="c"&gt;// Our second top-level command, with args&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Onw downside with this approach is how it introduces coupling between&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the code in the shared &lt;code&gt;Execute&lt;/code&gt; method and the various commands.&lt;/li&gt;
&lt;li&gt;the code in the shared &lt;code&gt;NewTop&lt;/code&gt; factory function, which could requires modifications to accommodate the specifics of various commands&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A better model is more direct and prevents such coupling. It keeps per-command factory functions, and uses a function field to store the runner function on the instance. That way the dedicated factory functions are used in &lt;code&gt;root.go&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitStatus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
        &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;
    &lt;span class="p"&gt;}{&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"help"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CommandsCommand&lt;/span&gt;&lt;span class="p"&gt;()},&lt;/span&gt;    &lt;span class="c"&gt;// Implement "commands"&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"help"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FlagsCommand&lt;/span&gt;&lt;span class="p"&gt;()},&lt;/span&gt;       &lt;span class="c"&gt;// Implement "flags"&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"help"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HelpCommand&lt;/span&gt;&lt;span class="p"&gt;()},&lt;/span&gt;        &lt;span class="c"&gt;// Implement "help"&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"top"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NewTop1&lt;/span&gt;&lt;span class="p"&gt;()},&lt;/span&gt;                         &lt;span class="c"&gt;// Our first top-level command, without args&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"top"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NewTop2&lt;/span&gt;&lt;span class="p"&gt;()},&lt;/span&gt;                         &lt;span class="c"&gt;// Our second top-level command, with args&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;top.go&lt;/code&gt; contains the reusable &lt;code&gt;top&lt;/code&gt; type , with various fields to store :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the constant values for which the &lt;code&gt;Name&lt;/code&gt;, &lt;code&gt;Synopsis&lt;/code&gt; and &lt;code&gt;Usage&lt;/code&gt; will just be getters;&lt;/li&gt;
&lt;li&gt;the local flags shared by both our commands, in this example &lt;code&gt;prefix&lt;/code&gt;, as declared by &lt;code&gt;SetFlags&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;a function field storing the runner function for the &lt;code&gt;Execute&lt;/code&gt; method.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;synopsis&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;usage&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="c"&gt;// Reuse support&lt;/span&gt;
    &lt;span class="n"&gt;prefix&lt;/span&gt;                &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="c"&gt;// Actual features&lt;/span&gt;
    &lt;span class="n"&gt;run&lt;/span&gt;                   &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FlagSet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitStatus&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Synopsis&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;synopsis&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Usage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;usage&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SetFlags&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FlagSet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StringVar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"prefix"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Add a prefix to the result"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FlagSet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitStatus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"command %s is not runnable"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitFailure&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A limitation of function fields vs methods lies in the fact that they do not receive the instance as a hidden first parameter like methods do, meaning that with the same signature, they cannot access the instance, which &lt;code&gt;Execute&lt;/code&gt; needs to access the local flag values.&lt;br&gt;
The command instance must therefore be passed as an explicit extra argument, hence the &lt;code&gt;*top&lt;/code&gt; parameter in the function signature, on line 15.&lt;/p&gt;

&lt;p&gt;To remain as close as possible to a standard &lt;a href="https://go.dev/ref/spec#Method_expressions"&gt;method expression&lt;/a&gt;, that parameter should be the first, but it would conflict with the Go usage of having context always be the first parameter of any function, hence the placement as the second parameter.&lt;/p&gt;

&lt;p&gt;Commands using the shared type, like &lt;code&gt;top2&lt;/code&gt;, define a runner function with that signature, which provides the runner with access to the instance as if they were methods; and their factory function assigns that runner to the instance during the instance initialization process, like in this code in &lt;code&gt;top2.go&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;top2Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FlagSet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitStatus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VerboseKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"In %s.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Args&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;": "&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitSuccess&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;NewTop2&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"top2"&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;synopsis&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s is an exemple top-level custom command with arguments"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;usage&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s arg1 arg2 ..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;      &lt;span class="n"&gt;top2Execute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This process removes coupling between commands and the &lt;code&gt;Execute&lt;/code&gt; function. An unlimited number of commands can now reuse the shared command type, without having to modify the implementation in &lt;code&gt;top.Execute&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ go run . top1 -prefix today
today: hello
$ go run . top2 -prefix "the answer is" 42
the answer is: 42
$
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Level 3 : Commanders
&lt;/h2&gt;

&lt;h3&gt;
  
  
  3.1 Procedural API vs object API
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;The code for that level is available on &lt;a href="https://github.com/fgm/subcommands_demo/tree/level3.1-object_api"&gt;level3.1-object_api&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Up until now, we have been using the public functions exported by google/subcommands :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;subcommands.Alias&lt;/code&gt; and &lt;code&gt;subcommands.Register&lt;/code&gt; to register command instances&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;subcommands.ImportantFlag&lt;/code&gt; to label flags as flobal&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;subcommands.CommandsCommand&lt;/code&gt;, &lt;code&gt;subcommands.FlagsCommand&lt;/code&gt; and &lt;code&gt;subcommands.HelpCommand&lt;/code&gt; for the builtin help and documentation features&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That procedure-based API is actually only a facade simplifying the underlying object API : exepct for &lt;code&gt;Alias&lt;/code&gt;, which does not depend on a &lt;code&gt;Commander&lt;/code&gt;, each of these functions is actually a method call to the method with the same name on a default instance of the &lt;code&gt;subcommands.Commander&lt;/code&gt; type, held in the exported mutable global variable &lt;code&gt;subcommands.DefaultCommander&lt;/code&gt;, which is initialized when importing &lt;code&gt;github.com/google/subcommands&lt;/code&gt; by the &lt;a href="https://github.com/google/subcommands/blob/master/subcommands.go#L462"&gt;&lt;code&gt;init&lt;/code&gt; pseudo-function&lt;/a&gt;, using the &lt;code&gt;subcommands.go&lt;/code&gt; fragment below :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// DefaultCommander is the default commander using flag.CommandLine for flags&lt;/span&gt;
&lt;span class="c"&gt;// and os.Args[0] for the command name.&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;DefaultCommander&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Commander&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;DefaultCommander&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NewCommander&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CommandLine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Register adds a subcommand to the supported subcommands in the&lt;/span&gt;
&lt;span class="c"&gt;// specified group. (Help output is sorted and arranged by group&lt;/span&gt;
&lt;span class="c"&gt;// name.)  The empty string is an acceptable group name; such&lt;/span&gt;
&lt;span class="c"&gt;// subcommands are explained first before named groups. It is a&lt;/span&gt;
&lt;span class="c"&gt;// wrapper around DefaultCommander.Register.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;DefaultCommander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is but one case of a model frequently used throughout the Go standard library, for instance by packages &lt;code&gt;flag&lt;/code&gt; (&lt;code&gt;flag.CommandLine&lt;/code&gt;) or &lt;code&gt;http&lt;/code&gt; (&lt;code&gt;http.DefaultClient&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;We can switch to that object model by only changing our &lt;code&gt;root.go&lt;/code&gt; file, in which we replace every procedural call (except &lt;code&gt;Alias&lt;/code&gt;) by a method call on that default &lt;code&gt;Commander&lt;/code&gt; instance :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitStatus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;commander&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DefaultCommander&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
        &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;
    &lt;span class="p"&gt;}{&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"help"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;commander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CommandsCommand&lt;/span&gt;&lt;span class="p"&gt;()},&lt;/span&gt;      &lt;span class="c"&gt;// Implement "commands"&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"help"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;commander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FlagsCommand&lt;/span&gt;&lt;span class="p"&gt;()},&lt;/span&gt;         &lt;span class="c"&gt;// Implement "flags"&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"help"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;commander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HelpCommand&lt;/span&gt;&lt;span class="p"&gt;()},&lt;/span&gt;          &lt;span class="c"&gt;// Implement "help"&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"top"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NewTop1&lt;/span&gt;&lt;span class="p"&gt;()},&lt;/span&gt;                         &lt;span class="c"&gt;// Our first top-level command, without args&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"top"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NewTop2&lt;/span&gt;&lt;span class="p"&gt;()},&lt;/span&gt;                         &lt;span class="c"&gt;// Our second top-level command, with args&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"top"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Alias&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NewTop1&lt;/span&gt;&lt;span class="p"&gt;())},&lt;/span&gt; &lt;span class="c"&gt;// An alias for our top1 command&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;commander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;debug&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"debug"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Show debug information"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;verbose&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Be more verbose"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;commander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ImportantFlag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"v"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DebugKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;VerboseKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;commander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"meaning"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The program keeps operating in the exact same way as the previous version.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.2 Using custom commanders
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;The code for that level is available on &lt;a href="https://github.com/fgm/subcommands_demo/tree/level3.2-custom_commander"&gt;level3.2-custom_commander&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Our next step will be to create our own &lt;code&gt;Commander&lt;/code&gt; instance, rather that using the shared mutable instance exported by google/subcommands, so we can keep its initialization and mutations under control. We will therefore create it in the &lt;code&gt;Execute&lt;/code&gt; function in our &lt;code&gt;root.go&lt;/code&gt; file :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitStatus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// See subcommands.DefaultCommander&lt;/span&gt;
    &lt;span class="n"&gt;commander&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewCommander&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CommandLine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing else deviates from the previous version, but we are now one step closer to a testable code structure, by removing our dependency on the global &lt;code&gt;subcommands.DefaultCommander&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Time to finish the work and make &lt;code&gt;Execute&lt;/code&gt; completely testable by removing all remaining dependencies to other globals.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.3 Creating a testable command structure
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;The code for that level is available on &lt;a href="https://github.com/fgm/subcommands_demo/tree/level3.3-testable"&gt;level3.3&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Our code is still encumbered by a number of obstacles before it can be unit tested easily :&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;th&gt;Solution&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;global standard and error outputs&lt;/td&gt;
&lt;td&gt;inject from &lt;code&gt;main&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;global &lt;code&gt;os.Args&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;inject from &lt;code&gt;main&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;global &lt;code&gt;flag.CommandLine&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;replace by a custom &lt;code&gt;flag.FlagSet&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;global &lt;code&gt;flag.Bool&lt;/code&gt;, &lt;code&gt;flag.Parse&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;replace by equivalent &lt;code&gt;flag.FlagSet&lt;/code&gt; methods&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;hidden use of global &lt;code&gt;log.std&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;remplace by a custom &lt;code&gt;log.Logger&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;flag&lt;/code&gt; calling &lt;code&gt;os.Exit&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;modify &lt;code&gt;flag.FlagSet&lt;/code&gt; creation options&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;command creation in &lt;code&gt;Execute&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;inject from a factory&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Once we apply these changes, our latest version of &lt;code&gt;main.go&lt;/code&gt; should become the only place where globals are still accessed :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;sts&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stdout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stderr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LstdFlags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Describe&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sts&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also need to create a &lt;code&gt;Describe&lt;/code&gt; factory instantiating our commands in  &lt;code&gt;root.go&lt;/code&gt;,  so that &lt;code&gt;Execute&lt;/code&gt; now receives them instead of creating them itself :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;group&lt;/span&gt;   &lt;span class="kt"&gt;string&lt;/span&gt;
  &lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outW&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Writer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"top"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NewTop1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outW&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;)},&lt;/span&gt;                         &lt;span class="c"&gt;// Our first top-level command, without args&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"top"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NewTop2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outW&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;)},&lt;/span&gt;                         &lt;span class="c"&gt;// Our second top-level command, with args&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"top"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Alias&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NewTop1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outW&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;))},&lt;/span&gt; &lt;span class="c"&gt;// An alias for our top1 command&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;…and our new version of &lt;code&gt;Execute&lt;/code&gt; now receives all that data it needs by injection instead of referencing imported variables or creating instances itself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;outW&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Writer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c"&gt;// Standard output for command results&lt;/span&gt;
    &lt;span class="n"&gt;errW&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Writer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c"&gt;// Error output for logs&lt;/span&gt;
    &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c"&gt;// CLI args to avoid depending on the flag global&lt;/span&gt;
    &lt;span class="n"&gt;logFlags&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c"&gt;// Log flags to make error message testing easier&lt;/span&gt;
    &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outW&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Writer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c"&gt;// Command registration descriptions&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitStatus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Do not depend on log.Default().&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errW&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;logFlags&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Create a flag.FlagSet from args to avoid depending on global os.Args.&lt;/span&gt;
    &lt;span class="c"&gt;// Continue on error to support testing instead of the ExitOnError on flag.CommandLine&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Expected at least one argument for the program name, got none"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitFailure&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewFlagSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ContinueOnError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Create a custom commander to avoid depending on global flag.CommandLine and os.Args&lt;/span&gt;
    &lt;span class="n"&gt;commander&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewCommander&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="n"&gt;descriptions&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"help"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;commander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CommandsCommand&lt;/span&gt;&lt;span class="p"&gt;()},&lt;/span&gt; &lt;span class="c"&gt;// Implement "commands"&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"help"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;commander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FlagsCommand&lt;/span&gt;&lt;span class="p"&gt;()},&lt;/span&gt;    &lt;span class="c"&gt;// Implement "flags"&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"help"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;commander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HelpCommand&lt;/span&gt;&lt;span class="p"&gt;()},&lt;/span&gt;     &lt;span class="c"&gt;// Implement "help"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;descriptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;descriptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outW&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;descriptions&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;commander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;debug&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"debug"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Show debug information"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;verbose&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Be more verbose"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;commander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ImportantFlag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"v"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Parse must not receive the program name, hence the slice.&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Our logger has been configured above.&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error parsing CLI flags: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitUsageError&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DebugKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;VerboseKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;commander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"meaning"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;40-41: &lt;code&gt;outW&lt;/code&gt; and &lt;code&gt;errW&lt;/code&gt; are the two &lt;code&gt;io.Writer&lt;/code&gt; passed by &lt;code&gt;main()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;41,47: &lt;code&gt;errW&lt;/code&gt; is used to create a &lt;code&gt;log.Logger&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;44: &lt;code&gt;describe&lt;/code&gt; is the command description factory, passed by &lt;code&gt;main()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;55: a new &lt;code&gt;FlagSet&lt;/code&gt; is created from received parameters, to break the dependency on &lt;code&gt;os.Args&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;58: a &lt;code&gt;Commander&lt;/code&gt; is create from that new &lt;code&gt;FlagSet&lt;/code&gt; and received arguments, to break the dependency on &lt;code&gt;flag.CommandLine&lt;/code&gt;, and indirect dependency to &lt;code&gt;os.Args&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;66: &lt;code&gt;outW&lt;/code&gt; and our new logger are passed to &lt;code&gt;describe&lt;/code&gt; so it can pass them  into the command factory functions, allowing command instances to work on injected writers instead of global variables.&lt;/li&gt;
&lt;li&gt;72, 73: global flags are defined on the new &lt;code&gt;FlagSet&lt;/code&gt; instead of global &lt;code&gt;flag.CommandLine&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;77: flags parsing is run on the &lt;code&gt;FlagSet&lt;/code&gt; instead of global &lt;code&gt;flag.CommandLine&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;Execute&lt;/code&gt; is no longer using any global variable, and passes injected dependencies to the &lt;code&gt;top1&lt;/code&gt; et &lt;code&gt;top2&lt;/code&gt; command instances. We have to modify these too, so that they use the injected writer and logger instead of shared globals. This is how it applies in &lt;code&gt;top1.go&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;top1Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FlagSet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitStatus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VerboseKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"In %s.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NArg&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s expects no arguments, called with %d: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Args&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitFailure&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"hello"&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;": "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;outW&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitSuccess&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;NewTop1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outW&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Writer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"top1"&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;outW&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="n"&gt;outW&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;      &lt;span class="n"&gt;top1Execute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;synopsis&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s is an exemple top-level custom command without arguments"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;usage&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code in &lt;code&gt;top2&lt;/code&gt; is very similar, and the &lt;code&gt;top&lt;/code&gt; type in &lt;code&gt;top.go&lt;/code&gt; has been extended as show at lines 34-40 above to store the injected dependencies.&lt;/p&gt;

&lt;p&gt;This enables us to establish a &lt;a href="https://github.com/fgm/subcommands_demo/tree/level3.3-testable/cmd"&gt;100% test coverage rate&lt;/a&gt; very simply, without needing any mocking tool.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ go test -race -count=1 -cover ./cmd
ok      github.com/fgm/subcommands_demo/cmd 0.035s  coverage: 100.0% of statements
$
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Level 4 : adding nested subcommands
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;The code for that level is available on &lt;a href="https://github.com/fgm/subcommands_demo/tree/level4.1-nesting"&gt;level4.1-nesting&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With more complex applications, some commands will need a hierarchy of subcommands, but google/subcommands does not describe how to implement them, leading to a false impression that it does not support them.&lt;/p&gt;

&lt;p&gt;That support is actually a consequence of our use of a custom commander created from received parameters passed to &lt;code&gt;subcommands.NewCommander&lt;/code&gt; : since flags are now defined on a local &lt;code&gt;FlagSet&lt;/code&gt; and arguments received, all it takes to implement a command accepting subcommands is to create a &lt;code&gt;Commander&lt;/code&gt; instance from the arguments not consumed after resolving the command itself.&lt;/p&gt;

&lt;p&gt;This is how our new &lt;code&gt;top3&lt;/code&gt; works, with its &lt;code&gt;sub31&lt;/code&gt; and &lt;code&gt;sub32&lt;/code&gt; nested commands, to be found in &lt;code&gt;top3.go&lt;/code&gt;. Feature-wise, it is similar to &lt;code&gt;top1&lt;/code&gt; and &lt;code&gt;top2&lt;/code&gt;, but its runner function &lt;code&gt;top31Execute&lt;/code&gt; now includes the subcommands handling logic in addition to the base &lt;code&gt;top3&lt;/code&gt; logic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;top3Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;topFS&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FlagSet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitStatus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VerboseKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"In %s.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c"&gt;// Handle command called without subcommands.&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;topFS&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NArg&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;top3Internal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;topFS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Create a flag.FlagSet from args to use only remaining args&lt;/span&gt;
    &lt;span class="c"&gt;// Continue on error to support testing.&lt;/span&gt;
    &lt;span class="n"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewFlagSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ContinueOnError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Create a custom commander to restart evaluation below this command.&lt;/span&gt;
    &lt;span class="n"&gt;commander&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewCommander&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;descriptions&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;commander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CommandsCommand&lt;/span&gt;&lt;span class="p"&gt;()},&lt;/span&gt; &lt;span class="c"&gt;// Implement "commands"&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;commander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FlagsCommand&lt;/span&gt;&lt;span class="p"&gt;()},&lt;/span&gt;    &lt;span class="c"&gt;// Implement "flags"&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;commander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HelpCommand&lt;/span&gt;&lt;span class="p"&gt;()},&lt;/span&gt;     &lt;span class="c"&gt;// Implement "help"&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NewSub31&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;outW&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;)},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NewSub32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;outW&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;)},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;descriptions&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;commander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Parse must not receive the command name.&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;topFS&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Args&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error parsing %s flags: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitUsageError&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;commander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;near the beginning (lines 29-31), the command checks whether it receives arguments, which could be subcommand names. If there are none, it then transfers control to its own internal logic, which performs the work desired for &lt;code&gt;top3&lt;/code&gt; without a subcommand.&lt;/li&gt;
&lt;li&gt;otherwise, it implements a logic similar to the one in our root &lt;code&gt;Execute&lt;/code&gt; function :

&lt;ul&gt;
&lt;li&gt;create a local &lt;code&gt;FlagSet&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;create a local &lt;code&gt;Commander&lt;/code&gt; from that &lt;code&gt;FlagSet&lt;/code&gt; and available arguments,&lt;/li&gt;
&lt;li&gt;register subcommands on the &lt;code&gt;Commander&lt;/code&gt;, including builtin commnds,&lt;/li&gt;
&lt;li&gt;parse available arguments for local flags and arguments on the nested commands&lt;/li&gt;
&lt;li&gt;run the subcommand designated by arguments, if any.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ go run . top3
hello top3
$ go run . top3 commands
commands
flags
help
sub31
sub32
$ go run . top3 help sub31
sub31  -prefix string
        Add a prefix to the result
$ go run . top3 sub31 -prefix today
today: hello sub31
$
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Level 5 : beyond &lt;code&gt;NewCommander&lt;/code&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  5.1 Controlling outputs beyond our code
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;The code for that level is available on &lt;a href="https://github.com/fgm/subcommands_demo/tree/level5.1-newcommander"&gt;level5.1-newcommander&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Although we have injected everything for our own logic to support unit testing, some error outputs remain, from the &lt;code&gt;subcommands&lt;/code&gt; and &lt;code&gt;flag&lt;/code&gt; packages themselves, in error situations, and can be seen when running tests. We could have foreseen it, because &lt;code&gt;NewCommander&lt;/code&gt; does not take any argument for the standard or output error to use by the instance it returns.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ go test -race -count=1 -v  ./cmd 2&amp;gt;&amp;amp;1 | grep -vE '(CONT|RUN|PASS|PAUSE)'
flag provided but not defined: -bad
Usage: Test_Execute &amp;lt;flags&amp;gt; &amp;lt;subcommand&amp;gt; &amp;lt;subcommand args&amp;gt;

Subcommands for help:

  ...snip (33 lines total)...

flag provided but not defined: -bad
top1  -prefix string
        Add a prefix to the result
flag provided but not defined: -bad
c  -prefix string
        Add a prefix to the result
ok      github.com/fgm/subcommands_demo/cmd 0.036s
$
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However just because that redirection is not available at instance creation, it is still available &lt;em&gt;after&lt;/em&gt; creation, as we do here in &lt;code&gt;root.go&lt;/code&gt; for top-level commands and global flags :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;outW&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Writer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c"&gt;// Standard output for command results&lt;/span&gt;
    &lt;span class="n"&gt;errW&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Writer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c"&gt;// Error output for logs&lt;/span&gt;
    &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c"&gt;// CLI args to avoid depending on the flag global&lt;/span&gt;
    &lt;span class="n"&gt;logFlags&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c"&gt;// Log flags to make error message testing easier&lt;/span&gt;
    &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outW&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Writer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c"&gt;// Command registration descriptions&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitStatus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* ...snip... */&lt;/span&gt;
    &lt;span class="n"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewFlagSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ContinueOnError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetOutput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errW&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Create a custom commander to avoid depending on global flag.CommandLine and os.Args&lt;/span&gt;
    &lt;span class="n"&gt;commander&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewCommander&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;commander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;outW&lt;/span&gt;
    &lt;span class="n"&gt;commander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;errW&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Redirecting the additional properties removes most of the parasitic output we were seeing during tests :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ go test -race -count=1 -v  ./cmd 2&amp;gt;&amp;amp;1 | grep -vE '(CONT|RUN|PASS|PAUSE)'
flag provided but not defined: -bad
flag provided but not defined: -bad
ok      github.com/fgm/subcommands_demo/cmd 0.045s
$
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The two remaining uncaptured messages appear to be a bug in version 1.2.0 of google/subcommands, for which &lt;a href="https://github.com/google/subcommands/pull/39"&gt;a pull request exists&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We have now covered all the useful features of the google/subcommands package. All that remains is two related sets of features which are unlikely to be used in most practical cases.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.2 Commanders introspection
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;The code for that level is available on &lt;a href="https://github.com/fgm/subcommands_demo/tree/level5.2-visit"&gt;level5.2-visit&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;subcommands.Commander&lt;/code&gt; type includes exported methods allowing code to examine its internal flags and commands data.&lt;/p&gt;

&lt;p&gt;Let us create a top-level &lt;code&gt;visit&lt;/code&gt; command, similar to those we have been writing, and which demonstrates all these methods. It is located in the &lt;code&gt;visit.go&lt;/code&gt; file.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;VisitAll&lt;/code&gt; methods implements the Visitor pattern, allowing introspection of the flags on the &lt;code&gt;Commander&lt;/code&gt; instances:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;visitAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;commander&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Commander&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Writer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"VisitAll show all the commander flags:"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;tw&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;tabwriter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewWriter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tabwriter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tw&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;Name&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;Default&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;Value&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;Usage&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;commander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VisitAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Flag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tw&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\t\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DefValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Usage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="n"&gt;tw&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Flush&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Running "demo visit":
VisitAll show all the commander flags:
 |Name  |Default |Value |Usage                  |
 |debug |false   |false |Show debug information |
 |v     |false   |true  |Be more verbose        |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;VisitAllImportant&lt;/code&gt; methods is almost identical, but only visits flags labeled as important:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;VisitAllImportant only shows the "important" flags:
 |Name |Default |Value |Usage           |
 |v    |false   |true  |Be more verbose |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;VisitGroups&lt;/code&gt; method implements the Visitor pattern, allowing introspection of the &lt;code&gt;CommandGroup&lt;/code&gt; instances created from the group names used when registering commands. It is quite limited, as the public methods on the &lt;code&gt;CommandGroup&lt;/code&gt; type do not provide access to the grouped commands:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;visitGroups&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;commander&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Commander&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Writer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"VisitGroups only visits the command groups, not the commands:"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;tw&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;tabwriter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewWriter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tabwriter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tw&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;Name&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;Len&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;commander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VisitGroups&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CommandGroup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tw&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;%d&lt;/span&gt;&lt;span class="se"&gt;\t\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Len&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="n"&gt;tw&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Flush&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;VisitGroups only visits the command groups, not the commands:
 |Name |Len |
 |help |3   |
 |top  |5   |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;VisitCommands&lt;/code&gt; method implement the Visitor pattern in a much more useful way, providing access to the &lt;code&gt;Command&lt;/code&gt; instances registered on the &lt;code&gt;Commander&lt;/code&gt;, and from there to their &lt;code&gt;CommandGroup&lt;/code&gt; and local flags:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;visitCommands&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;commander&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Commander&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Writer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"VisitCommands visits the commands themselves:"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;tw&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;tabwriter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewWriter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tabwriter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tw&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;Group&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;Name&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;Synopsis&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;Flags&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;commander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VisitCommands&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CommandGroup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewFlagSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"visit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ContinueOnError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetFlags&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;
        &lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VisitAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Flag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tw&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\t\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Synopsis&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;", "&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="n"&gt;tw&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Flush&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"(command usage omitted for readability)"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;VisitCommands visits the commands themselves:
 |Group |Name     |Synopsis                                                            |Flags  |
 |help  |commands |list all command names                                              |       |
 |help  |flags    |describe all known top-level flags                                  |       |
 |help  |help     |describe subcommands and their syntax                               |       |
 |top   |top1     |top1 is an exemple top-level custom command without arguments       |prefix |
 |top   |top2     |top2 is an exemple top-level custom command with arguments          |prefix |
 |top   |1        |top1 is an exemple top-level custom command without arguments       |prefix |
 |top   |top3     |top3 is an exemple top-level custom command with nested subcommands |prefix |
 |top   |visit    |demoes commander Visit* functions                                   |       |
(command usage omitted for readability)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because these visitor callbacks do not receive the &lt;code&gt;Commander&lt;/code&gt; instance, the &lt;code&gt;visit&lt;/code&gt; command will need to carry an injected commander instance, as commands are not aware of the &lt;code&gt;Commander&lt;/code&gt; invoking them. We perform this with a new feature in &lt;code&gt;root.go&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;CommanderAware&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;SetCommander&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;commander&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;subcommands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Commander&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c"&gt;/* ...snip... */&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;descriptions&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;vc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CommanderAware&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;vc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetCommander&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;commander&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;commander&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our &lt;code&gt;visit&lt;/code&gt; command is an instance of the &lt;code&gt;visitCmd&lt;/code&gt; type, which includes a &lt;code&gt;subcommands.Commander&lt;/code&gt; field, and an associated &lt;code&gt;visitCmd.SetCommander&lt;/code&gt; setter, making it a &lt;code&gt;CommanderAware&lt;/code&gt; implementation, allowing the &lt;code&gt;Execute&lt;/code&gt; function to inject it with the active &lt;code&gt;Commander&lt;/code&gt; as show on lines 48-49.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.3 Overriding builtin output
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;The code for that level is available on &lt;a href="https://github.com/fgm/subcommands_demo/tree/level5.3-explain"&gt;level5.3-explain&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The last and most esoteric feature in google/subcommands is the ability to swap the implementation of the builtin &lt;code&gt;CommandsCommand&lt;/code&gt;, &lt;code&gt;FlagsCommand&lt;/code&gt; and &lt;code&gt;HelpCommand&lt;/code&gt;, using matching function fieled on the &lt;code&gt;subcommands.Commander&lt;/code&gt; type :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Explain&lt;/code&gt; is a &lt;code&gt;func(io.Writer)&lt;/code&gt; field, initialized in &lt;code&gt;NewCommander&lt;/code&gt; with the unexported method expression &lt;code&gt;cdr.writer&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ExplainGroup&lt;/code&gt; is a &lt;code&gt;func(io.Writer, *CommandGroup)&lt;/code&gt; field, initialized in &lt;code&gt;NewCommander&lt;/code&gt; with unexported function &lt;code&gt;explainGroup&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ExplainCommand&lt;/code&gt; is a &lt;code&gt;func(w io.Writer, c subcommands.Command)&lt;/code&gt; field, initialized in &lt;code&gt;NewCommander&lt;/code&gt; with unexported function &lt;code&gt;explain&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since these function fields are missing receiver access although they need it, our new &lt;code&gt;explain&lt;/code&gt; command, defined in &lt;code&gt;cmd/explain.go&lt;/code&gt;, has to be &lt;code&gt;CommanderAware&lt;/code&gt;, so it can replace the fields with functions having access to the &lt;code&gt;Commander&lt;/code&gt; instance, using the one instance it was injected with :&lt;/p&gt;

&lt;p&gt;Examples below first show the default builtin output, then the output of a customized version&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ExplainCommand&lt;/code&gt; : builtin output, then YAML API version:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Running "demo explain":

Demoes overriding ExplainCommand to describe top3.
- Builtin version using unexported explain:
top3  -prefix string
        Add a prefix to the result
- Custom version in YAML format:
top3:
    flags:
        - name: prefix
          default: ""
          usage: Add a prefix to the result
    synopsis: top3 is an exemple top-level custom command with nested subcommands
    usage: top3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ExplainGroup&lt;/code&gt; : builtin output, then YAML API version:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Demoes overriding ExplainGroup.
- Builtin version using private explainGroup:
Subcommands for help:
    commands         list all command names
    flags            describe all known top-level flags
    help             describe subcommands and their syntax  
...snip...
- Custom version in YAML format, without access to group contents:
help: 3
top: 6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Explain&lt;/code&gt; : builtin output, then neutral version suggesting how to write a custom description
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Demoes overriding Explain.
- Builtin version using private commander.explain:
Usage: demo &amp;lt;flags&amp;gt; &amp;lt;subcommand&amp;gt; &amp;lt;subcommand args&amp;gt;


Top-level flags (use "demo flags" for a full list):
  -v=false: Be more verbose

- Custom version, build from commander methods:
Use any commander.(Explain|Visit)* methods
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Pros

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;google/subcommands&lt;/code&gt; is an excellent fit for small, simple projects&lt;/li&gt;
&lt;li&gt;it is uncommonly lightweight, and very stable due to its having no dependencies at all&lt;/li&gt;
&lt;li&gt;starting with it does not prevent evolving from a simple version to a multi-level command hierarchy with a mix of local and global flags&lt;/li&gt;
&lt;li&gt;it does not make it difficult to provide unit test coverage for the commands  themselves instead of limiting one to the service code the commands call upon.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Cons

&lt;ul&gt;
&lt;li&gt;it does not natively merge CLI flags and environment variables&lt;/li&gt;
&lt;li&gt;it does not natively include merging configuration files with flags&lt;/li&gt;
&lt;li&gt;creating complex commands with validation hooks has no direct support: all steps will have to be implemented together in the &lt;code&gt;Execute&lt;/code&gt; method&lt;/li&gt;
&lt;li&gt;it does not natively include the &lt;em&gt;persistent flags&lt;/em&gt; concept, that is flags defined at one level and also applying to subcommands. These can however be passed manually, for example in the context like we did for global flags.&lt;/li&gt;
&lt;li&gt;creating multi-level command hierarchies requires a bit more work than with some other tools.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To summarize, that package is likely to be your tool of choice for your next microservice or CLI tool, but not if you are building your next giant monolith.&lt;/p&gt;

</description>
      <category>howto</category>
      <category>go</category>
      <category>cli</category>
    </item>
    <item>
      <title>Tip of the day: how to edit Ansible Jinja2 templates in JetBrains IDEs</title>
      <dc:creator>Frédéric G. MARAND</dc:creator>
      <pubDate>Sun, 26 Dec 2021 13:36:29 +0000</pubDate>
      <link>https://dev.to/fgm/tip-of-the-day-how-to-edit-ansible-jinja2-templates-in-jetbrains-ides-imk</link>
      <guid>https://dev.to/fgm/tip-of-the-day-how-to-edit-ansible-jinja2-templates-in-jetbrains-ides-imk</guid>
      <description>&lt;p&gt;&lt;a href="https://blog.riff.org/topic/computing"&gt;Computing&lt;/a&gt; | &lt;a href="https://blog.riff.org/taxonomy/term/246"&gt;Ansible&lt;/a&gt; | &lt;a href="https://blog.riff.org/taxonomy/term/247"&gt;Jinja2&lt;/a&gt; | &lt;a href="https://blog.riff.org/taxonomy/term/248"&gt;Twig&lt;/a&gt; | &lt;a href="https://blog.riff.org/taxonomy/term/242"&gt;Goland&lt;/a&gt; | &lt;a href="https://blog.riff.org/tags/phpstorm"&gt;phpstorm&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One annoying missing feature in most JetBrains IDEs is the lack of builtin support for Jinja2 templates, used notably as the Ansible template engine.&lt;/p&gt;

&lt;p&gt;One &lt;em&gt;paid&lt;/em&gt; solution exists, the &lt;a href="https://plugins.jetbrains.com/plugin/12626-orchide--ansible-language-support"&gt;OrchidE&lt;/a&gt; plugin, but there is a free workaround. Can you guess which one ?&lt;/p&gt;

&lt;p&gt;One template engine which originally got a lot of inspiration from &lt;a href="https://jinja.palletsprojects.com/en/3.0.x/"&gt;Jinja&lt;/a&gt; is the PHP &lt;a href="https://twig.symfony.com/"&gt;Twig&lt;/a&gt; engine made popular by Symfony.&lt;/p&gt;

&lt;p&gt;Even today, in spite of the divergent evolutions of Jinja 3 and Twig 3, it is close enough in basic syntax for the Twig plugin to be used to edit Ansible Jinja templates. And the JetBrains &lt;a href="https://plugins.jetbrains.com/plugin/7303-twig"&gt;Twig plugin&lt;/a&gt; has a very useful feature in the form of "sub-templates". That is, providing syntax support for both the template engine itself (the braces content) and the template destination (YAML, INI, Apache Config, etc).&lt;/p&gt;

&lt;p&gt;This relies on having template files named &lt;code&gt;(file).(target type).twig&lt;/code&gt; : on such files the Twig plugin applies Twig (Jinja) syntax to the braces content and target type syntax to the rest of the file. For example, we could create a &lt;code&gt;myvhost.apacheconf.twig&lt;/code&gt; file and have it be edited as a "Jinja" template targeting an Apache config file, with the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to Preferences / Editor / File Types, add &lt;code&gt;*.apacheconf&lt;/code&gt; to the &lt;em&gt;Apache config&lt;/em&gt; type; validate.&lt;/li&gt;
&lt;li&gt;Create your Apache vhost template as &lt;code&gt;my_vhost.j2&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Symlink it to &lt;code&gt;my_vhost.apacheconf.twig&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Enjoy !&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you don't mind going for a more unusual, but even simpler approach, you can even forego the &lt;code&gt;*.j2&lt;/code&gt; extension altogether, and name your templates that way, also when referencing them as &lt;code&gt;template.src&lt;/code&gt; arguments: no symlinks, no problems.&lt;/p&gt;

&lt;p&gt;Just don't forget to document why your templates are named that way in your project README file: other devs could be surprised to see that unusual extension.&lt;/p&gt;

</description>
      <category>jinja</category>
      <category>ansible</category>
      <category>twig</category>
      <category>jetbrains</category>
    </item>
    <item>
      <title>GoLand tip of the day: clean up GoLand leftover cache and log folders</title>
      <dc:creator>Frédéric G. MARAND</dc:creator>
      <pubDate>Thu, 25 Mar 2021 08:15:05 +0000</pubDate>
      <link>https://dev.to/fgm/goland-tip-of-the-day-clean-up-goland-leftover-cache-and-log-folders-1dbf</link>
      <guid>https://dev.to/fgm/goland-tip-of-the-day-clean-up-goland-leftover-cache-and-log-folders-1dbf</guid>
      <description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.riff.org/taxonomy/term/242"&gt;Goland&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When GoLand is upgraded from one version to the next, the deployment process adds a new set of configuration, cache, and log directories. But it does not remove the versions associated to the previous versions of the IDE, to ease rolling back to the previous version if an upgrade happens to cause an issue.&lt;/p&gt;

&lt;p&gt;So after some time, removing these now-unused folders will regain some disk space, possibly more than 1 GB. Here are their respective locations and content on macOS:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;Size indication&lt;/th&gt;
&lt;th&gt;Configuration variable&lt;/th&gt;
&lt;th&gt;Default location&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Configuration&lt;/td&gt;
&lt;td&gt;3 to 10 MB&lt;/td&gt;
&lt;td&gt;&lt;code&gt;idea.config.path&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;~/Library/Preferences/Gogland1.0&lt;/code&gt; &lt;code&gt;~/Library/Preferences/Goland.(version)&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Plugins&lt;/td&gt;
&lt;td&gt;50 to 100 MB&lt;/td&gt;
&lt;td&gt;&lt;code&gt;idea.plugins.path&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;~/Library/Application Support/Gogland1.0&lt;/code&gt; &lt;code&gt;~/Library/Application Support/GoLand-EAP&lt;/code&gt; &lt;code&gt;~/Library/Application Support/GoLand ~/Library/Application Support/GoLand.(version)&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Caches&lt;/td&gt;
&lt;td&gt;200 MB or (much) more&lt;/td&gt;
&lt;td&gt;&lt;code&gt;idea.system.path&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;~/Library/Caches/Gogland1.0&lt;/code&gt; &lt;code&gt;~/Library/Caches/GoLand2018.(version)&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Logs&lt;/td&gt;
&lt;td&gt;1 to 10 MB&lt;/td&gt;
&lt;td&gt;&lt;code&gt;idea.log.path&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;~/Library/Logs/Gogland1.0&lt;/code&gt; &lt;code&gt;~/Library/Logs/GoLand2018.(version)&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;On Windows and Linux, lookup the location using the name of the configuration variable in the third column.&lt;/p&gt;

&lt;p&gt;Notice that the Toolbox app uses similar locations&lt;/p&gt;

</description>
      <category>goland</category>
      <category>go</category>
      <category>jetbrains</category>
    </item>
    <item>
      <title>Tip of the day: patching legacy Drupal 7 projects with Composer</title>
      <dc:creator>Frédéric G. MARAND</dc:creator>
      <pubDate>Tue, 26 Jan 2021 09:30:58 +0000</pubDate>
      <link>https://dev.to/fgm/tip-of-the-day-patching-legacy-drupal-7-projects-with-composer-5209</link>
      <guid>https://dev.to/fgm/tip-of-the-day-patching-legacy-drupal-7-projects-with-composer-5209</guid>
      <description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.riff.org/topic/computing/php_0"&gt;PHP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.riff.org/category/drupal_tips_and_tricks"&gt;Drupal tips and tricks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.riff.org/tags/drupal7"&gt;DRUPAL-7&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.riff.org/tags/composer"&gt;Composer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some late Drupal 7 projects use Composer for project structure and tooling, even though they don't use Composer for the Drupal requirements proper. In that case, the normal Drupal 8/9 patching process using &lt;a href="https://github.com/cweagans/composer-patches"&gt;cweagans/composer-patches&lt;/a&gt; is not available, since dependencies are not handled with Composer. &lt;/p&gt;

&lt;p&gt;So, is there a way to apply patches cleanly from Composer ? Sure there is! Let's see how.&lt;/p&gt;

&lt;h3&gt;
  
  
  The problem
&lt;/h3&gt;

&lt;p&gt;A typical situation happens like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Legacy Drupal 7 project keeps on being used, but not upgraded to Drupal 8 / Drupal 9 or BackdropCMS/li&amp;gt; &lt;/li&gt;
&lt;li&gt;Since it has to be maintainable, it is best on the then-current technique of git submodules, with each contrib being brought in as a separate submodule&lt;/li&gt;
&lt;li&gt;But then, more recent updates bring in Composer, e.g. to start using modern PHP components, starting the autoloader from &lt;code&gt;settings.local.php&lt;/code&gt;; or using it for additional tools like Drush or PHPunit. &lt;/li&gt;
&lt;li&gt;When a module needs to be patched, the legacy drush-based process becomes an issue with submodules and Composer, and yet, because components are not downloaded by Composer, using &lt;code&gt;cweagans/composer-patches&lt;/code&gt; is not an options&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now, how can the patch process be handled in &lt;code&gt;composer.json&lt;/code&gt;, just as is would be in any modern Composer deployment ?&lt;/p&gt;

&lt;h3&gt;
  
  
  How to use Composer patches with zero plugin
&lt;/h3&gt;

&lt;p&gt;There is actually a very simple mechanism for this: using Composer hooks on &lt;a href="https://getcomposer.org/doc/articles/scripts.md#command-events"&gt;command events&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That's all we need. Let's take an example: how to add the PHP 7.4 compatibility patch for Gmap, available on the &lt;a href="https://www.drupal.org/project/gmap/issues/3118279"&gt;https://www.drupal.org/project/gmap/issues/3118279&lt;/a&gt; issue ?&lt;/p&gt;

&lt;h4&gt;
  
  
  First step: creating a &lt;code&gt;composer patch&lt;/code&gt; command
&lt;/h4&gt;

&lt;p&gt;First we need to defined our patches and how to apply them. Here is what needs to be added to &lt;code&gt;composer.json&lt;/code&gt; for a start:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="err"&gt;...misc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;sections...&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="nl"&gt;"require"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="s2"&gt;"require-dev: { ... },  
  "&lt;/span&gt;&lt;span class="err"&gt;scripts&lt;/span&gt;&lt;span class="s2"&gt;": {    
    "&lt;/span&gt;&lt;span class="err"&gt;patch&lt;/span&gt;&lt;span class="s2"&gt;": [      
      "&lt;/span&gt;&lt;span class="err"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;www/sites/all/modules/contrib/gmap;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;curl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;https://www.drupal.org/files/issues/&lt;/span&gt;&lt;span class="mi"&gt;2020-03-06&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;3118279-3&lt;/span&gt;&lt;span class="err"&gt;.patch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;patch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;-p&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s2"&gt;"   
    ],  
  },  
  "&lt;/span&gt;&lt;span class="err"&gt;type&lt;/span&gt;&lt;span class="s2"&gt;": "&lt;/span&gt;&lt;span class="err"&gt;project&lt;/span&gt;&lt;span class="s2"&gt;"
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;scripts&lt;/code&gt; section allows adding custom commands to Composer&lt;/li&gt;
&lt;li&gt;In this case, we add a new &lt;code&gt;patch&lt;/code&gt; command, to apply all patches&lt;/li&gt;
&lt;li&gt;Since commands can be just shell scripts, we create one line for each patch, made of two parts:

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;cd (the module directory)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;apply the patch straight from its download URL, taking advantage of the fact that the &lt;code&gt;patch&lt;/code&gt; command takes patches form its standard input&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;These two have to be kept as a single shell command, because the working directory is only retained for the direction of the shell subprocess, hence the &lt;code&gt;;&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this step, we can now use &lt;code&gt;composer patch&lt;/code&gt; to apply our patches on demand. But we can do better: apply the command automatically.&lt;/p&gt;

&lt;h4&gt;
  
  
  Second step: applying patches on composer install/update
&lt;/h4&gt;

&lt;p&gt;Remember, Composer includes these command hooks for install and update. To quote the Composer documentation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;post-install-cmd&lt;/code&gt;: occurs after the install command has been executed with a lock file present.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;post-update-cmd&lt;/code&gt;: occurs after the update command has been executed, or after the install command has been executed without a lock file present.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Beyond invoking shell scripts, Composer can also invoke its custom commands by prepending them with an &lt;code&gt;@&lt;/code&gt; like Symfony services&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...snip...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;    
    &lt;/span&gt;&lt;span class="nl"&gt;"patch"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;      
      &lt;/span&gt;&lt;span class="s2"&gt;"cd www/sites/all/modules/contrib/gmap; curl https://www.drupal.org/files/issues/2020-03-06/3118279-3.patch | patch -p1"&lt;/span&gt;&lt;span class="w"&gt;   
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;    
    &lt;/span&gt;&lt;span class="nl"&gt;"post-install-cmd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"@patch"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;    
    &lt;/span&gt;&lt;span class="nl"&gt;"post-update-cmd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"@patch"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="err"&gt;...snip...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, any time we run &lt;code&gt;composer install&lt;/code&gt; or &lt;code&gt;composer update&lt;/code&gt;, Composer will apply the patches without having to type &lt;code&gt;composer patch&lt;/code&gt; manually.&lt;/p&gt;

&lt;p&gt;However, there are still two issues, which is especially annoying if the site uses submodules, but would also apply if all code is committed to the project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;After one of &lt;code&gt;composer install&lt;/code&gt; or &lt;code&gt;composer update&lt;/code&gt;, the files are patches. So any subsequent install or update will find them modified, and attempt to preserve them or rollback, requiring many interactions&lt;/li&gt;
&lt;li&gt;The modified files are visible to git, which could invite us to commit them, which is probably not desired.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Third step: cleaning up
&lt;/h4&gt;

&lt;p&gt;So we can just add an automatic cleanup &lt;em&gt;before&lt;/em&gt; the install/update commands, so that our patch command, which runs &lt;em&gt;after&lt;/em&gt; these tasks, will find the git checkout pristine&lt;/p&gt;

&lt;p&gt;For projects committing contrib dependencies, a simple &lt;code&gt;git reset --hard&lt;/code&gt; is all it takes, but that will not work with submodules, so we need to be a bit smarter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...snip...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"patch"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"cd www/sites/all/modules/contrib/gmap; curl https://www.drupal.org/files/issues/2020-03-06/3118279-3.patch | patch -p1"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"subclean"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"git submodule update --init -f"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"pre-install-cmd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"@subclean"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"pre-update-cmd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"@subclean"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"post-install-cmd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"@patch"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"post-update-cmd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"@patch"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...snip...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This time we define a &lt;code&gt;composer subclean&lt;/code&gt; command to clean up submodules, and we register it to run before both install and update.&lt;/p&gt;

&lt;p&gt;Now, we can run &lt;code&gt;composer install&lt;/code&gt; and &lt;code&gt;composer update&lt;/code&gt; multiple times, and find the project clean everytime.&lt;/p&gt;

&lt;p&gt;Finally, come commit time, we can just run &lt;code&gt;composer subclean&lt;/code&gt; before committing, or even as a git pre-commit hook, and the patch-induced changes in our contributions will be reset, at no risk of getting committed.&lt;/p&gt;

</description>
      <category>drupal</category>
      <category>composer</category>
      <category>legacy</category>
    </item>
    <item>
      <title>Gérer les erreurs en Go 1.14+</title>
      <dc:creator>Frédéric G. MARAND</dc:creator>
      <pubDate>Thu, 27 Feb 2020 07:33:23 +0000</pubDate>
      <link>https://dev.to/fgm/gerer-les-erreurs-en-go-114-200i</link>
      <guid>https://dev.to/fgm/gerer-les-erreurs-en-go-114-200i</guid>
      <description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.riff.org/topic/computing/golang"&gt;Google Go = Golang&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.riff.org/taxonomy/term/245"&gt;Golang Paris&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;La gestion des erreurs a été beaucoup enrichie en Go 1.13 et ses améliorations ont commencé à être appliquées en Go 1.14.&lt;/p&gt;

&lt;p&gt;Cette présentation, donnée au meetup Golang Paris chez Deezer le 26/02/2020 présente les mécanismes standard &lt;code&gt;error&lt;/code&gt;, les tentatives d'évolution &lt;code&gt;check / handle&lt;/code&gt; et &lt;code&gt;try / defer&lt;/code&gt;, et le mécanisme d'&lt;em&gt;error wrapping&lt;/em&gt; finalement validé depuis Go 1.13.&lt;/p&gt;


&lt;div class="ltag_speakerdeck"&gt;
  &lt;iframe height="463" id="talk_frame_ca1b83e7e72240a39b2748b029235f0b" src="//speakerdeck.com/player/ca1b83e7e72240a39b2748b029235f0b" width="710"&gt;&lt;/iframe&gt;
&lt;/div&gt;


</description>
      <category>go</category>
      <category>errors</category>
      <category>exceptions</category>
    </item>
    <item>
      <title>Showcase: Migrating FranceTVSport.fr to Drupal 8 and Symfony 4</title>
      <dc:creator>Frédéric G. MARAND</dc:creator>
      <pubDate>Mon, 18 Mar 2019 13:03:18 +0000</pubDate>
      <link>https://dev.to/fgm/showcase-migrating-francetvsportfr-to-drupal-8-and-symfony-4-faa</link>
      <guid>https://dev.to/fgm/showcase-migrating-francetvsportfr-to-drupal-8-and-symfony-4-faa</guid>
      <description>&lt;p&gt;&lt;a href="https://blog.riff.org/topic/computing/php_0"&gt;PHP&lt;/a&gt; | &lt;a href="https://blog.riff.org/topic/computing/grokking_drupal"&gt;Grokking Drupal&lt;/a&gt; | &lt;a href="https://blog.riff.org/topic/computing/php/symfony2"&gt;Symfony&lt;/a&gt; | &lt;a href="https://blog.riff.org/tags/drupal8"&gt;DRUPAL-8&lt;/a&gt; | &lt;a href="https://blog.riff.org/tags/symfony"&gt;Symfony&lt;/a&gt; | &lt;a href="https://blog.riff.org/taxonomy/term/243"&gt;DrupalCamp&lt;/a&gt; | &lt;a href="https://blog.riff.org/taxonomy/term/244"&gt;Showcase&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The opening talk as &lt;a href="https://paris2019.drupal.fr/"&gt;DrupalCamp Paris 2019&lt;/a&gt; was a presentation given by Thomas Jolliet (FranceTV) and yours truly about how we rebuilt &lt;a href="https://sport.francetvinfo.fr/"&gt;FranceTV Sport&lt;/a&gt; to a Symfony 4 / headless Drupal 8 combo.&lt;/p&gt;

&lt;p&gt;The most salient points of the talk are probably the "defense in depth" mechanisms we built for scalability and fault tolerance, and the business results, like -85% full page load time, -65% &lt;a href="https://docs.webpagetest.org/metrics/speedindex/"&gt;speed index&lt;/a&gt;, or +50% iOS app traffic.&lt;/p&gt;


&lt;div class="ltag_speakerdeck"&gt;
  &lt;iframe height="463" id="talk_frame_8be5e630ce5f480986369fad3c1a180f" src="//speakerdeck.com/player/8be5e630ce5f480986369fad3c1a180f" width="710"&gt;&lt;/iframe&gt;
&lt;/div&gt;


</description>
      <category>drupal</category>
      <category>rabbitmq</category>
      <category>varnish</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Go internals unofficial wiki</title>
      <dc:creator>Frédéric G. MARAND</dc:creator>
      <pubDate>Mon, 04 Mar 2019 11:09:22 +0000</pubDate>
      <link>https://dev.to/fgm/go-internals-unofficial-wiki-1jhi</link>
      <guid>https://dev.to/fgm/go-internals-unofficial-wiki-1jhi</guid>
      <description>&lt;p&gt;&lt;a href="https://blog.riff.org/topic/computing/golang"&gt;Google Go = Golang&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The "Go internals unofficial wiki" on goin.wikispot.org used to be a valuable resource for developers interesting in the internal operation of the Go runtime, but disappeared when wikispot.org went down in 04/2014.&lt;/p&gt;

&lt;p&gt;I spent a couple of hours this morning to restore and reformat its contents to the &lt;a href="https://wiki.audean.com/go/internals"&gt;Golang section on the Audean wiki&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gww8NVor--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/bxf89w7cdlkwavvs19dd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gww8NVor--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/bxf89w7cdlkwavvs19dd.png" alt="Table of contents of the Go internals wiki"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enjoy... but responsibly : its content was fresh in 2014, not last week...&lt;/p&gt;

</description>
      <category>go</category>
      <category>wiki</category>
      <category>internals</category>
    </item>
    <item>
      <title>GoLand tip of the day: when Make run configurations don't find go</title>
      <dc:creator>Frédéric G. MARAND</dc:creator>
      <pubDate>Fri, 12 Oct 2018 11:31:06 +0000</pubDate>
      <link>https://dev.to/fgm/goland-tip-of-the-day-when-make-run-configurations-dont-find-go-5a22</link>
      <guid>https://dev.to/fgm/goland-tip-of-the-day-when-make-run-configurations-dont-find-go-5a22</guid>
      <description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.riff.org/topic/computing"&gt;Computing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.riff.org/topic/computing/golang"&gt;Google Go = Golang&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.riff.org/taxonomy/term/242"&gt;Goland&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The problem
&lt;/h3&gt;

&lt;p&gt;In a GoLand 2018.3 EAP run configuration, a Makefile run configuration finds the &lt;code&gt;go&lt;/code&gt; binary on macOS, but not on Ubuntu, causing make targets like this one to fail:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Makefile
client/test.wasm: client/main.go  # Building WASM
        GOARCH=wasm GOOS=js go build -o client/test.wasm client/main.go

$ /usr/bin/make -f (some edited path)/Makefile
client/test.wasm/bin/sh: 1: go: not found
make: *** [client/test.wasm] Error 127
$
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple enough to fix...&lt;/p&gt;

&lt;h3&gt;
  
  
  The diagnostic
&lt;/h3&gt;

&lt;p&gt;On the command line, the same &lt;code&gt;GOARCH=wasm GOOS=js go build -o client/test.wasm client/main.go&lt;/code&gt; line works normally. Looks like a path issue in Goland or the plugin. Checking in the Makefile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Makefile
client/test.wasm: client/main.go    
        # "${PATH}" 
        # Building WASM 
        GOARCH=wasm GOOS=js go build -o client/test.wasm client/main.go

$ # Building WASM
make: *** [client/test.wasm] Error 127# "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin"
$
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So indeed, on at least this version, the PATH is not taken into account. Let's fix this.&lt;/p&gt;

&lt;h3&gt;
  
  
  The solution
&lt;/h3&gt;

&lt;p&gt;Of course, one could just add the Go bin path to the tasks in these targets, but this is uncalled for on other environments, so we can just remind GoLand to add this path to the run configuration.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Edit the Run configuration&lt;/li&gt;
&lt;li&gt;Edit the &lt;code&gt;Environment variables&lt;/code&gt; field&lt;/li&gt;
&lt;li&gt;Add a definition for the &lt;code&gt;PATH&lt;/code&gt; variable taken from an &lt;code&gt;echo $PATH&lt;/code&gt; on the command line&lt;/li&gt;
&lt;li&gt;Apply and close&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Oddities
&lt;/h3&gt;

&lt;p&gt;As usual, Make has its own peculiar charm, requiring the variable name to use the braced format shown above instead of a plain &lt;code&gt;$PATH&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Trying to extend the PATH variable by just adding something like &lt;code&gt;$PATH:/usr/local/go/bin&lt;/code&gt; or &lt;code&gt;${PATH}:/usr/local/go/bin&lt;/code&gt; won't work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;in the first case, Make will receive the result of evaluation &lt;code&gt;$P&lt;/code&gt;, then the &lt;code&gt;ATH&lt;/code&gt; string, so other binaries beyond the ones in &lt;code&gt;/usr/local/go/bin&lt;/code&gt; will be missing&lt;/li&gt;
&lt;li&gt;in the second case, Make detects a variable referencing itself and aborts the task&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>make</category>
      <category>makefile</category>
      <category>go</category>
      <category>goland</category>
    </item>
    <item>
      <title>Tip of the day: how to compare Guitar Pro files</title>
      <dc:creator>Frédéric G. MARAND</dc:creator>
      <pubDate>Sun, 07 Oct 2018 09:21:56 +0000</pubDate>
      <link>https://dev.to/fgm/tip-of-the-day-how-to-compare-guitar-pro-files-474k</link>
      <guid>https://dev.to/fgm/tip-of-the-day-how-to-compare-guitar-pro-files-474k</guid>
      <description>&lt;p&gt;&lt;a href="https://blog.riff.org/topic/music"&gt;Music&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.riff.org/taxonomy/term/240"&gt;GuitarPro&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.riff.org/taxonomy/term/241"&gt;GP7&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.riff.org/tags/xml"&gt;XML&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;When working on compositions in a multi-member band (currently 5 in &lt;a href="https://www.facebook.com/AnotherDay78"&gt;AnotherDay&lt;/a&gt;), each member tends to create their own Guitar Pro files to avoid overwriting the previous versions created by other band members. And &lt;code&gt;.gp&lt;/code&gt; files tend to accumulate for the same song. At which point I start to wonder: "I know there's this riff in one of the versions, but which one ?" or "Are these two files really different or could I just merge them by editing a few notes, or remove one altogether ?"&lt;/p&gt;

&lt;p&gt;The problem, of course, is that &lt;a href="https://www.guitar-pro.com/en/index.php?pg=guitar-pro"&gt;Guitar Pro&lt;/a&gt;, even in version 7.5, has no builtin file comparison tool. How can one compare these files ?&lt;/p&gt;

&lt;h2&gt;
  
  
  Diagnostic
&lt;/h2&gt;

&lt;p&gt;If GP7 doesn't have a buitin solution, how about comparing the files themselves ? Problem: the file format is not documented. But a &lt;code&gt;file score.gp&lt;/code&gt; command returns &lt;code&gt;Zip archive data, at least v2.0 to extract&lt;/code&gt;. So let's unzip the file to see what it looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ unzip score.gp
Archive:  score.gp   
creating: Content/  
  inflating: Content/BinaryStylesheet
  inflating: Content/LayoutConfiguration
  inflating: Content/PartConfiguration
  inflating: Content/Preferences.json  
  inflating: Content/score.gpif
  inflating: VERSION
$ cat VERSION
7.0
$ cd Content
$ file *
BinaryStylesheet:    data
LayoutConfiguration: X11 SNF font data, MSB
firstPartConfiguration:   data
Preferences.json:    ASCII text, with no line terminators
score.gpif:          XML 1.0 document text, UTF-8 Unicode text, with very long lines$`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A quick look at the content of the files confirms that the actual score data is contained in the &lt;code&gt;score.gpif&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ tidy -q -xml -indent score.gpif | head -20  
&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;GPIF&amp;gt;
  &amp;lt;GPVersion&amp;gt;7&amp;lt;/GPVersion&amp;gt;
  &amp;lt;GPRevision required="12021" recommended="12023"&amp;gt;
  12024&amp;lt;/GPRevision&amp;gt;
  &amp;lt;Encoding&amp;gt;
    &amp;lt;EncodingDescription&amp;gt;GP7&amp;lt;/EncodingDescription&amp;gt;
  &amp;lt;/Encoding&amp;gt;
  &amp;lt;Score&amp;gt;
    &amp;lt;Title&amp;gt;
      &amp;lt;![CDATA[]]&amp;gt;
&amp;lt;/Title&amp;gt;
    &amp;lt;SubTitle&amp;gt;
      &amp;lt;![CDATA[]]&amp;gt;
&amp;lt;/SubTitle&amp;gt;
    &amp;lt;Artist&amp;gt;
      &amp;lt;![CDATA[]]&amp;gt;
&amp;lt;/Artist&amp;gt;
    &amp;lt;Album&amp;gt;
      &amp;lt;![CDATA[]]&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahah... so it's an XML document with a &lt;code&gt;GPIF&lt;/code&gt; top-level element. A quick search with that keyword lands us on a file called "The Guitarpro 7 (".GP") file format" by the &lt;a href="https://musescore.org/"&gt;MuseScore&lt;/a&gt; developers, currently available at &lt;a href="https://musescore.org/sites/musescore.org/files/2017-08/the_guitarpro_7_file%20format.doc"&gt;https://musescore.org/sites/musescore.org/files/2017-08/the_guitarpro_7_file%20format.doc&lt;/a&gt;. And its content allows one to understand the contents of these scores. I bet it would even come in handy to manually edit/repair a file corrupted by the frequent crashes of Guitar Pro.&lt;/p&gt;

&lt;p&gt;But that's not the goal for today, we can now compare these scores more or less easily.&lt;/p&gt;

&lt;h2&gt;
  
  
  The solutions
&lt;/h2&gt;

&lt;p&gt;First solution is to use the process described above and compare the &lt;code&gt;score.gpif&lt;/code&gt; files using your &lt;a href="http://meldmerge.org/"&gt;favorite text comparison software&lt;/a&gt;. Works well, but can we do it with less command-line manipulation ?&lt;/p&gt;

&lt;p&gt;Turns out, most of the process can be replicated in Guitar Pro itself, by using the new (?) MusicXML export: just navigate to &lt;code&gt;File&lt;/code&gt; / &lt;code&gt;Export&lt;/code&gt; / &lt;code&gt;MusicXML...&lt;/code&gt; to export the scores to compare, and you directly get a pair of XML files which you can directly compare in your visual text comparison tool. Problem solved.&lt;/p&gt;

</description>
      <category>music</category>
      <category>guitar</category>
      <category>guitarpro</category>
      <category>xml</category>
    </item>
    <item>
      <title>Munin plugins for Beanstalkd in PHP are now 1.0.0</title>
      <dc:creator>Frédéric G. MARAND</dc:creator>
      <pubDate>Sun, 12 Aug 2018 19:16:07 +0000</pubDate>
      <link>https://dev.to/fgm/munin-plugins-for-beanstalkd-in-php-are-now-1-0-0-1n0e</link>
      <guid>https://dev.to/fgm/munin-plugins-for-beanstalkd-in-php-are-now-1-0-0-1n0e</guid>
      <description>&lt;p&gt;In 2014, I created a PHP version of the &lt;a href="https://github.com/fgm/beanstalk-munin-php"&gt;Munin plugins for Beanstalkd&lt;/a&gt; introduced by AirBnB, but originally created in Python.&lt;/p&gt;

&lt;p&gt;Fast forward four years, and after being adapted for compliance with the PHP-FIG PSR1, PSR2 and PSR12 standards, as well as the Zend coding standards, and with extra documentation, I published the first "stable" version 1.0.0 of the package today under the Apache APL-2.0 license.&lt;/p&gt;

&lt;p&gt;To use it and ensure observability of your &lt;a href="http://kr.github.io/beanstalkd/"&gt;favorite job queue&lt;/a&gt;, follow the instructions in the INSTALL.md file. In short, it's just 3 steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;clone the repository&lt;/li&gt;
&lt;li&gt;install its dependencies with &lt;code&gt;composer install&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;symlink the plugins to &lt;code&gt;/etc/munin/plugins&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it, you can now plot command rate, connections, jobs rate, age in queue, queue size by type, and timeouts frequency.&lt;/p&gt;

&lt;p&gt;Blog tags:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://blog.riff.org/topic/computing/php_0"&gt;PHP&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.riff.org/taxonomy/term/238"&gt;munin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.riff.org/taxonomy/term/239"&gt;observability&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.riff.org/tags/phpfig"&gt;php-fig&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>php</category>
      <category>munin</category>
      <category>observability</category>
      <category>beanstalkd</category>
    </item>
    <item>
      <title>Lighthouse 3.0 is out: Drupal 8.5 has killer performance</title>
      <dc:creator>Frédéric G. MARAND</dc:creator>
      <pubDate>Sun, 05 Aug 2018 16:08:11 +0000</pubDate>
      <link>https://dev.to/fgm/lighthouse-3-0-is-out-drupal-8-5-has-killer-performance-3gl7</link>
      <guid>https://dev.to/fgm/lighthouse-3-0-is-out-drupal-8-5-has-killer-performance-3gl7</guid>
      <description>&lt;p&gt;Lighthouse 3.0 is out: Drupal 8.5 has killer performanceFrederic MarandSun, 2018-08-05 18:08&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.riff.org/topic/computing"&gt;Computing&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.riff.org/tags/drupal8"&gt;DRUPAL-8&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.riff.org/tags/performance"&gt;performance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.riff.org/tags/chrome"&gt;chrome&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you may have noticed if you are a regular here, I just refreshed the theme on this site to a custom theme built on Bartik. And since Chrome had just been updated, I took the newly updated performance audit.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UpqlX-_5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.riff.org/sites/default/files/2018-08/Drupal8-Lighthouse3-100.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UpqlX-_5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.riff.org/sites/default/files/2018-08/Drupal8-Lighthouse3-100.png" alt="Screenshot of a 100% score on Lighthouse 3.0 by Drupal 8.5"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What more to say ?&lt;/p&gt;

</description>
      <category>drupal</category>
      <category>webperf</category>
      <category>lighthouse</category>
    </item>
    <item>
      <title>How to debug Drupal 8 Functional tests with XDebug</title>
      <dc:creator>Frédéric G. MARAND</dc:creator>
      <pubDate>Sun, 29 Jul 2018 19:12:18 +0000</pubDate>
      <link>https://dev.to/fgm/how-to-debug-drupal-8-functional-tests-with-xdebug-578k</link>
      <guid>https://dev.to/fgm/how-to-debug-drupal-8-functional-tests-with-xdebug-578k</guid>
      <description>&lt;p&gt;How to debug Drupal 8 Functional tests with XDebug&lt;/p&gt;

&lt;h3&gt;
  
  
  The problem
&lt;/h3&gt;

&lt;p&gt;While converting the old-style functional tests in the &lt;a href="https://drupal.org/project/mongodb"&gt;MongoDB project&lt;/a&gt; from &lt;code&gt;WebTestBase&lt;/code&gt; to &lt;code&gt;BrowserTestBase&lt;/code&gt;, I stumbled upon a problem: after following the drupal.org instructions to &lt;a href="https://www.drupal.org/docs/8/phpunit/running-phpunit-tests-within-phpstorm"&gt;run PHPunit tests from PhpStorm&lt;/a&gt;, doing step-by-step debugging in the IDE worked nicely, but then stopped at the first &lt;code&gt;$this-&amp;gt;drupalLogin();&lt;/code&gt; call, returning a 404 after a very long delay, although the same call running without debugging worked normally. What could be going on ?&lt;/p&gt;

&lt;h3&gt;
  
  
  The diagnostic
&lt;/h3&gt;

&lt;p&gt;Stepping into &lt;code&gt;UiHelperTrait::drupalLogin()&lt;/code&gt;, I noticed the delay occurent during the &lt;code&gt;drupalGet('user/login')&lt;/code&gt; call early in the method, before submitting the account identification. Could it be the issue ?&lt;/p&gt;

&lt;p&gt;Indeed, evaluating the result of the call via &lt;code&gt;$this-&amp;gt;getSession()-&amp;gt;getStatusCode();&lt;/code&gt; after that call returned show a 504 Timeout HTTP status code. And indeed, dumping the page with &lt;code&gt;$this-&amp;gt;getSession()-&amp;gt;getPage()-&amp;gt;getContent()&lt;/code&gt; show it to contain a typically timeout page.&lt;/p&gt;

&lt;p&gt;Examining the logs showed the timeout happened at the PHP level, during the opposite direction call performed by Xdebug towards the debugging client, although such calls obviously worked since I'd been stepping through code for hours before that.&lt;/p&gt;

&lt;h3&gt;
  
  
  The solution
&lt;/h3&gt;

&lt;p&gt;The solution was suggested by the always helpful and knowledgeable &lt;a href="https://www.drupal.org/u/berdir"&gt;@berdir&lt;/a&gt; : PhpStorm happens to set a limit to the number of simultaneous connections it will accept for debugging, and that limit is 1 by default.&lt;/p&gt;

&lt;p&gt;All of a sudden, it made sense: during classical debugging, the PHP interpreter from the host site establishes one connection to the client (the PhpStorm IDE), but when invoking the child site during such a call, a second instance of the interpreter is started and tries to connect too... but is blocked by the single connection limit of the default configuration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zGBtotM3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.riff.org/sites/default/files/inline-images/phpstorm-xdebug-connections_0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zGBtotM3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.riff.org/sites/default/files/inline-images/phpstorm-xdebug-connections_0.png" alt="Screenshot from the XDebug preferences in PhpStorm 2018.1.2" width="880" height="443"&gt;&lt;/a&gt; So all it takes is increase the number of connections!&lt;/p&gt;

&lt;p&gt;In PhpStorm 2018 and 2019 macOS, the settings can be found at &lt;em&gt;PhpStorm / Preferences / Languages &amp;amp; Frameworks / PHP / Debug&lt;/em&gt; in the &lt;code&gt;External connections&lt;/code&gt; part of the right pane, as shown below.&lt;/p&gt;

&lt;p&gt;No need to restart the IDE or PHP, just restart the debugging run configuration, and it works beautifully.&lt;/p&gt;

</description>
      <category>xdebug</category>
      <category>phpstorm</category>
      <category>phpunit</category>
      <category>drupal</category>
    </item>
  </channel>
</rss>
