Использование структуры из другого пакета в методе

Всем привет. У меня есть несколько пакетов в проекте

Пакет 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 шт):

Автор решения: prospero78su

У вас конфликтует имя типа и имя переменной с этим же типом (тип не имеет метода 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))
    
}

→ Ссылка