func getlArgs(typ reflect.Type, args []interface{}) ([]reflect.Value, error) {
	var rst []reflect.Value
	for _, v := range args {
		val := reflect.ValueOf(v)
		if !val.IsValid() {  
			return nil, ErrZeroValue
		}
		rst = append(rst, val)
	}
	switch {
	case typ.IsVariadic():
		if typ.NumIn() < len(args)-1 {  
			return nil, ErrTooFewArgs
		}
	case !typ.IsVariadic() && typ.NumIn() > len(args):  
		return nil, ErrTooManyArgs
	}
	return rst, nil
}
getArgs retrieves argument list from args.
This tries to avoid common panics, and returns the corresponding errors instead.
panics can still occur but at least the ones related with arguments are mitigated.
package ita
import (
	"errors"
	"reflect"
)
var (
	ErrMethodNotFound = errors.New("ita: method not found")
	ErrZeroValue = errors.New("ita: zero value argument")
	ErrTooManyArgs = errors.New("ita: the method has more arguments than the ones provided")
	ErrTooFewArgs = errors.New("ita: you have provided more arguments than required by the method")
)
type Result struct {
	rst []reflect.Value
}
func (r *Result) First() (interface{}, bool) {
	if r.IsNil() {
		return nil, false
	}
	return r.Get(0)
}
func (r *Result) Get(index int) (val interface{}, ok bool) {
	if r.HasIndex(index) {
		return r.rst[index].Interface(), true
	}
	return nil, false
}
func (r *Result) IsNil() bool {
	return r.rst == nil
}
func (r *Result) Len() int {
	return len(r.rst)
}
func (r *Result) Last() (interface{}, bool) {
	if r.IsNil() {
		return nil, false
	}
	return r.Get(r.Len() - 1)
}
func (r *Result) HasIndex(index int) bool {
	if r.IsNil() {
		return false
	}
	if index >= r.Len() {
		return false
	}
	return true
}
func (r *Result) Set(rst []reflect.Value) {
	r.rst = rst
}
type Struct struct {
	value  reflect.Value
	data   reflect.Value
	result *Result
	err    error
}
func (s *Struct) Error() error {
	return s.err
}
func New(v interface{}) *Struct {
	value := reflect.ValueOf(v)
	var data reflect.Value
	switch value.Kind() {
	case reflect.Ptr:
		data = value
	default:
		data = reflect.New(reflect.TypeOf(v)).Elem()
	}
	return &Struct{
		value:  value,
		data:   data,
		result: &Result{},
		err:    nil,
	}
}
func (s *Struct) Call(method string, a ...interface{}) *Struct {
	clone := s.clone()
	m := clone.data.MethodByName(method)
	if !m.IsValid() {
		clone.err = ErrMethodNotFound
		return clone
	}
	typ := m.Type()
	args, err := getlArgs(typ, a)
	if err != nil {
		clone.err = err
		return clone
	}
	if typ.NumOut() > 0 {
		clone.callWithResults(m, args)
	} else {
		clone.call(m, args)
	}
	return clone
}
func (s *Struct) callWithResults(v reflect.Value, args []reflect.Value) {
	s.result.Set(v.Call(args))
}
func (s *Struct) call(v reflect.Value, args []reflect.Value) {
	v.Call(args)
}