Kendrick johnson
Kendrick johnson

Reputation: 322

go build error "db.GetUsers undefined (type *gorm.DB has no field or method GetUsers)"

I am new to golang and trying to make API server using gin + gorm.
I tried to build the code below but I am getting type *gorm.DB has no field or method GetUsers error.
This is a very simple API server and only I want to do is get all users from users table.

package models

import (
    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/postgres"
)

var db *gorm.DB

func init() {
    var err error
    db, err = gorm.Open("postgres", "host=localhost dbname=test user=postgres password=test sslmode=disable")
    if err != nil {
        return err
    }
}

type User struct {
   ID           int    `json:"id"`
   Username     string `json:"name"`
}

func NewUser(id int, name string) User {
    return User{
      ID:           id,
      Username:     name,
    }
}

// UserRepository
type UserRepository struct {
}

func NewUserRepository() UserRepository {
    return UserRepository{}
}

func (m UserRepository) GetUsers() []*User {
    var users []*User
    has, _ := db.GetUsers(&users)
    if has {
         return users
    }
    return nil
}

I implemented GetUsers() in controllers/user.goand I also created users table.
I have no idea why it says no field or method GetUsers.Someone give me an advice to solve this.

package controllers

import (
     "api-server/models"
)

type User struct {
}

func NewUser() User {
     return User{}
}

func (c User) GetUsers() interface{} {
     repo := models.NewUserRepository()
     user := repo.GetUsers()
     return user
}

Upvotes: 0

Views: 9670

Answers (2)

Jingchao Chen
Jingchao Chen

Reputation: 51

Tried to comment back to your question under Sergey's answer above, but I don't have the privilege since I'm new here.

As Sergey said, I cannot see GetUsers function in gorm.DB struct. If you do db.Raw("select * from users").Scan(&users), you cannot (don't need to either) assign two variables to the statement. Instead, just:

db.Raw("select * from users").Scan(&users)

This is because DB.Scan() returns only one result variable in your DB implementation:

// Scan scan value to a struct
func (s *DB) Scan(dest interface{}) *DB {
    return s.clone().NewScope(s.Value).Set("gorm:query_destination",dest).callCallbacks(s.parent.callbacks.queries).db
}

Updated answer after more context was added to the question:

That is because you didn't actually implement GetUsers for gorm.DB. What you did was - define a struct in controllers package named User, and attach a GetUsers method to that struct. Inside controllers/User.GetUsers you called repo.GetUsers which internally tries to call db.GetUsers. db is of type *gorm.DB which does not have GetUsers method defined.

One way to fix is as Sergey suggested, just do db.Raw(...).Scan(...).

If you really want to encapsulate gorm.DB and makes GetUsers look more native from the db connection, one thing you can try is:

type MyDB struct {
    gorm.DB
}
func (m *MyDB) GetUsers() []*Users {
    // do things like m.Raw(...).Scan(...)
}

And in your models, you declare db as type *MyDB instead of *gorm.DB.

For more official docs about this embedding technique, checkout https://golang.org/doc/effective_go.html#embedding

Upvotes: 1

user5627355
user5627355

Reputation:

If I see in your code I don't see GetUsers function db this *gorm.DB and not have GetUsers You need like this db..Raw("select * from users").Scan(&users)

Upvotes: 1

Related Questions