structmap

package module
v0.0.0-...-0e29110 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 11, 2020 License: MIT Imports: 3 Imported by: 2

README

Go Report Card GoDoc

中文版说明

This repo provides a function convert a struct in Golang to a map(unmarshal a struct to a map).It supports

  1. use tag to define the name of a filed in struct when converted in map. If no tag is specified, it will the name of field as key.
  2. a filed in struct can customize its to map method. To note that the customized method should have (string,interface{}) as output, with the string as key in map and interface{} as value in map.

Also, it skips unexported filed , nil pointer and field without tag.

Tags

For now, it supports 4 tags:

  • '-' means ignoring this field
  • 'omitempty' means ignoring this field when it is empty
  • 'dive' means recursively traversing the struct, converting every filed in struct to be a key in map
  • 'wildcard' applies for string value, it returns "%" +value +"%", which is conveniently for db wildcard query

Example

For example,

type User struct {
	Name      string       `map:"name,omitempty"`        // string
	Github    GithubPage   `map:"github,dive,omitempty"` // struct dive
	NoDive    StructNoDive `map:"no_dive,omitempty"`     // no dive struct
	MyProfile Profile      `map:"my_profile,omitempty"`  // struct implements its own method
}

type GithubPage struct {
	URL  string `map:"url"`
	Star int    `map:"star"`
}

type StructNoDive struct {
	NoDive int `map:"no_dive_int"`
}

type Profile struct {
	Experience string    `map:"experience"`
	Date       time.Time `map:"time"`
}

// its own toMap method
func (p Profile) StructToMap() (key string, value interface{}) {
	return "time", p.Date.Format(timeLayout)
}

by using

res, err := structmap.StructToMap(&user, tag, methodName)

can be converted to be

map[string]interface{}{
	"name":    "user",
	"no_dive":  map[string]int{"no_dive_int": 1},
    // dive struct field
	"url":     "https://github.com/liangyaopei",
	"star":    1,
    // customized method
	"time":    "2020-07-21 12:00:00",
}

Performance

Compared with using marshal/unmarshal function in json package, this repo has better performance.

func BenchmarkStructToMapByJson(b *testing.B) {
	user := newBenchmarkUser()
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		data, _ := json.Marshal(&user)
		m := make(map[string]interface{})
		json.Unmarshal(data, &m)
	}
}

func BenchmarkStructToMapByToMap(b *testing.B) {
	user := newBenchmarkUser()
	tag := "json"
	methodName := ""
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		struct_to_map.StructToMap(&user, tag, methodName)
	}
}

The result of using StructToMap

$ go test ./... -bench=BenchmarkStructToMapByToMap  -benchmem -run=^$ -count=10

BenchmarkStructToMapByToMap-4            1322222               960 ns/op             488 B/op         14 allocs/op
BenchmarkStructToMapByToMap-4            1225311               965 ns/op             488 B/op         14 allocs/op
BenchmarkStructToMapByToMap-4            1201177               947 ns/op             488 B/op         14 allocs/op
BenchmarkStructToMapByToMap-4            1308039               895 ns/op             488 B/op         14 allocs/op
BenchmarkStructToMapByToMap-4            1201592               936 ns/op             488 B/op         14 allocs/op
BenchmarkStructToMapByToMap-4            1351603               882 ns/op             488 B/op         14 allocs/op
BenchmarkStructToMapByToMap-4            1361508               878 ns/op             488 B/op         14 allocs/op
BenchmarkStructToMapByToMap-4            1355869               876 ns/op             488 B/op         14 allocs/op
BenchmarkStructToMapByToMap-4            1353205              1151 ns/op             488 B/op         14 allocs/op
BenchmarkStructToMapByToMap-4            1278057              1487 ns/op             488 B/op         14 allocs/op

The result of using json package

$ go test ./... -bench=BenchmarkStructToMapByJson  -benchmem -run=^$ -count=10 
BenchmarkStructToMapByJson-4      383409              3171 ns/op             992 B/op         30 allocs/op
BenchmarkStructToMapByJson-4      314690              3297 ns/op             992 B/op         30 allocs/op
BenchmarkStructToMapByJson-4      363764              3009 ns/op             992 B/op         30 allocs/op
BenchmarkStructToMapByJson-4      365799              3122 ns/op             992 B/op         30 allocs/op
BenchmarkStructToMapByJson-4      361111              3057 ns/op             992 B/op         30 allocs/op
BenchmarkStructToMapByJson-4      335830              3176 ns/op             992 B/op         30 allocs/op
BenchmarkStructToMapByJson-4      347206              3069 ns/op             992 B/op         30 allocs/op
BenchmarkStructToMapByJson-4      380973              3067 ns/op             992 B/op         30 allocs/op
BenchmarkStructToMapByJson-4      373834              3000 ns/op             992 B/op         30 allocs/op
BenchmarkStructToMapByJson-4      373597              3206 ns/op             992 B/op         30 allocs/op

Documentation

Index

Constants

View Source
const (
	OptIgnore    = "-"
	OptOmitempty = "omitempty"
	OptDive      = "dive"
	OptWildcard  = "wildcard"
)

Variables

This section is empty.

Functions

func StructToMap

func StructToMap(s interface{}, tag string, methodName string) (res map[string]interface{}, err error)

StructToMap convert a golang sturct to a map key can be specified by tag, LIKE `map:"tag"`. If there is no tag, struct filed name will be used instead methodName is the name the field has implemented. If implemented, it uses the method to get the key and value

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL