2020-11-26 14:27:42 +01:00
|
|
|
# Notation - print Go objects
|
2020-11-23 15:42:05 +01:00
|
|
|
|
2020-11-26 18:05:14 +01:00
|
|
|
[](https://goreportcard.com/report/github.com/aryszka/notation)
|
2020-11-26 17:17:27 +01:00
|
|
|
[](https://codecov.io/gh/aryszka/notation)
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
This package can be used to print (or sprint) Go objects for debugging purposes, with optional wrapping
|
|
|
|
(indentation) and optional type information.
|
2020-11-23 15:42:05 +01:00
|
|
|
|
|
|
|
### Alternatives
|
|
|
|
|
|
|
|
Notation is similar to the following great, more established and mature packages:
|
|
|
|
|
|
|
|
- [go-spew](https://github.com/davecgh/go-spew/)
|
|
|
|
- [litter](https://github.com/sanity-io/litter)
|
|
|
|
- [utter](https://github.com/kortschak/utter)
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
Notation differs from these primarily in the 'flavor' of printing and the package interface.
|
2020-11-23 15:42:05 +01:00
|
|
|
|
|
|
|
### Installation
|
|
|
|
|
|
|
|
`go get github.com/aryszka/notation`
|
|
|
|
|
|
|
|
### Usage
|
|
|
|
|
|
|
|
Pass in the Go object(s) to be printed to one of the notation functions. These functions can be categorized into
|
|
|
|
four groups:
|
|
|
|
|
|
|
|
- **Println:** the Println type functions print Go objects to stderr with an additional newline at the end.
|
|
|
|
- **Print:** similar to Println but without the extra newline.
|
|
|
|
- **Fprint:** the Fprint type functions print Go objects to an arbitrary writer passed in as an argument.
|
|
|
|
- **Sprint:** the Sprint type functions return the string representation of Go objects instead of printing them.
|
|
|
|
|
|
|
|
The format and the verbosity can be controlled with the suffixed variants of the above functions. By default,
|
|
|
|
the input arguments are printed without types on a single line. The following suffixes are available:
|
|
|
|
|
|
|
|
- **`w`**: wrap the output based on Go-style indentation
|
|
|
|
- **`t`**: print moderately verbose type information, omitting where it can be trivially inferred
|
|
|
|
- **`v`**: print verbose type information
|
|
|
|
|
|
|
|
When **`t`** or **`v`** are used together with **`w`**, they must follow **`w`**. The suffixes **`t`** and
|
|
|
|
**`v`** cannot be used together.
|
|
|
|
|
|
|
|
Wrapping is **not eager**. It doesn't wrap a line when it can fit on 72 columns. It also tolerates longer lines up
|
|
|
|
to 112 columns, when the output is considered to be more readable that way. This means very simple Go objects
|
|
|
|
are not wrapped even with the **`w`** variant of the functions.
|
|
|
|
|
|
|
|
For the available functions, see also the [godoc](https://godoc.org/github.com/aryszka/notation).
|
2020-11-26 17:14:45 +01:00
|
|
|
(Alternatively: [pkg.go.dev](https://pkg.go.dev/github.com/aryszka/notation).)
|
2020-11-23 15:42:05 +01:00
|
|
|
|
|
|
|
### Example
|
|
|
|
|
|
|
|
Assuming to have the required types defined, if we do the following:
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
```
|
2020-11-23 15:42:05 +01:00
|
|
|
b := bike{
|
|
|
|
frame: frame{
|
|
|
|
fork: fork{},
|
|
|
|
saddlePost: saddlePost{},
|
|
|
|
},
|
|
|
|
driveTrain: driveTrain{
|
|
|
|
bottomBracket: bracket{},
|
|
|
|
crank: crank{wheels: 2},
|
|
|
|
brakes: []brake{{discSize: 160}, {discSize: 140}},
|
|
|
|
derailleurs: []derailleur{{gears: 2}, {gears: 11}},
|
|
|
|
cassette: cassette{wheels: 11},
|
|
|
|
chain: chain{},
|
|
|
|
levers: []lever{{true}, {true}},
|
|
|
|
},
|
2020-11-30 15:48:13 +01:00
|
|
|
wheels: []wheel{{size: 700}, {size: 700}},
|
2020-11-23 15:42:05 +01:00
|
|
|
handlebar: handlebar{},
|
|
|
|
saddle: saddle{},
|
|
|
|
}
|
|
|
|
|
|
|
|
b.frame.fork.wheel = &b.wheels[0]
|
|
|
|
b.frame.fork.handlebar = &b.handlebar
|
|
|
|
b.frame.fork.handlebar.levers = []*lever{&b.driveTrain.levers[0], &b.driveTrain.levers[1]}
|
|
|
|
b.frame.fork.frontBrake = &b.driveTrain.brakes[0]
|
|
|
|
b.frame.saddlePost.saddle = &b.saddle
|
|
|
|
b.frame.bottomBracket = &b.driveTrain.bottomBracket
|
|
|
|
b.frame.frontDerailleur = &b.driveTrain.derailleurs[0]
|
|
|
|
b.frame.rearDerailleur = &b.driveTrain.derailleurs[1]
|
|
|
|
b.frame.rearBrake = &b.driveTrain.brakes[1]
|
|
|
|
b.frame.rearWheel = &b.wheels[1]
|
|
|
|
b.frame.bottomBracket.crank = &b.driveTrain.crank
|
|
|
|
b.frame.bottomBracket.crank.chain = &b.driveTrain.chain
|
|
|
|
b.frame.rearWheel.cassette = &b.driveTrain.cassette
|
|
|
|
b.frame.rearWheel.cassette.chain = &b.driveTrain.chain
|
|
|
|
|
|
|
|
s := notation.Sprintw(b)
|
|
|
|
```
|
|
|
|
|
|
|
|
We get the following string:
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
```
|
2020-11-23 15:42:05 +01:00
|
|
|
{
|
|
|
|
frame: {
|
|
|
|
fork: {
|
2020-11-30 15:48:13 +01:00
|
|
|
wheel: {size: 700, cassette: nil},
|
2020-11-26 14:27:42 +01:00
|
|
|
handlebar: {
|
|
|
|
levers: []{
|
|
|
|
{withShift: true},
|
|
|
|
{withShift: true},
|
|
|
|
},
|
|
|
|
},
|
2020-11-23 15:42:05 +01:00
|
|
|
frontBrake: {discSize: 160},
|
|
|
|
},
|
|
|
|
saddlePost: {saddle: {}},
|
|
|
|
bottomBracket: {crank: {wheels: 2, chain: {}}},
|
|
|
|
frontDerailleur: {gears: 2},
|
|
|
|
rearDerailleur: {gears: 11},
|
|
|
|
rearBrake: {discSize: 140},
|
2020-11-30 15:48:13 +01:00
|
|
|
rearWheel: {
|
|
|
|
size: 700,
|
|
|
|
cassette: {wheels: 11, chain: {}},
|
|
|
|
},
|
2020-11-23 15:42:05 +01:00
|
|
|
},
|
|
|
|
driveTrain: {
|
|
|
|
bottomBracket: {crank: {wheels: 2, chain: {}}},
|
|
|
|
crank: {wheels: 2, chain: {}},
|
|
|
|
brakes: []{{discSize: 160}, {discSize: 140}},
|
|
|
|
derailleurs: []{{gears: 2}, {gears: 11}},
|
|
|
|
cassette: {wheels: 11, chain: {}},
|
|
|
|
chain: {},
|
|
|
|
levers: []{{withShift: true}, {withShift: true}},
|
|
|
|
},
|
2020-11-26 14:27:42 +01:00
|
|
|
wheels: []{
|
2020-11-30 15:48:13 +01:00
|
|
|
{size: 700, cassette: nil},
|
|
|
|
{size: 700, cassette: {wheels: 11, chain: {}}},
|
2020-11-26 14:27:42 +01:00
|
|
|
},
|
2020-11-23 15:42:05 +01:00
|
|
|
handlebar: {levers: []{{withShift: true}, {withShift: true}}},
|
|
|
|
saddle: {},
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Using `notation.Sprintwv` instead of `notation.Sprintw`, we would get the following string:
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
```
|
2020-11-23 15:42:05 +01:00
|
|
|
bike{
|
|
|
|
frame: frame{
|
|
|
|
fork: fork{
|
2020-11-26 14:27:42 +01:00
|
|
|
wheel: *wheel{
|
2020-11-30 15:48:13 +01:00
|
|
|
size: float64(700),
|
2020-11-26 14:27:42 +01:00
|
|
|
cassette: (*cassette)(nil),
|
|
|
|
},
|
2020-11-23 15:42:05 +01:00
|
|
|
handlebar: *handlebar{
|
|
|
|
levers: []*lever{
|
|
|
|
*lever{withShift: bool(true)},
|
|
|
|
*lever{withShift: bool(true)},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
frontBrake: *brake{discSize: float64(160)},
|
|
|
|
},
|
|
|
|
saddlePost: saddlePost{saddle: *saddle{}},
|
2020-11-26 14:27:42 +01:00
|
|
|
bottomBracket: *bracket{
|
|
|
|
crank: *crank{
|
|
|
|
wheels: int(2),
|
|
|
|
chain: *chain{},
|
|
|
|
},
|
|
|
|
},
|
2020-11-23 15:42:05 +01:00
|
|
|
frontDerailleur: *derailleur{gears: int(2)},
|
|
|
|
rearDerailleur: *derailleur{gears: int(11)},
|
|
|
|
rearBrake: *brake{discSize: float64(140)},
|
|
|
|
rearWheel: *wheel{
|
2020-11-30 15:48:13 +01:00
|
|
|
size: float64(700),
|
2020-11-26 14:27:42 +01:00
|
|
|
cassette: *cassette{
|
|
|
|
wheels: int(11),
|
|
|
|
chain: *chain{},
|
|
|
|
},
|
2020-11-23 15:42:05 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
driveTrain: driveTrain{
|
2020-11-26 14:27:42 +01:00
|
|
|
bottomBracket: bracket{
|
|
|
|
crank: *crank{
|
|
|
|
wheels: int(2),
|
|
|
|
chain: *chain{},
|
|
|
|
},
|
|
|
|
},
|
2020-11-23 15:42:05 +01:00
|
|
|
crank: crank{wheels: int(2), chain: *chain{}},
|
2020-11-26 14:27:42 +01:00
|
|
|
brakes: []brake{
|
|
|
|
brake{discSize: float64(160)},
|
|
|
|
brake{discSize: float64(140)},
|
|
|
|
},
|
2020-11-23 15:42:05 +01:00
|
|
|
derailleurs: []derailleur{
|
2020-11-26 14:27:42 +01:00
|
|
|
derailleur{
|
|
|
|
gears: int(2),
|
|
|
|
},
|
|
|
|
derailleur{
|
|
|
|
gears: int(11),
|
|
|
|
},
|
2020-11-23 15:42:05 +01:00
|
|
|
},
|
|
|
|
cassette: cassette{wheels: int(11), chain: *chain{}},
|
|
|
|
chain: chain{},
|
2020-11-26 14:27:42 +01:00
|
|
|
levers: []lever{
|
|
|
|
lever{withShift: bool(true)},
|
|
|
|
lever{withShift: bool(true)},
|
|
|
|
},
|
2020-11-23 15:42:05 +01:00
|
|
|
},
|
|
|
|
wheels: []wheel{
|
2020-11-30 15:48:13 +01:00
|
|
|
wheel{size: float64(700), cassette: (*cassette)(nil)},
|
2020-11-26 14:27:42 +01:00
|
|
|
wheel{
|
2020-11-30 15:48:13 +01:00
|
|
|
size: float64(700),
|
2020-11-26 14:27:42 +01:00
|
|
|
cassette: *cassette{wheels: int(11), chain: *chain{}},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
handlebar: handlebar{
|
|
|
|
levers: []*lever{
|
|
|
|
*lever{withShift: bool(true)},
|
|
|
|
*lever{withShift: bool(true)},
|
|
|
|
},
|
2020-11-23 15:42:05 +01:00
|
|
|
},
|
|
|
|
saddle: saddle{},
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
### Subtleties
|
|
|
|
|
|
|
|
Notation doesn't provide configuration options, we can just pick the preferred function and call it with the
|
|
|
|
objects to be printed. The following details describe some of the behavior to be expected in case of various
|
|
|
|
input objects.
|
|
|
|
|
|
|
|
##### Numbers
|
|
|
|
|
|
|
|
Numbers are printed based on the `fmt` package's default formatting. When printing with moderate type
|
2020-11-26 14:27:42 +01:00
|
|
|
information, the type for the `int`, default width signed integers, will be omitted.
|
2020-11-23 15:42:05 +01:00
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
```
|
2020-11-23 15:42:05 +01:00
|
|
|
i := 42
|
|
|
|
notation.Printlnt(i)
|
|
|
|
```
|
|
|
|
|
|
|
|
Output:
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
```
|
2020-11-23 15:42:05 +01:00
|
|
|
42
|
|
|
|
```
|
|
|
|
|
|
|
|
##### Strings
|
|
|
|
|
|
|
|
When printing strings, by default they are escaped using the `strconv.Quote` function. However, when wrapping
|
2020-11-26 14:27:42 +01:00
|
|
|
long strings, and the string contains a newline and doesn't contain a backquote, then the string is printed
|
|
|
|
as a raw string literal, delimited by backquotes.
|
2020-11-23 15:42:05 +01:00
|
|
|
|
|
|
|
Short string:
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
```
|
2020-11-23 15:42:05 +01:00
|
|
|
s := `foobar
|
|
|
|
baz`
|
|
|
|
notation.Printlnw(s)
|
|
|
|
```
|
|
|
|
|
|
|
|
Output:
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
```
|
2020-11-23 15:42:05 +01:00
|
|
|
"foobar\nbaz"
|
|
|
|
```
|
|
|
|
|
|
|
|
Long string:
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
```
|
2020-11-23 15:42:05 +01:00
|
|
|
s := `The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The
|
|
|
|
quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown
|
|
|
|
fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps
|
|
|
|
over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy
|
|
|
|
dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The
|
|
|
|
quick brown fox jumps over the lazy dog.`
|
|
|
|
|
2020-11-26 18:47:36 +01:00
|
|
|
notation.Printlnw(s)
|
2020-11-23 15:42:05 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
Output:
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
```
|
2020-11-23 15:42:05 +01:00
|
|
|
`The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The
|
|
|
|
quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown
|
|
|
|
fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps
|
|
|
|
over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy
|
|
|
|
dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The
|
|
|
|
quick brown fox jumps over the lazy dog.`
|
|
|
|
```
|
|
|
|
|
|
|
|
##### Arrays/Slices
|
|
|
|
|
|
|
|
Slices are are printed by printing their elements between braces, prefixed either by '[]' or the type of the
|
|
|
|
slice. Example:
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
```
|
2020-11-23 15:42:05 +01:00
|
|
|
l := []int{1, 2, 3}
|
|
|
|
notation.Println(l)
|
|
|
|
```
|
|
|
|
|
|
|
|
Output:
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
```
|
2020-11-23 15:42:05 +01:00
|
|
|
[]{1, 2, 3}
|
|
|
|
```
|
|
|
|
|
|
|
|
To differentiate arrays from slices, arrays are always prefixed with their type or square brackets containing
|
|
|
|
the length of the array:
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
```
|
2020-11-23 15:42:05 +01:00
|
|
|
a := [...]{1, 2, 3}
|
|
|
|
notation.Println(a)
|
|
|
|
```
|
|
|
|
|
|
|
|
Output:
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
```
|
2020-11-23 15:42:05 +01:00
|
|
|
[3]{1, 2, 3}
|
|
|
|
```
|
|
|
|
|
|
|
|
##### Bytes
|
|
|
|
|
|
|
|
When the type of a slice is `uint8`, or an alias of it, e.g. `byte`, then it is printed as []byte, with the hexa
|
|
|
|
representation of its bytes:
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
```
|
2020-11-23 15:42:05 +01:00
|
|
|
b := []byte(
|
2020-11-26 14:27:42 +01:00
|
|
|
`The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The
|
2020-11-23 15:42:05 +01:00
|
|
|
quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown
|
|
|
|
fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps
|
|
|
|
over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy
|
|
|
|
dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The
|
|
|
|
quick brown fox jumps over the lazy dog.`,
|
|
|
|
)
|
|
|
|
|
|
|
|
notation.Printlnwt(b)
|
|
|
|
```
|
|
|
|
|
|
|
|
Output:
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
```
|
2020-11-23 15:42:05 +01:00
|
|
|
[]byte{
|
|
|
|
54 68 65 20 71 75 69 63 6b 20 62 72 6f 77 6e 20 66 6f 78 20 6a
|
|
|
|
75 6d 70 73 20 6f 76 65 72 20 74 68 65 20 6c 61 7a 79 20 64 6f
|
|
|
|
67 2e 20 54 68 65 20 71 75 69 63 6b 20 62 72 6f 77 6e 20 66 6f
|
|
|
|
78 20 6a 75 6d 70 73 20 6f 76 65 72 20 74 68 65 20 6c 61 7a 79
|
|
|
|
20 64 6f 67 2e 20 54 68 65 0a 71 75 69 63 6b 20 62 72 6f 77 6e
|
|
|
|
20 66 6f 78 20 6a 75 6d 70 73 20 6f 76 65 72 20 74 68 65 20 6c
|
|
|
|
61 7a 79 20 64 6f 67 2e 20 54 68 65 20 71 75 69 63 6b 20 62 72
|
|
|
|
6f 77 6e 20 66 6f 78 20 6a 75 6d 70 73 20 6f 76 65 72 20 74 68
|
|
|
|
65 20 6c 61 7a 79 20 64 6f 67 2e 20 54 68 65 20 71 75 69 63 6b
|
|
|
|
20 62 72 6f 77 6e 0a 66 6f 78 20 6a 75 6d 70 73 20 6f 76 65 72
|
|
|
|
20 74 68 65 20 6c 61 7a 79 20 64 6f 67 2e 20 54 68 65 20 71 75
|
|
|
|
69 63 6b 20 62 72 6f 77 6e 20 66 6f 78 20 6a 75 6d 70 73 20 6f
|
|
|
|
76 65 72 20 74 68 65 20 6c 61 7a 79 20 64 6f 67 2e 20 54 68 65
|
|
|
|
20 71 75 69 63 6b 20 62 72 6f 77 6e 20 66 6f 78 20 6a 75 6d 70
|
|
|
|
73 0a 6f 76 65 72 20 74 68 65 20 6c 61 7a 79 20 64 6f 67 2e 20
|
|
|
|
54 68 65 20 71 75 69 63 6b 20 62 72 6f 77 6e 20 66 6f 78 20 6a
|
|
|
|
75 6d 70 73 20 6f 76 65 72 20 74 68 65 20 6c 61 7a 79 20 64 6f
|
|
|
|
67 2e 20 54 68 65 20 71 75 69 63 6b 20 62 72 6f 77 6e 20 66 6f
|
|
|
|
78 20 6a 75 6d 70 73 20 6f 76 65 72 20 74 68 65 20 6c 61 7a 79
|
|
|
|
0a 64 6f 67 2e 20 54 68 65 20 71 75 69 63 6b 20 62 72 6f 77 6e
|
|
|
|
20 66 6f 78 20 6a 75 6d 70 73 20 6f 76 65 72 20 74 68 65 20 6c
|
|
|
|
61 7a 79 20 64 6f 67 2e 20 54 68 65 20 71 75 69 63 6b 20 62 72
|
|
|
|
6f 77 6e 20 66 6f 78 20 6a 75 6d 70 73 20 6f 76 65 72 20 74 68
|
|
|
|
65 20 6c 61 7a 79 20 64 6f 67 2e 20 54 68 65 0a 71 75 69 63 6b
|
|
|
|
20 62 72 6f 77 6e 20 66 6f 78 20 6a 75 6d 70 73 20 6f 76 65 72
|
|
|
|
20 74 68 65 20 6c 61 7a 79 20 64 6f 67 2e
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
##### Maps
|
|
|
|
|
|
|
|
Maps are printed with their entries sorted by the string representation of their keys:
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
```
|
2020-11-23 15:42:05 +01:00
|
|
|
m := map[string]int{"b": 1, "c": 2, "a": 3}
|
|
|
|
notation.Println(m)
|
|
|
|
```
|
|
|
|
|
|
|
|
Output:
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
```
|
2020-11-23 15:42:05 +01:00
|
|
|
map{"a": 3, "b": 1, "c": 2}
|
|
|
|
```
|
|
|
|
|
|
|
|
This way a map is printed always the same way. If, for a reason, this is undesired, then this behavior can be
|
|
|
|
disabled via the `MAPSORT=0` environment variable.
|
|
|
|
|
|
|
|
##### Hidden values: channels, functions
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
Certain values, like channels and functions are printed without expanding their internals, e.g. channel state or
|
2020-11-23 15:42:05 +01:00
|
|
|
function body. When printing with types, the signature of these objects is printed:
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
```
|
2020-11-23 15:42:05 +01:00
|
|
|
f := func(int) int { return 42 }
|
|
|
|
notation.Println(f)
|
|
|
|
```
|
|
|
|
|
|
|
|
Output:
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
```
|
2020-11-23 15:42:05 +01:00
|
|
|
func()
|
|
|
|
```
|
|
|
|
|
|
|
|
With types:
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
```
|
2020-11-23 15:42:05 +01:00
|
|
|
f := func(int) int { return 42 }
|
|
|
|
notation.Printlnt(f)
|
|
|
|
```
|
|
|
|
|
|
|
|
Output:
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
```
|
2020-11-23 15:42:05 +01:00
|
|
|
func(int) int
|
|
|
|
```
|
|
|
|
|
|
|
|
##### Wrapping
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
The 'w' variant of the printing functions wraps the output with Go style indentation where the lines would be
|
2020-11-23 15:42:05 +01:00
|
|
|
too long otherwise. The wrapping is not eager, it only aims for fitting the lines on 72 columns. To measure the
|
|
|
|
indentation, it assumes 8 character width tabs. In certain cases, it tolerates longer lines up to 112 columns,
|
|
|
|
when the output would probably more readable that way. Of course, readability is subjective.
|
|
|
|
|
|
|
|
As a hidden feature, when it's really necessary, it is possible to change the above control values via
|
2020-11-26 14:27:42 +01:00
|
|
|
environment variables. TABWIDTH controls the measuring of the indentation. LINEWIDTH sets the aimed column width
|
2020-11-23 15:42:05 +01:00
|
|
|
of the printed lines. LINEWIDTH1 sets the tolerated threshold for those lines that are allowed to exceed the
|
|
|
|
default line width. E.g. if somebody uses two-character wide tabs in their console, they can use the package
|
|
|
|
like this:
|
|
|
|
|
|
|
|
```
|
|
|
|
TABWIDTH=2 go test -v -count 1
|
|
|
|
```
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
As a consequence, it is also possible to forcibly wrap all lines:
|
2020-11-23 15:42:05 +01:00
|
|
|
|
|
|
|
```
|
|
|
|
TABWIDTH=0 LINEWIDTH=0 LINEWIDTH1=0 go test -v -count 1
|
|
|
|
```
|
|
|
|
|
|
|
|
##### Types
|
|
|
|
|
|
|
|
Using the 't' or 'v' suffixed variants of the printing functions, notation prints the types together with the
|
|
|
|
values. When the name of a type is available, the name is printed instead of the literal representation of the
|
|
|
|
type. The package path is not printed.
|
|
|
|
|
|
|
|
Named type:
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
```
|
2020-11-23 15:42:05 +01:00
|
|
|
type t struct{foo int}
|
|
|
|
v := t{42}
|
|
|
|
notation.Printlnt(v)
|
|
|
|
```
|
|
|
|
|
|
|
|
Output:
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
```
|
2020-11-23 15:42:05 +01:00
|
|
|
t{foo: 42}
|
|
|
|
```
|
|
|
|
|
|
|
|
Unnamed type:
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
```
|
2020-11-23 15:42:05 +01:00
|
|
|
v := struct{foo int}{42}
|
|
|
|
notation.Printlnt(v)
|
|
|
|
```
|
|
|
|
|
|
|
|
Output:
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
```
|
2020-11-23 15:42:05 +01:00
|
|
|
struct{foo int}{foo: 42}
|
|
|
|
```
|
|
|
|
|
|
|
|
Using the 't' suffixed variants of the printing functions, displaying only moderately verbose type information,
|
|
|
|
the types of certain values is omitted, where it can be inferred from the context:
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
```
|
2020-11-23 15:42:05 +01:00
|
|
|
v := []struct{foo int}{{42}, {84}}
|
|
|
|
notation.Printlnt(os.Stdout, v)
|
|
|
|
```
|
|
|
|
|
|
|
|
Output:
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
```
|
2020-11-23 15:42:05 +01:00
|
|
|
[]struct{foo int}{{foo: 42}, {foo: 84}}
|
|
|
|
```
|
|
|
|
|
|
|
|
##### Cyclic references
|
|
|
|
|
|
|
|
Cyclic references are detected based on an approach similar to the one in the stdlib's reflect.DeepEqual
|
2020-11-26 14:27:42 +01:00
|
|
|
function. Such occurrences are displayed in the output with references:
|
2020-11-23 15:42:05 +01:00
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
```
|
2020-11-23 15:42:05 +01:00
|
|
|
l := []interface{}{"foo"}
|
|
|
|
l[0] = l
|
|
|
|
notation.Fprint(os.Stdout, l)
|
|
|
|
```
|
|
|
|
|
|
|
|
Output:
|
|
|
|
|
2020-11-26 14:27:42 +01:00
|
|
|
```
|
2020-11-23 15:42:05 +01:00
|
|
|
r0=[]{r0}
|
|
|
|
```
|
2020-11-26 14:27:42 +01:00
|
|
|
|