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
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
Don’t care; same issues as JSON.
Enough! Today was rough. Next: time.