Skip to content

support the variadic function #11

Description

@achun

Usage like this:

package main

import (
    "fmt"
    "github.com/codegangsta/inject"
)

type SliceInterface interface{}

func Handler1(s string, si ...SliceInterface) {
    fmt.Println("Handler1", s, si)
}

func Handler2(s string, si ...interface{}) {
    fmt.Println("Handler2", s, si)
}

func Handler3(s string, si ...int) {
    fmt.Println("Handler3", s, si)
}

func main() {
    s := "foo"
    si := []SliceInterface{s}
    i := []interface{}{s}
    sint := []int{1, 2, 3}

    ij := inject.New()
    ij.Map(s)
    fmt.Println(ij.Invoke(Handler1))
    fmt.Println(ij.Invoke(Handler2))
    fmt.Println(ij.Invoke(Handler3))

    ij.Map(si).Map(i).Map(sint)
    fmt.Println(ij.Invoke(Handler1))
    fmt.Println(ij.Invoke(Handler2))
    fmt.Println(ij.Invoke(Handler3))
}

I was thinking the code would look something like this:

func InterfaceOf(value interface{}) reflect.Type {
    t := reflect.TypeOf(value)

    for t.Kind() == reflect.Ptr {
        t = t.Elem()
    }

    if t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Interface {
        return t
    }

    if t.Kind() != reflect.Interface {
        panic("Called inject.InterfaceOf with a value that is not a pointer to an interface. (*MyInterface)(nil) but got " + t.Kind().String())
    }

    return t
}

func (inj *injector) Invoke(f interface{}) ([]reflect.Value, error) {
    t := reflect.TypeOf(f)

    var in = make([]reflect.Value, t.NumIn()) //Panic if t is not kind of Func
    for i := 0; i < t.NumIn(); i++ {
        argType := t.In(i)
        val := inj.Get(argType)
        if val.IsValid() {
            in[i] = val
            continue
        }
        if !val.IsValid() && t.IsVariadic() && i == t.NumIn()-1 {
            in[i] = reflect.New(argType).Elem()
            break
        }
        return nil, fmt.Errorf("Value not found for type %v", argType)
    }
    if t.IsVariadic() && len(in) == t.NumIn() {
        return reflect.ValueOf(f).CallSlice(in), nil
    }
    return reflect.ValueOf(f).Call(in), nil
}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions