Go: вызов функции, передающей указатель на массив - PullRequest
2 голосов
/ 19 мая 2011

Я потратил немного времени, пытаясь сделать это, и я думаю, что мне нужен глобальный массив (не слайс), и я хочу передать его как указатель, а не по значению.Функция, получающая указатель, должна проверить на nil, и, если nil, прочитать массив с диска, используя, например: «baForm, oOserr = ioutil.ReadFile (sFormName)».Вызывающая функция может передавать либо глобальный массив, либо локальный массив вызывающей функции, которая, как я полагаю, будет собирать мусор.

Причина этого заключается в том, что я хочу, чтобы стандартная функция считывала формы с диска,и часто используемые формы хранятся по всему миру.Несмотря на то, что некоторые думают, что есть лучший способ, я все же хочу знать, как этого добиться, а именно: а) иметь глобальный или локальный массив, б) не передавать по значению, в) глобальные массивы будут считываться только один раз с диска илокальные массивы будут читаться при каждом вызове функции.ТИА.

Ответы [ 2 ]

1 голос
/ 19 мая 2011

Прочитав ваше описание, я не могу понять, почему передача указателя на массив лучше, чем передача фрагмента, но решать вам.

Вы можете передать указатель так же, как вы делаете это в C - прикрепите звездочку (*) к объявлению и добавьте амперсанд (&) к значению при вызове функции.

Просто помните, что в Go размер массива является частью его типа. Это означает, что объявление вашей функции будет иметь встроенный размер массива, поэтому вы не можете вызывать функцию, используя массив любого другого размера. Одной только этой причины обычно достаточно для использования среза вместо массива.

0 голосов
/ 19 мая 2011

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

package main

import (
    "fmt"
    "io/ioutil"
    "math"
    "os"
    "sync"
)

type Form struct {
    Name     string
    useCount int64
    Data     []byte
}

// The capacity of the forms buffer.
const formsCap = 2

// The forms buffer.
var (
    forms     = make(map[string]*Form, formsCap)
    formsLock sync.RWMutex
)

func ReadForm(name string) (form *Form, err os.Error) {
    formsLock.RLock()
    form, ok := forms[name]
    formsLock.RUnlock()
    if !ok {
            form = &Form{name, 0, nil}
    }
    if form.Data == nil {
        data, err := ioutil.ReadFile(name + ".form")
        if err != nil {
            return nil, err
        }
        form = &Form{name, 0, data}
        formsLock.Lock()
        if len(forms) >= formsCap {
            minForm := &Form{useCount: math.MaxInt64}
            for i, f := range forms {
                if f.useCount < minForm.useCount {
                    minForm = f
                }
            }
            minform.Data = nil
        }
        forms[name] = form
        formsLock.Unlock()
    }
    form.useCount++
    return form, nil
}

func main() {
    // form files are named name.form e.g. form1.form
    for _, name := range []string{"form1", "form2", "form3"} {
        f, err := ReadForm(name)
        if err != nil {
            fmt.Println(err)
        } else {
            fmt.Println(string(f.Data))
        }
    }
    fmt.Println(len(forms), forms)
}

РЕДАКТИРОВАТЬ: Операции на карте не являются атомарными. Пересмотреть пример программы, чтобы использовать мьютекс для одновременного доступа к карте forms.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...