Learning Go – Day 8

Featured image by Egon Elbre

Implementing the Stringer interface

The standard library defines the Stringer interface that is used to return a string.

type Stringer interface {
	String() string
}
  • Implement the Stringer interface on your custom types
type Person struct {
	Name string
}

// Implementation for Stringer
func (p Person) String() string {
	return "My name is " + p.Name
}

// Your type can now be passed to function that accept Stringer based types
fmt.Print(person1)

Launching other command line applications

For example using exec.Command() you could build the app during a unit-test and run it.

import (
	"os"
	"os/exec"
)

app := exec.Command("go", "build", "-o", "myapp")
if err := app.Run(); err != nil {
	fmt.Fprintf(os.Stderr, "Building tool myapp failed with error: %s", err)
	os.Exit(42)
}
  • You can bind Stderr to be outputted into Stdout before running the command.
cmd := exec.Command("ls", "-la")
out, err := cmd.CombinedOutput()
// Convert out to a string for processing
outString = string(out)
  • You can get access to the command’s Stdin pipe and write to it.
cmdStdIn, err := cmd.StdinPipe()

io.WriteString(cmdStdIn, "Input to be passed to stdin of the process")
cmdStdIn.Close()

if err := cmd.Run(); err != nil {
}
  • You can redirect the Stdout or Stderr output to any io.Writer.
cmd := exec.Command("ls", "-la")
cmd.Stdout = &someOtherIOWriter
cmd.Run()
  • Change the working directory the command executes in with cmd.Dir = somePath.
  • Set environment variables for the command by setting cmd.Env which is defined as Env []string. Each string is “key=value”.
  • To see if a specific executable can be found in the $PATH variable, use exec.LookPath().
path, err := exec.LookPath("git")
if err != nil {
	log.Fatal("git need to be installed")
}
fmt.Printf("git was found at %s\n", path)
  • NOTE: There is this package called context which among many other things can also be used in combination with exec to execute commands with a timeout or to allow to be cancelled etc. See this for a general guide on how to use context.

Miscellaneous

  • Can track date time using the time package and the time.Time type.
  • To get the current date time, use time.Now() method.
  • Recall you can return error type from your functions/methods and use fmt.Errorf to return a string based error message.
  • You can use the errors package to check for OS errors.
import "errors"

if errors.Is(err, os.ErrNotExist) {
...
}
  • The package ioutil has been deprecated from Go 1.16. It is replaced with io and os
  • You can remove files using os.Remove().
  • Get the current working directory with os.Getwd().
  • You can read an environment variable using os.Getenv().
  • You can join strings together using strings.Join(elems []string, sep string) string.
  • You can declare a multiline string using the backticks `
const multiline = `This is
a multiline
string in golang
`
  • To get just the filename from a path.
import "path/filepath"

fmt.Println(filepath.Base("test.txt")) // test.txt
fmt.Println(filepath.Base("a/b/c/test.txt")) // test.txt
  • You can build up a buffer and then create a []byte (slice of bytes) using bytes.Buffer
func makeBytes() []byte {
	var buffer bytes.Buffer

	buffer.WriteString("The quick brown fox ")
	buffer.WriteString("jumped over the lazy dog")

	return buffer.Bytes()
}

fmt.Println(makeBytes())
// [84 104 101 32 113 117 105 99 107 32 98 114 111 119 ...
fmt.Println(string(makeBytes()))
// The quick brown fox jumped over the lazy dog

Reference to external packages