August 22nd, 2024 08:17 UTC · 2 months ago

Golang

Relearning Go: Day 9

String Functions & String Formatting to XML

String Functions & String Formatting

gobyexample.com/string-functions
gobyexample.com/string-formatting

All looks useful and covers most bases. It’s nice that there are a variety of ways to format values, e.g. %v, %+v, %#v. Also to print out the type name.

If I get the format string wrong, it still compiles and runs, and prints out something that tells me about the error:

fmt.Printf("pointer: %p\n", 123) // prints "pointer: %!p(int=123)"

The only indication of a problem ahead of time comes if I run go vet – which the Go Playground does automatically:

./prog.go:74:2: fmt.Printf format %p has arg 123 of wrong type int

But sometimes go vet can’t help either, because p could be anything:

var p interface{} = 123 // i.e. not a pointer.
fmt.Printf("pointer: %p\n", p)

It’s odd that it takes a separate tool to find a type error. In addition, fmt.Printf is doing all its work at run-time, even though (almost) all type information is available to the compiler. Parsing the format string and validating arguments could have been done once, at compile time, with code paths already selected, e.g. through code generation. Printing a pointer, for example, might hypothetically expand to:

fmt.Print(
    "pointer: ",
    fmt.PrintPointer(p),
    "\n",
)

which would not compile unless p is a pointer. This would prevent bugs from compiling and improve performance.

That said, it would slow down compilation, and fast compilation is valued by Go developers. But if the compiler isn’t catching type errors, and tools like go vet need to be run as well (and which might not catch type errors either), are we not being fooled?

Text Templates

gobyexample.com/text-templates

I’ve seen these before, in the Docker CLI for example:

$ docker inspect --help

Usage:  docker inspect [OPTIONS] NAME|ID [NAME|ID...]

Return low-level information on Docker objects

Options:
  -f, --format string   Format output using a custom template:
                        'json':             Print in JSON format
                        'TEMPLATE':         Print output using the given Go template.
                        Refer to https://docs.docker.com/go/formatting/ for more information about formatting output with templates
  -s, --size            Display total file sizes if the type is container
      --type string     Return JSON for specified type

They’re fine, and the expression syntax is constrained enough that they can be readily implemented in other languages, but they’re also Yet Another Template Syntax.

Regular Expressions

gobyexample.com/regular-expressions

Useful to have regexp.MustCompile for global regular expressions – but it still gets checked at run-time. Even better would be for some compile-time checks.

JSON

gobyexample.com/json

Years ago I thought that this was one of the ugliest parts of Go, and it’s disappointing to see that nothing has changed.

type response2 struct {
    Page   int      `json:"page"`
    Fruits []string `json:"fruits"`
}

Magic strings/comments, again with no compile-time support, only some help from go vet.

What if I want to add support for a new encoding? Can I use those magic strings too? Do I have to write my own version of go vet so I can prevent wholly preventable bugs at ~compile-time as long as I remember to run it?

XML

gobyexample.com/xml

Don’t care; same issues as JSON.


Enough! Today was rough. Next: time.