Disclaimer: This article will be updated from time to time to add new content or make any changes in exsisting sections without any notice. Using them under your own investigation in production is advised.
I. Grammar
1.1 Ommit empty struct in `json.Marshal()'
Suppose we have a nested struct like:
|
|
And if only info
filed is assinged with a value when initialized.
|
|
What we get will be:
|
|
How do we omit ExampleValues
field if it is not assigned with a value? Use a pointer!
|
|
And the result will be:
|
|
1.2 Avoid omitempty
for fields that are asgined with 0 or empty string
With a struct defined like this:
|
|
Even if we can initialize a TestStruct
with some special values and perform a json marshal.
|
|
What we get will be an empty json object.
|
|
And that might not be something we expected.
Since the tag omitempty
means all empty values (that are false, 0, any nil pointer or interface value, and any array, slice, map, or string of length zero) will be omited no matter whether thay are assigned on purpose or not. Sometimes what we need is some kind of feature like ommitnil
tag that omit those fields which are not initialized and keep them even if they are initialized with empty values
Apparently there is no such tag feature in standard library. To make it work we may have to use interface{}
.
|
|
To compare, we may initialize TestStruct2
twice in different ways, partly and wholly.
|
|
And we get will be:
|
|
The result lies in the fact that interface{}
won’t be nil after being initialized even if the data it points to is empty value.
1.3 Type Assertions & Type Switches
Interfaces in Go can introduce ambiguity about the underlying type.
A type assertion allows us to extract the interface value’s underlying concrete value using this syntax: interfaceVariable.(concreteType)
.
For example:
|
|
NOTE: this will cause a panic if the interface variable does not hold a value of the concrete type.
We can test whether an interface value holds a specific concrete type by making use of both return values of the type assertion: the underlying value and a boolean value that reports whether the assertion succeeded. For example:
|
|
If input
holds a string
, then str
will be the underlying value and ok
will be true.
If input
does not hold a string
, then str
will be the zero value of type string
(ie. ""
- the empty string) and ok
will be false.
No panic occurs in any case.
A type switch can perform several type assertions in series.
It has the same syntax as a type assertion (interfaceVariable.(concreteType)
), but the concreteType
is replaced with the keyword type
.
Here is an example:
|
|
II. Design Pattern
2.1 Singleton
Singleton is usually used as a global instance, initialized lazily or eagerly with double concurrent check.
|
|