mardi 24 février 2015

Go Reflect Method Call invalid memory address or nil pointer dereference

I'm trying to use reflect to call a method on a struct.


The code I have is dispersed, but everything relevant should be here;



// Begin new transaction, attach to new transaction service
transactionService := &models.TransactionService{}
transactionService.Begin()

// Transactioner interface type
transactionerType := reflect.TypeOf((*models.Transactioner)(nil)).Elem()

// Go through target controllers' models
// Attach transactionService to each model

val := reflect.ValueOf(c.AppController).Elem()
for i := 0; i < val.NumField(); i++ {
// For each field, check if it'
valueField := val.Field(i)

if valueField.Type().Implements(transactionerType) {
attachMethodValue := valueField.MethodByName("Attach")
args := []reflect.Value{reflect.ValueOf(transactionService)}
revel.INFO.Printf("%+v",attachMethodValue)
revel.INFO.Println(args)
attachMethodValue.Call(args)
}
}


...


The two print-statements near the end give the following output, followed by a panic



INFO 2015/02/24 21:01:12 gorp.go:122: Begun transaction
INFO 2015/02/24 21:01:12 init.go:79: <func(*models.TransactionService) Value>
INFO 2015/02/24 21:01:12 init.go:80: [<*models.TransactionService Value>]
ERROR 2015/02/24 21:01:12 panic.go:29: runtime error: invalid memory address or nil pointer dereference


As you can see, they don't seem to be nil values, which is why I'm confused about why I'm getting the panic.


Other code that might provide the contextual information.



type AppController struct {
*revel.Controller
}

type UserController struct {
AppController
UserModel *models.UserModel
}

type GorpModel struct {
transactionService *TransactionService
}

func (m *GorpModel) Attach(transactionService *TransactionService) {
m.transactionService = transactionService
revel.INFO.Println("Transactioner called!")
}

type Transactioner interface {
Attach(transactionService *TransactionService)
}

type TransactionService struct {
txn *gorp.Transaction
}

func (t *TransactionService) Begin() {
revel.INFO.Println("Begun transaction")
t.txn = BeginTransaction()
}


Any ideas on what the issue is?






Aucun commentaire:

Enregistrer un commentaire