There is no built-in format verb that causes zero values to be omitted.
Here are some options.
fmt.Stringer
You can hard-code the string format for your type by implementing fmt.Stringer:
package main
import (
"fmt"
"strings"
)
type myStruct struct {
a string
b int
c bool
}
func (s myStruct) String() string {
var fields []string
if s.a != "" {
fields = append(fields, fmt.Sprintf("a:%q", s.a))
}
if s.b != 0 {
fields = append(fields, fmt.Sprintf("b:%d", s.b))
}
if s.c {
fields = append(fields, fmt.Sprintf("c:%t", s.c))
}
return fmt.Sprintf("{%s}", strings.Join(fields, ","))
}
func main() {
s := myStruct{a: "foo"}
fmt.Println(s)
}
Output:
{a:"foo"}
https://play.golang.org/p/Dw7F4Ua0Eyq
Reflection
You can use reflection to build something that will work with any struct, but it is perhaps more hassle than it is worth. Example omitted.
JSON
Another alternative is to marshal it to JSON, which handles the reflection part and has support for omitting zero values. Example:
package main
import (
"encoding/json"
"log"
"os"
)
type myStruct struct {
A string `json:",omitempty"`
B int `json:",omitempty"`
C bool `json:",omitempty"`
}
func main() {
s := myStruct{A: "foo"}
if err := json.NewEncoder(os.Stdout).Encode(s); err != nil {
log.Fatal(err)
}
}
Output:
{"A":"foo"}
https://play.golang.org/p/NcckEBNdnW6
JSON with unexported fields
If you prefer to keep the original struct as-is; you can define a custom marshaller with an anonymous struct. Note however that the struct format is then duplicated in the MarshalJSON
method which adds a bit of complexity:
package main
import (
"encoding/json"
"log"
"os"
)
type myStruct struct {
a string
b int
c bool
}
func (s myStruct) MarshalJSON() ([]byte, error) {
return json.Marshal(
struct {
A string `json:"a,omitempty"`
B int `json:"b,omitempty"`
C bool `json:"c,omitempty"`
}{
A: s.a,
B: s.b,
C: s.c,
},
)
}
func main() {
s := myStruct{a: "foo"}
if err := json.NewEncoder(os.Stdout).Encode(s); err != nil {
log.Fatal(err)
}
}
Output:
{"a":"foo"}
https://play.golang.org/p/qsCKUNeFLpw
JSON with unexported fields + fmt.Stringer
If you want, you can again implement fmt.Stringer, which fmt.Printf
and friends will pick up:
package main
import (
"encoding/json"
"fmt"
)
type myStruct struct {
a string
b int
c bool
}
func (s myStruct) MarshalJSON() ([]byte, error) {
return json.Marshal(
struct {
A string `json:"a,omitempty"`
B int `json:"b,omitempty"`
C bool `json:"c,omitempty"`
}{
A: s.a,
B: s.b,
C: s.c,
},
)
}
func (s myStruct) String() string {
j, err := json.Marshal(s)
if err != nil {
return ""
}
return string(j)
}
func main() {
s := myStruct{a: "foo"}
fmt.Println(s)
}
Output:
{"a":"foo"}
https://play.golang.org/p/TPDoLOTAVJo