Robust & Easy to use model mapper and utility methods for Go struct
. Typical methods increase productivity and make Go development more fun ๐
v0.5 released and tagged on Jan 02, 2017
go-model tested with Go v1.2
and above.
go-model library provides handy methods to process struct
with below highlighted features. It's born from typical need while developing Go application or utility. I hope it's helpful to Go community!
- Embedded/Anonymous struct
- Multi-level nested struct/map/slice
- Pointer and non-pointer within struct/map/slice
- Struct within map and slice
- Embedded/Anonymous struct fields appear in map at same level as represented by Go
- Interface within struct/map/slice
- Get struct field
reflect.Kind
by field name - Get all the struct field tags (
reflect.StructTag
) or selectively by field name - Get all
reflect.StructField
for given struct instance - Get or Set by individual field name on struct
- Add global no traverse type to the list or use
notraverse
option in the struct field - Options to name map key, omit empty fields, and instruct not to traverse with struct/map/slice
- Conversions between mixed non-pointer types
Please refer section Versioning for detailed info.
# install the library
go get -u gopkg.in/jeevatkm/go-model.v0
# install the latest & greatest library
go get -u github.com/jeevatkm/go-model
Import go-model into your code and refer it as model
. Have a look on model test cases to know more possibilities.
import (
"gopkg.in/jeevatkm/go-model.v0"
)
- Copy - usage, godoc
- Map - usage, godoc
- Clone - usage, godoc
- IsZero - usage, godoc
- HasZero - usage, godoc
- IsZeroInFields - usage, godoc
- Fields - usage, godoc
- Kind - usage, godoc
- Tag - usage, godoc
- Tags - usage, godoc
- Get - usage, godoc
- Set - usage, godoc
- AddNoTraverseType - usage, godoc
- RemoveNoTraverseType - usage, godoc
- AddConversion - usage, godoc
- RemoveConversion - usage, godoc
How do I copy my struct object into another? Not to worry, go-model does deep copy.
// let's say you have just decoded/unmarshalled your request body to struct object.
tempProduct, _ := myapp.ParseJSON(request.Body)
product := Product{}
// tag your Product fields with appropriate options like
// -, omitempty, notraverse to get desired result.
// Not to worry, go-model does deep copy :)
errs := model.Copy(&product, tempProduct)
fmt.Println("Errors:", errs)
fmt.Printf("\nSource: %#v\n", tempProduct)
fmt.Printf("\nDestination: %#v\n", product)
I want to convert my struct into Map (map[string]interface{}
). Sure, go-model does deep convert.
// tag your SearchResult fields with appropriate options like
// -, name, omitempty, notraverse to get desired result.
sr, _ := myapp.GetSearchResult( /* params here */ )
// Embedded/Anonymous struct fields appear in map at same level as represented by Go
srchResMap, err := model.Map(sr)
fmt.Println("Error:", err)
fmt.Printf("\nSearch Result Map: %#v\n", srchResMap)
I would like to clone my struct object. That's nice, you know go-model does deep processing.
input := Product { /* Product struct field values go here */ }
// have your struct fields tagged appropriately. Options like
// -, name, omitempty, notraverse to get desired result.
clonedObj := model.Clone(input)
// let's see the result
fmt.Printf("\nCloned Object: %#v\n", clonedObj)
I want to check my struct object is empty or not. Of course, go-model does deep zero check.
// let's say you have just decoded/unmarshalled your request body to struct object.
productInfo, _ := myapp.ParseJSON(request.Body)
// wanna check productInfo is empty or not
isEmpty := model.IsZero(productInfo)
// tag your ProductInfo fields with appropriate options like
// -, omitempty, notraverse to get desired result.
fmt.Println("Hey, I have all fields zero value:", isEmpty)
I want to check my struct object has any zero/empty value. Of course, go-model does deep zero check.
// let's say you have just decoded/unmarshalled your request body to struct object.
productInfo, _ := myapp.ParseJSON(request.Body)
// wanna check productInfo is empty or not
isEmpty := model.HasZero(productInfo)
// tag your ProductInfo fields with appropriate options like
// -, omitempty, notraverse to get desired result.
fmt.Println("Hey, I have zero values:", isEmpty)
Is it possible to check to particular fields has zero/empty values. Of-course you can.
// let's say you have just decoded/unmarshalled your request body to struct object.
product, _ := myapp.ParseJSON(request.Body)
// check particular fields has zero value or not
fieldName, isEmpty := model.IsZeroInFields(product, "SKU", "Title", "InternalIdentifier")
fmt.Println("Empty Field Name:", fieldName)
fmt.Println("Yes, I have zero value:", isEmpty)
You wanna all the fields from struct
, Yes you can have it :)
src := SampleStruct {
/* struct fields go here */
}
fields, _ := model.Fields(src)
fmt.Println("Fields:", fields)
go-model library provides an ability to know the reflect.Kind
in as easy way.
src := SampleStruct {
/* struct fields go here */
}
fieldKind, _ := model.Kind(src, "BookingInfoPtr")
fmt.Println("Field kind:", fieldKind)
I want to get Go lang supported Tag value from my struct
. Yes, it is easy to get it.
src := SampleStruct {
BookCount int `json:"-"`
BookCode string `json:"-"`
ArchiveInfo BookArchive `json:"archive_info,omitempty"`
Region BookLocale `json:"region,omitempty"`
}
tag, _ := model.Tag(src, "ArchiveInfo")
fmt.Println("Tag Value:", tag.Get("json"))
// Output:
Tag Value: archive_info,omitempty
I would like to get all the fields Tag values from my struct
. It's easy.
src := SampleStruct {
BookCount int `json:"-"`
BookCode string `json:"-"`
ArchiveInfo BookArchive `json:"archive_info,omitempty"`
Region BookLocale `json:"region,omitempty"`
}
tags, _ := model.Tags(src)
fmt.Println("Tags:", tags)
I want to get value by field name on my struct
. Yes, it is easy to get it.
src := SampleStruct {
BookCount: 100,
BookCode: "GHT67HH00",
}
value, _ := model.Get(src, "BookCode")
fmt.Println("Value:", value)
// Output:
Value: GHT67HH00
I want to set value by field name on my struct
. Yes, it is easy to get it.
src := SampleStruct {
BookCount: 100,
BookCode: "GHT67HH00",
}
err := model.Set(&src, "BookCount", 200)
fmt.Println("Error:", err)
There are scenarios, where you want the object values but not to traverse/look inside the struct object. Use notraverse
option in the model tag for those fields or Add it NoTraverseTypeList
. Customize it as per your need.
Default NoTraverseTypeList
has these types time.Time{}
, &time.Time{}
, os.File{}
, &os.File{}
, http.Request{}
, &http.Request{}
, http.Response{}
, &http.Response{}
.
// If you have added your type into list then you need not mention `notraverse` option for those types.
// Adding type into NoTraverseTypeList
model.AddNoTraverseType(time.Location{}, &time.Location{})
// Removing type from NoTraverseTypeList
model.RemoveNoTraverseType(time.Location{}, &time.Location{})
This example registers a custom conversion from the int
to the string
type.
AddConversion((*int)(nil), (*string)(nil), func(in reflect.Value) (reflect.Value, error) {
return reflect.ValueOf(strconv.FormatInt(in.Int(), 10)), nil
})
If a an integer field on the source struct matches the name of a string field on the target struct, the provided Converter method is invoked.
Note that if you want to register a converter from int
to *string
you will
have to provide a pointer to a pointer as destination type ( (**string)(nil)
).
More examples can be found in the AddConversion godoc.
go-model releases versions according to Semantic Versioning
gopkg.in/jeevatkm/go-model.vX
points to appropriate tag versions; X
denotes version number and it's a stable release. It's recommended to use version, for eg. gopkg.in/jeevatkm/go-model.v0
. Development takes place at the master branch. Although the code in master should always compile and test successfully, it might break API's. We aim to maintain backwards compatibility, but API's and behaviour might be changed to fix a bug.
Welcome! If you find any improvement or issue you want to fix, feel free to send a pull request. I like pull requests that include test cases for fix/enhancement. I have done my best to bring pretty good code coverage. Feel free to write tests.
BTW, I'd like to know what you think about go-model. Kindly open an issue or send me an email; it'd mean a lot to me.
Jeevanandam M. - [email protected]
Have a look on Contributors page.
go-model released under MIT license, refer LICENSE file.