Проблема с импортом модулей в golang

Я учу Go и пытаюсь сделать api. Проблема в том что когда я сохраняю проект (ctrl+s) в vscode он просто удаляет зависимость (стирает строку с импортом) если я делаю go run он возвращает undefined: api Что я делаю не так?

структура проекта

файлы

package api

import (
    "github.com/gofiber/fiber/v2"
    "./../db_driver"
)

func api() {
    app := fiber.New()

    app.Get("/list", func(c *fiber.Ctx) error {
        return db_driver.get_all_news()
    })

    app.Get("/:param", func(c *fiber.Ctx) error {
        return c.SendString("param: " + c.Params("param"))
    })

    app.Post("/", func(c *fiber.Ctx) error {
        return c.SendString("POST request")
    })

    app.Listen(":3000")

}
package db_driver

import (
    "database/sql"
    "fmt"
    "log"
    "os"

    _ "github.com/go-sql-driver/mysql"
    "github.com/joho/godotenv"
)

type News struct {
    ID         int64
    Title      string
    Content    string
    Categories []int64
}

type Categories struct {
    ID      int64
    News_ID int64
}

// init is invoked before main()
var db *sql.DB

func init() {

    godotenv.Load()

    user := os.Getenv("DB_USER")
    password := os.Getenv("DB_PASSWORD")

    var err error
    db, err = sql.Open("mysql", fmt.Sprintf("%s:%s@/reform", user, password))
    if err != nil {
        log.Fatal(err)
    }

}

func get_all_news() ([]News, error) {
    var news_list []News

    rows, err := db.Query("SELECT News.Id, News.Title, News.Content, (SELECT GROUP_CONCAT(NC.CategoryId) FROM NewsCategories NC WHERE NC.NewsId = News.Id) as Categories FROM News;")
    if err != nil {
        return nil, fmt.Errorf("get_list_news: %v", err)
    }
    defer rows.Close()
    for rows.Next() {
        var news News
        if err := rows.Scan(&news.ID, &news.Title, &news.Content, &news.Categories); err != nil {
            return nil, fmt.Errorf("get_list_news: %v", err)
        }
        news_list = append(news_list, news)
    }
    if err := rows.Err(); err != nil {
        return nil, fmt.Errorf("get_list_news: %v", err)
    }
    return news_list, nil
}

func push_one(news News) {
    result, err := db.Exec("INSERT INTO News (Title, Content) VALUES (?, ?)", news.Title, news.Content)
    if err != nil {
        fmt.Println("get_list_news: %v", err)
    }
    id, err := result.LastInsertId()
    if err != nil {
        fmt.Println("get_list_news: %v", err)
    }
    list_categories := news.Categories
    for _, value := range list_categories {
        _, err := db.Exec("INSERT INTO NewsCategories (NewsId, CategoryId) VALUES (?, ?)", id, value)
        if err != nil {
            fmt.Println("get_list_news: %v", err)
        }
    }
}
package main

import (
    "./api"
)

func main() {
    api.api()
}

файл go.work для main

go 1.18

use (
    ./api
)

для api

go 1.18

use ./../db_driver

Ответы (1 шт):

Автор решения: Pak Uula

VS Code удаляет импорт import "api" из-за того, что этот импорт не используется в вашем коде:

  • имя функции api() написано с маленькой буквы, что означает по правилам Го, это внутренняя функция пакета, недоступная извне
  • раз функция недоступна, её вызов VSCode игнорирует.
  • более нигде пакет api не используется, поэтому VSCode его спокойно выбрасывает.

Вам нужно переименовать в файле api.go функцию api() на Api(). Тогда import "api" перестанет исчезать.

Но вам это не поможет. В вашем проекте множество других проблем, из-за которых он не заработает: у вас три модуля, воркспейс, относительные пути импорта, вложенные воркспейсы, ошибки с именами, ошибки с обработкой ошибок.

Прежде всего, проблемы со структурой. Вам не нужны три модуля и два воркспейса. Достаточно одного модуля.

Как бы я делал ваш проект:

mkdir my-project
cd my-project
go mod init my-project
mkdir api
mkdir db_driver

затем скопировал бы api.go в ./api, db_driver.go в ./db_driver, main.go в ..

Поправил бы импорты:

  • в main.go: import my-project/api
  • в ./api/api.go: import my-project/db_driver

В режиме с модулями Го не разрешает использовать относительные в импорте, пути, нужны пути, включающие имя модуля. Модуль я назвал my-project, поэтому пути к пакетам должны быть my-project/api и my-prject/db_driver

Переименовал интерфейсные функции на заглавные:

  • api.go: api -> Api
  • db_driver.go: get_all_news -> GetAllNews, push_one -> PushOne

Затем обновил бы зависимости:

go mod tidy 

и можно запускать

go run .

и увидел бы что-то в таком духе


 ┌───────────────────────────────────────────────────┐ 
 │                   Fiber v2.52.0                   │ 
 │               http://127.0.0.1:3001               │ 
 │       (bound on host 0.0.0.0 and port 3001)       │ 
 │                                                   │ 
 │ Handlers ............. 5  Processes ........... 1 │ 
 │ Prefork ....... Disabled  PID ............ 680898 │ 
 └───────────────────────────────────────────────────┘ 

Работает )

Проект целиком: https://github.com/pakuula/StackOverflow/tree/main/go/1566782

→ Ссылка