Как правильно вынести map/массив в отдельный пакет?

В Go есть несколько способов вынести map или массив в отдельный пакет. В данном ответе я расскажу о наиболее распространенных подходах.

Первый подход - создание отдельной структуры данных, которая будет содержать ваш map или массив. Для начала вы можете определить новый тип данных, который будет представлять вашу структуру:

type MyData struct {
    myMap map[string]int
    myArray []string
}

Затем вы можете определить методы для работы с этой структурой:

func (d *MyData) AddToMap(key string, value int) {
    d.myMap[key] = value
}

func (d *MyData) GetFromMap(key string) int {
    return d.myMap[key]
}

func (d *MyData) AddToArray(item string) {
    d.myArray = append(d.myArray, item)
}

func (d *MyData) GetFromArray(index int) string {
    return d.myArray[index]
}

Затем вы можете разместить эту структуру в отдельном пакете, создав файл mydata.go с таким содержимым:

package mypackage

type MyData struct {
    myMap map[string]int
    myArray []string
}

func (d *MyData) AddToMap(key string, value int) {
    d.myMap[key] = value
}

func (d *MyData) GetFromMap(key string) int {
    return d.myMap[key]
}

func (d *MyData) AddToArray(item string) {
    d.myArray = append(d.myArray, item)
}

func (d *MyData) GetFromArray(index int) string {
    return d.myArray[index]
}

Затем в вашем основном коде вы можете импортировать пакет mypackage и использовать его:

package main

import (
    "fmt"
    "mypackage"
)

func main() {
    data := mypackage.MyData{
        myMap: make(map[string]int),
        myArray: []string{},
    }

    data.AddToMap("key1", 1)
    data.AddToArray("item1")

    fmt.Println(data.GetFromMap("key1")) // Выведет 1
    fmt.Println(data.GetFromArray(0)) // Выведет item1
}

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

package mypackage

type MyData interface {
    AddToMap(key string, value int)
    GetFromMap(key string) int
    AddToArray(item string)
    GetFromArray(index int) string
}

Далее вы можете разместить реализацию этого интерфейса в отдельном файле mydata.go:

package mypackage

type myDataImpl struct {
    myMap map[string]int
    myArray []string
}

func (d *myDataImpl) AddToMap(key string, value int) {
    d.myMap[key] = value
}

func (d *myDataImpl) GetFromMap(key string) int {
    return d.myMap[key]
}

func (d *myDataImpl) AddToArray(item string) {
    d.myArray = append(d.myArray, item)
}

func (d *myDataImpl) GetFromArray(index int) string {
    return d.myArray[index]
}

func NewMyData() MyData {
    return &myDataImpl{
        myMap: make(map[string]int),
        myArray: []string{},
    }
}

Затем в вашем основном коде вы можете создать новый экземпляр интерфейса MyData с помощью функции NewMyData:

package main

import (
    "fmt"
    "mypackage"
)

func main() {
    data := mypackage.NewMyData()

    data.AddToMap("key1", 1)
    data.AddToArray("item1")

    fmt.Println(data.GetFromMap("key1")) // Выведет 1
    fmt.Println(data.GetFromArray(0)) // Выведет item1
}

Оба подхода имеют свои преимущества и недостатки, и выбор зависит от конкретной задачи. В первом подходе вы получаете полный контроль над структурой данных, но код может быть сложнее для понимания и использования. Во втором подходе код становится более абстрактным, но вы получаете гибкость в использовании разных реализаций интерфейса MyData.