Thanks to visit codestin.com
Credit goes to github.com

Skip to content

lopolopen/shoot

Repository files navigation

A pack of tools for "go generate".

Project status:

BETA VERSION. USE WITH CAUTION!

How to use?

Usage: shoot <subcommand> [options]
These are all the sub commands supported as of now:
new [-opt] [-getset] [-json] [-exp] [-tagcase=<case>] [-type=<Type> | -file=<GoFile>] [dir] [-s] [-v]
enum [-bit] [-json] [-text] -[sql] [-type=<Type> | -file=<GoFile>] [dir] [-v]
rest [-type=<Type> | -file=<GoFile>] [dir] [-v]
map [-path=<path>] [-alias=<alias>] [-to=<DestType>] [-type=<SrcType> | -file=<GoFile>] [dir] [-s] [-v]

using go1.24+ (SUGGESTED)

why 1.24

Tool dependencies

install

go get -tool github.com/lopolopen/shoot/cmd/shoot@latest

generate instruction examples

//go:generate go tool shoot new -getset -json -type=YourType

//go:generate go tool shoot new -getset -json -file=$GOFILE

//go:generate go tool shoot enum -json -type=YourEnum

//go:generate go tool shoot rest -type=YourClient

//go:generate go tool shoot map -path=../destpath -type=YourSrcType
go generate			# run in the current directory
go generate ./...	# recursively run in the current directory and its subdirectories

using go1.24- (at leat 1.18)

go install github.com/lopolopen/shoot/cmd/shoot@latest

go get github.com/lopolopen/shoot@latest	# manual installation is necessary for legacy-version projects
//go:generate shoot new -getset -json -type=YourType

//go:generate shoot new -getset -json -file=$GOFILE

//go:generate shoot enum -json -type=YourEnum

//go:generate shoot rest -type=YourClient

//go:generate shoot map -path=../destpath -type=YourSrcType

generated file sample 1:

// Code generated by "shoot new -getset -type=User"; DO NOT EDIT.

package example

// NewUser constructs a new instance of type User
func NewUser(id int, name string, age int) *User {
	return &User{
		id:   id,
		name: name,
		age:  age,
	}
}

// Id gets the value of field id
func (u *User) Id() int {
	return u.id
}

// Name gets the value of field name
func (u *User) Name() string {
	return u.name
}

// Age gets the value of field age
func (u *User) Age() int {
	return u.age
}

// SetId sets the value of field id
func (u *User) SetId(id_ int) {
	u.id = id_
}

// SetName sets the value of field name
func (u *User) SetName(name_ string) {
	u.name = name_
}

// SetAge sets the value of field age
func (u *User) SetAge(age_ int) {
	u.age = age_
}

generated file sample 2:

// Code generated by "shoot rest -type=Client"; DO NOT EDIT.

package example

import (
	"context"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strings"
	"time"

	"github.com/lopolopen/shoot"
)

type client struct {
	client *http.Client
	conf   *shoot.RestConf
}

func (c *client) GetUser(ctx context.Context, userID string, pageSize int, pageIdx *int) (*User, *http.Response, error) {
	path_ := "/users/{id}"
	path_ = strings.Replace(path_, "{id}", fmt.Sprintf("%v", userID), 1)

	url_, err := url.JoinPath(c.conf.BaseURL(), path_)
	if err != nil {
		return nil, nil, err
	}

	req_, err := http.NewRequestWithContext(ctx, "GET", url_, nil)
	if err != nil {
		return nil, nil, err
	}

	query_ := req_.URL.Query()
	query_.Set("size", fmt.Sprintf("%v", pageSize))
	if pageIdx != nil {
		query_.Set("page_idx", fmt.Sprintf("%v", *pageIdx))
	}
	req_.URL.RawQuery = query_.Encode()

	req_.Header.Add("Accept", "application/json")
	req_.Header.Add("Tenant-Id", "123")

	resp_, err := c.client.Do(req_)
	if err != nil {
		return nil, nil, err
	}
	defer resp_.Body.Close()

	switch {
	case resp_.StatusCode >= 500:
		body_, _ := io.ReadAll(resp_.Body)
		err = fmt.Errorf("server error %d: %s", resp_.StatusCode, string(body_))
	case resp_.StatusCode >= 400:
		body_, _ := io.ReadAll(resp_.Body)
		err = fmt.Errorf("client error %d: %s", resp_.StatusCode, string(body_))
	case resp_.StatusCode >= 300 || resp_.StatusCode < 200:
		err = fmt.Errorf("not supported error %d", resp_.StatusCode)
	}
	if err != nil {
		return nil, resp_, err
	}

	var r_ User
	err = json.NewDecoder(resp_.Body).Decode(&r_)
	if err == io.EOF {
		err = nil //ignore EOF errors caused by empty response body
	}
	if err != nil {
		return nil, resp_, err
	}
	return &r_, resp_, nil
}

generated file sample 3:

// Code generated by "shoot map -path=../../domain/model -alias=domain -type=*"; DO NOT EDIT.

package dto

import domain "mappersample/domain/model"

// ToDomain converts receiver to type domain.Order
func (o *Order) ToDomain() *domain.Order {
	if o == nil {
		return nil
	}
	order_ := new(domain.Order)
	order_.ID = o.ID
	order_.Amount = o.StringToDecimal(o.Amount)
	order_.Status = o.Status
	order_.OrderTime = o.StringToTime(o.OrderingTime)
	if o.Address != nil {
		order_.Address = *o.Address.ToDomain()
	}
	o.writeDomain(order_)
	return order_
}

// FromDomain reads from type domain.Order, then writes back to receiver and returns it
func (o *Order) FromDomain(order_ *domain.Order) *Order {
	if order_ == nil {
		return nil
	}
	if o == nil {
		o = new(Order)
	}
	o.ID = order_.ID
	o.Amount = o.DecimalToString(order_.Amount)
	o.Status = order_.Status
	o.OrderingTime = o.TimeToString(order_.OrderTime)
	o.Address = new(OrderAddress).FromDomain(&order_.Address)
	o.readDomain(order_)
	return o
}

more examples:

samples

TODO:

  • shoot new -getset -type=YourType
  • shoot new: field instruction like get;default=1
  • shoot new -opt|option -type=YourType
  • shoot new -json -type=YourType
  • shoot new: embed struct
  • shoot new: external package
  • shoot new -file=YourFile
  • shoot new: type instruction like ignore
  • shoot new: -separate
  • shoot enum -bit|bitwise -type=YourEnum
  • shoot enum -json -type=YourEnum
  • refactor: duplicated code
  • shoot map

Inspiring projects

About

A pack of tools for "go generate".

Resources

License

Stars

Watchers

Forks

Packages

No packages published