Selecting a specific functionality based on the parameter

Hi,

I want to select a specific repository at runtime by, for example, passing an argument to, let’s say, a “selector” function. Yes, it is something like a Strategy pattern in OOP. Say I have a “selector” function/struct/whatever you name it. When I call it by passing Account struct, I should only be able to access its methods so Total(). If I pass User then FindNameByID(id int). Is this possible with Go?

I looked at Go Strategy pattern but my structs will always have different functions in them.

Thanks

package repository

type User struct {
	// Some field(s)
}

func (u User) FindNameByID(id int) string {
	// Do something with u

	users := map[int]string{1: "bob", 2: "jon"}

	return users[id]
}
package repository

type Account struct {
	// Some field(s)
}

func (a Account) Total() int {
	// Do something with a
	return 10
}

Usage

ar := RepoSelector(Account{})
ar->Total()

ur := RepoSelector(User{})
ur->FindNameByID(1)

NOTE: Somehow, if possible, I don’t want to pass field parameters to Account and User so they should be already injected.

Hi @GoingToGo,

If you use strategy pattern, you should define your method in your interface. let say your interface is

type RepoSelector interface {
FindNameByID(int)
Total() int
}

So when you define method in your RepoSelector interface it must be accessible that two method FindNameByID(int) and Total() int in your struct. e.g for Account and User

type User struct {}
func (u User) Total()int {}
func (u User) FindNameByID(int){}

type Account struct {}
func (a Account) Total()int {}
func (a Account) FindNameByID(int){}

Thanks for the answer. However, your solution goes against my “only” requirement which isolates functions per receivers so if I fetch User, only FindNameByID() should be visible, not Total().

For me, It is impossible to isolate method with single interface. However, I just write a simple code to find a way to isolate functions using two interface.

type SelectorA interface {
     FindNameByID(int)
 }

type SelectorB interface {
    Total() int
}

type Operation struct {}

func NewOperation(m interface{}) interface{} {`
    switch v := m.(type) {
	case SelectorA:
		log.Println("[ SelectorA ]",v)
		return v
	case SelectorB:
		log.Println("[ SelectorB ]",v)
		return v
	default:
		log.Println("Unknown interface")
    }
    return nil
}

type User struct {}

func (a User) FindNameByID(n int) {
  log.Println("user:",n)
}

type Account struct {}

func (a Account) Total() int {
    return 10
}

func main() {

    me := NewOperation(User{}).(User) // as User, since it is interface
    me.FindNameByID(34)

    n := NewOperation(Account{}).(Account)
    log.Println("Total:",n.Total())
}

Hi, @GoingToGo,

I’m a little confused by your example. It seems that when you get a User, you want to treat it as some sort of repository of Users that you can lookup by ID, but when you get an Account, you’re getting a Total of a specific account. Does User get you one specific User or a repository, and does Account get you one account or a repository?

@skillian You are missing the point by focusing on what functions might possibly do which is irrelevant to the question.

Thanks @adriel

Your solution is what I though at some point as well but as you probably already guessed it might get very ugly very quickly as things grow. I’ll probably rethink about my idea as so far I couldn’t find a clean solution. Thanks for the input though.

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