我花了一些时间尝试这样做,我想我需要一个全局数组(不是切片),我想把它作为指针传递,而不是通过值。接收指针的函数需要测试nil,如果为nil,则使用例如:“baForm,oOserr = ioutil.ReadFile(sFormName)”从磁盘读取数组。调用函数可以传递一个全局数组或一个本地数组到调用函数,我认为它将被垃圾收集。
这样做的原因是我想要一个标准函数从磁盘读取表单,并且常用的表单是全局存储的。尽管有些人可能认为有更好的方法,但我仍然想知道如何实现这一点,即:a)具有全局或本地数组,b)不通过值,c)全局数组将只从磁盘读取一次每次调用函数时都会读取本地数组。 TIA。
答案 0 :(得分:1)
从阅读你的描述中,我看不出为什么将指针传递给数组比传递切片更好 - 但这取决于你。
您可以像在C中一样传递指针 - 将星号(*
)附加到声明中,并在调用函数时将符号(&
)置于值。
请记住,在Go中,数组大小是其类型的一部分。这意味着您的函数声明将嵌入数组大小,因此您无法使用任何不同大小的数组调用该函数。仅此原因通常足以保证使用切片而不是数组。
答案 1 :(得分:0)
这是一个示例程序,它根据使用次数维护动态表单缓冲区。如果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)
}
编辑:Map operations are not atomic.修改示例程序以使用互斥锁来同时访问forms
地图。