Использование структуры из другого пакета в методе
Всем привет. У меня есть несколько пакетов в проекте
Пакет models содержит
type User_JSON struct {
UID string `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
Dob string `json:"dob"`
}
Пакет db содержит
func New_user(user models.User_JSON) (bool, models.User_JSON) {
defer tools.Panic_recover("inserting user in db")
id, err := bcrypt.GenerateFromPassword([]byte(user.UID), 2)
tools.Errors("bcryprgenerate(generating uid)", err)
user.UID = string(id)
conn := Connect(tools.Home() + ".conn_config.yaml")
tx := conn.Table("users").Create(&user)
return tx.Error == nil, user
}
Мне нужно для обьекта User_JSON реализовать метод New()
Я перехожу в третий пакет(api) и делаю там
func NewUser(w http.ResponseWriter, r *http.Request) {
user := models.User_JSON{
UID: "123",
Name: "testname",
Email: "test@email",
Dob: "22-03-1990",
}
user.New() //и, соответственно здесь тоже ругается
}
func (user models.User_JSON) New() { //здесь ругается на user (invalid receiver models.User_JSON (type not defined in this package))
db.New_user(user)
}
Мне, конечно, хотелось бы оставить метод New()в models но тогда cicle import Я нагуглил что нельзя делать методы для структур находящихся в других пакетах. А как же тогда быть, если я не могу делать метод в пакете со структурой так как это 100% приведет к cicle import, не хочу плодить в разных пакетах одну и ту же структуру(User_JSON)
Ответы (2 шт):
У вас конфликтует имя типа и имя переменной с этим же типом (тип не имеет метода New). Например, назовите переменную user_
Вас могут выручить интерфейсы. Ваш model/User_JSON не должен зависеть от db напрямую. Ему подойдёт любая штука, которая умеет New_user(user User_JSON) (bool, models.User_JSON). Интерфейс надо объявить в том же пакете, который его использует (а не в том, который его реализует). После этого ваш пакет model не будет зависеть от пакета db.
Небольшой пример
package foo
type A struct {
Name string
}
type bInterface interface {
B(a A) string
}
func (a A) CallB(b bInterface) string {
return b.B(a)
}
package bar
import "so/goImportCycle/foo"
type B struct {}
func (b B) B(a foo.A) string {
return a.Name
}
package main
import (
"fmt"
"so/goImportCycle/foo"
"so/goImportCycle/bar"
)
func main() {
a := foo.A{"Foo"}
b := bar.B{}
fmt.Println(a.CallB(b))
}