AST analysis: How can I tell, at runtime, what datatypes a `function(emptyInterface) emptyInterface` expects and returns?

Hello fellow gophers !

You are given a function (which you cannot change, it is a function variable, you cannot read its code) that takes in an interface and returns an interface:

 function(interface{})interface{}

You know that this function will always convert its input to a data type X (every possible input gets converted to that same X), and will always returned an object of type Y (always type Y) converted to interface{}.

How can you tell, (using reflection ?), at runtime, what are the exact types X and Y. Is it even possible to do so without running the function, just by programmatically analyzing its code ?

Any ideas ? Think outside the box, or inside the box, whatever works.

Come on people, come up with some ideas.

Sample code

package main

import (
“fmt”
“reflect”
)

func test(x interface{}) {
xType := reflect.TypeOf(x)
xValue := reflect.ValueOf(x)
fmt.Println(xType, xValue) // “[]int [1 2 3]”
}

func main() {
test([]int{1, 2, 3})
}

Hi Yamil,

It is a nice try, but requires me to change the function. It also requires me to be able to read and edit its code.

I am looking for more creative ideas, where I receive the function as a variable (the function itself it is my input) and then I analyze it to figure out where are the lines with return and what exactly is returned on those lines.

I don’t really understand your problem so i am just thinking and writing maybe this wont be help at all but…

Go is strict language try smth like this function(inputInterface{}) outputInterface{}
create your interfaces

Is this a thought experiment or is there a practical question here? If the latter, I’d like to get more information about the code/infrastructure around the code that lead to this situration.

I believe that one of the neat aspects of forums (and of this forum, in particular) is the follow-up questions that can maybe cause the asker (myself included) to reconsider their question in ways that the asker didn’t think of.

For example, instead of changing the function, f, perhaps you could wrap it into another function, f′, that checks and determines the function’s input and output types, like Yamil Bracho suggested. Your counter to that suggestion was that you’d have to change the function, but, in fact, you wouldn’t have to change the function if you wrapped the function – you’d have to change the code that calls the function (is it a requirement that the calling code not be changed as well?) – but not the function itself.

Also, is this an XY problem where you have determined that you need to know the input and output types of a function, but, perhaps, potentially, if you were to re-analyze the issue as a whole, it might be possible that the problem could be simpler than the way you see it at this time?

For example, perhaps the scenario is that you have some generic code where you register functions in some sort of repository like this:

func Register(name string, f func(interface{}) interface{}) {
    someGlobalState.Store(name, f)
}

But (without having seen the architecture and/or usage of these func(interface{}) interface{} functions), perhaps you could do this:

var someGlobalState sync.Map

type someGlobalStateKey struct {
    TIn reflect.Type
    TOut reflect.Type
}

func Register(name string, Tin, Tout reflect.Type, f func(interface{}) interface{}) {
    key := someGlobalStateKey{TIn: Tin, TOut: Tout}
    someGlobalState.Store(key, f)
}

// ... Some code that calls register later

func init() {
    Register("sin", reflect.TypeOf(float32(0)), reflect.TypeOf(float32(0)), func (x interface{}) interface{} {
        return float32(math.Sin(x.(float64)))
    })
}

This way, you don’t have to do any runtime analysis of the function’s usage; it’s already registered with the proper types. You could add additional code around the usage of these functions (perhaps in debug builds) that check the types of the parameters and report errors for incorrect usage.

TL;DR

I think we need more information about the code/infrastructure around how these functions are declared and/or used to provide better answers.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.