Type Wrapper

test release

type-wrapper is type wrapper generator for Go programming language.

What is type-wrapper?

type-wrap is a tool that generates:

  • Wrapper struct from any structs.
  • Getter and Setter methods
  • Json method which marshal the original type to []byte
  • Interface for the wrapper struct

Sometimes you might make struct fields unexported in order for values of fields not to be accessed or modified from anywhere in your codebases, and define getters or setters for values to be handled in a desired way.

But writing wrappers for structs with many fields is time-consuming, but not exciting or creative.

type-wrapper frees you from tedious, monotonous tasks.

Installation

To get the latest released version

Go 1.18+

go install github.com/Marble-Technologies/[email protected]

Usage

Declare Struct with wrapper Tag

type-wrapper generates wrapper methods from defined structs, so you need to declare a struct and fields with wrapper tag.

Values for wrapper tag is getter and setter, getter is for generating getter method and setter is for setter methods.

Here is an example:

type MyStruct struct {
    Field1 string    `wrapper:"getter"`
    field2 *int      `wrapper:"setter"`
    Field3 time.Time `wrapper:"getter,setter"`
}

Generated wrapper will be

// MyStructWrapper encapulates the type MyStruct
type MyStructWrapper struct {
	MyStruct
}

func (m MyStructWrapper) Field1() string {
	return m.MyStruct.Field1
}

func (m MyStructWrapper) SetField2(val *int) {
	m.MyStruct.field2 = val
}

func (m MyStructWrapper) Field3() time.Time {
	return m.MyStruct.Field3
}

func (m MyStructWrapper) SetField3(val time.Time) {
	m.MyStruct.Field3 = val
}

getter and setter methods won’t be generated if wrapper tag isn’t specified. But you can explicitly skip generation by using - for tag value.

type MyStruct struct {
    ignoredField `accessor:"-"`
}

Following to convention, setter’s name is Set<FieldName>() and getter’s name is <FieldName>() by default, in other words, Set will be put into setter’s name and Get will not be put into getter’s name.

You can customize names for setter and getter if you want.

type MyStruct struct {
    Field1 string `wrapper:"getter:GetFirstField"`
    Field2 int    `wrapper:"setter:ChangeSecondField"`
}

Generated methods will be

type MyStructWrapper struct {
	MyStruct
}

func (m MyStructWrapper) GetFirstField() string {
	return m.MyStruct.Field1
}

func (m MyStructWrapper) ChangeSecondField(val int) {
	m.MyStruct.Field2 = val
}

getter and setter methods won’t be generated if wrapper tag isn’t specified. But you can explicitly skip generation by using - for tag value.

type MyStruct struct {
    ignoredField `wrapper:"-"`
}

Generate the interface of the Wrapper type

If an interface name provided to wrapper tool, it will generate the interface which the wrapper type implements,

Here is an example ()

type MyStruct struct {
	Field1 string    `wrapper:"getter"`
	Field2 *int      `wrapper:"setter"`
	Field3 time.Time `wrapper:"getter,setter:SetTime"`
}

type IStruct interface {
	Field1() string
	SetField2(val *int)
	Field3() time.Time
	SetTime(val time.Time)
}

// MyStructWrapper encapulates the type MyStruct
type MyStructWrapper struct {
	MyStruct
}

func (m MyStructWrapper) Field1() string {
	return m.MyStruct.Field1
}

func (m MyStructWrapper) SetField2(val *int) {
	m.MyStruct.Field2 = val
}

func (m MyStructWrapper) Field3() time.Time {
	return m.MyStruct.Field3
}

func (m MyStructWrapper) SetTime(val time.Time) {
	m.MyStruct.Field3 = val
}

Generate the Json method

type-wrapper can generate Json method which uses encoding/json package to marshal the original type Here is an example ()

type MyStruct struct {
	Field1 string    `wrapper:"getter" json:"name,omitempty"`
	Field2 *int      `wrapper:"setter" json:"value,omitempty"`
	Field3 time.Time `wrapper:"getter,setter:SetTime" json:"time,omitempty"`
}

import (
	"encoding/json"
	"time"
)

type IStruct interface {
	Field1() string
	SetField2(val *int)
	Field3() time.Time
	SetTime(val time.Time)
	Json() []byte
}

// MyStructWrapper encapulates the type MyStruct
type MyStructWrapper struct {
	MyStruct
	// The name of the original type, it gets initalized when calling Json() function, DO NOT USE IT
	DataType string `json:"_data_type,omitempty"`
}

func (m MyStructWrapper) Field1() string {
	return m.MyStruct.Field1
}

func (m MyStructWrapper) SetField2(val *int) {
	m.MyStruct.Field2 = val
}

func (m MyStructWrapper) Field3() time.Time {
	return m.MyStruct.Field3
}

func (m MyStructWrapper) SetTime(val time.Time) {
	m.MyStruct.Field3 = val
}

func (m MyStructWrapper) Json() []byte {
	m.DataType = "MyStruct"
	if data, err := json.Marshal(m); err == nil {
		return data
	}
	return []byte{}
}

Run type-wrapper command

$ type-wrapper [flags] source-dir

source-dir
  source-dir is the directory where the definition of the target struct is located.
  If source-dir is not specified, current directory is set as source-dir.

Flags:
  -interface string
        wrapper interface name to be generated
  -json
        generate Json() method
  -lock string
        lock name
  -output string
        output file name; default <type_name>_wrapper.go
  -receiver string
        receiver name; default first letter of type name
  -type string
        type name; must be set
  -version
        show the version of wrap
  -wrapper string
        wrapper type name; default <type_name>Wrapper

Example:

$ type-wrapper -type MyStruct -wrapper WStruct -interface IStruct -json -receiver myStruct -output my_struct_wrapper.go path/to/target

go generate

You can also generate wrappers by using go generate.

package mypackage

//go:generate type-wrapper -type MyStruct -wrapper WStruct -interface IStruct -json -receiver myStruct -output my_struct_wrapper.go 

type MyStruct struct {
    field1 string `wrapper:"getter"`
    field2 *int   `wrapper:"setter"`
}

Then run go generate for your package.

Credits

This project has been inspired by accessory project and it uses most of its source code.

We acknowledge and are grateful to masaushi and yumm007 for their great work

License

The type-wrapper project (and all code) is licensed under the MIT License.

GitHub

View Github