I am new to golang and trying to understand why I am getting this error.
Unresolved type 'models'
I have struct declared called Users, as follow:
package models
import (
"gorm.io/gorm"
"time"
)
type Utenti struct {
gorm.Model
ID int `json:"id"`
Name string `json:"name"`
Surname string `json:"surname"`
Email string `json:"email"`
Username string `json:"username"`
Password []byte `json:"-"`
}
when I try to use this model as a receiver in my auth process:
package authentication
import (
"github.com/user/repo/internal/models"
"golang.org/x/crypto/bcrypt"
)
// Encrypt the password before saving to the database
func (user *models.Utenti) HashPassword(password string) {
hashedPassword, _ := bcrypt.GenerateFromPassword([]byte(password), 14)
user.Password = hashedPassword
}
func (user *Utenti) ComparePassword(password string) bool {
err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password))
return err == nil
}
the *models.Utenti show the error Unresolved type 'models'
I am using Goland and I tried to invalidate caches, I cleared golang caches. The issue happens only in this specific package (authentication), I can call the models and use it in all other places but this package.
As a work around, I also created the struct in the same package and passed the models.Utenti, as follow:
type Utenti struct {
models.Utenti
}
and updated the above code to use *Utenti, this seems to have worked but in my actual code;
utenti := Utenti{
Name: data["name"].(string),
Surname: data["surname"].(string),
Email: strings.TrimSpace(data["email"].(string)),
//....
}
I am not able to access the Fields of the Struct.
At this point I am really confused and I am sure I missing some knowledge about using receivers from different packages etc.
If anyone can help me to understand this I will be grateful
How to reproduce:
Project Structure
├── cmd
│ └── server
│ └── main.go
├── db
│ └── db.go
├── db-init
├── go.mod
├── go.sum
└── internal
├── authentication
│ ├── auth.go
├── models
│ └── Utenti.go
in internal/models/Utenti.go
package models
import (
"gorm.io/gorm"
"time"
)
type Utenti struct {
gorm.Model
ID int `json:"id"`
Name string `json:"name"`
Surname string `json:"surname"`
Email string `json:"email"`
Username string `json:"username"`
Password []byte `json:"-"`
}
In internal/authentication/auth.go
package authentication
import (
"github.com/user/repo/internal/models"
"golang.org/x/crypto/bcrypt"
)
// Encrypt the password before saving to the database
func (user *models.Utenti) HashPassword(password string) {
hashedPassword, _ := bcrypt.GenerateFromPassword([]byte(password), 14)
user.Password = hashedPassword
}
func (user *models.Utenti) ComparePassword(password string) bool {
err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password))
return err == nil
}
With this you should see that the function HashPassword and ComparePassword, the (user *models.Utenti) is red and shows the mentioned error.
>Solution :
You have:
// Encrypt the password before saving to the database
func (user *models.Utenti) HashPassword(password string) {
hashedPassword, _ := bcrypt.GenerateFromPassword([]byte(password), 14)
user.Password = hashedPassword
}
But you can’t define a method on a type defined in another package. That’s why the weird error message: on the receiver func (user *models.Utenti), the thing after the receiver name must be a (not package-qualified) type.
It’s not clear what the "best" solution is, but perhaps you can just define a function:
// HashUtentiPassword updates the users password with a hashed version, to be used before saving to the database.
func HashUtentiPassword(user *models.Utenti, password string) {
hashedPassword, _ := bcrypt.GenerateFromPassword([]byte(password), 14)
user.Password = hashedPassword
}