我花了一些时间尝试这样做,我认为我需要一个全局数组(不是切片),我想将其作为指针传递,而不是按值传递。接收指针的函数需要测试nil,如果为nil,则从磁盘读取数组,例如:"baForm,oOserr = ioutil。ReadFile(sFormName)"。调用函数可能会传递一个全局数组或一个本地数组到调用函数,我认为这些数组将被垃圾回收。
这样做的原因是我想要一个标准函数来从磁盘读取表单,并且常用的表单是全局存储的。尽管有些人是否认为有更好的方法,但我仍然想知道如何实现这一目标,即:a)具有全局或局部数组,b)不按值传递,c)全局数组将仅从磁盘读取一次,并且每次调用函数时都会读取本地数组。蒂亚。
通过阅读您的描述,我不明白为什么将指针传递给数组比传递切片更好 - 但这取决于您。
你可以像在 C 中一样传递指针 - 在声明中附加一个星号 ( *
),并在调用函数时将 & 符号 ( &
) 附加到值。
请记住,在 Go 中,数组大小是其类型的一部分。这意味着您的函数声明将嵌入数组大小,因此您不能使用任何不同大小的数组调用函数。仅此原因通常就足以保证使用切片而不是数组。
下面是一个基于使用计数维护动态表单缓冲区的示例程序。如果 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
映射。