在Go语言中,可以通过自定义类型和结构体方法来实现以映射形式读写文件的功能。以下是一个完整的示例:
package main
import (
"bufio"
"encoding/json"
"fmt"
"os"
"sync"
)
// FileMap 自定义文件映射类型
type FileMap struct {
filePath string
data map[string]string
mu sync.RWMutex
}
// NewFileMap 创建新的FileMap实例
func NewFileMap(filePath string) (*FileMap, error) {
fm := &FileMap{
filePath: filePath,
data: make(map[string]string),
}
// 加载现有数据
if err := fm.load(); err != nil && !os.IsNotExist(err) {
return nil, err
}
return fm, nil
}
// Write 写入键值对
func (fm *FileMap) Write(key, value string) error {
fm.mu.Lock()
defer fm.mu.Unlock()
fm.data[key] = value
return fm.save()
}
// Read 读取键对应的值
func (fm *FileMap) Read(key string) (string, bool) {
fm.mu.RLock()
defer fm.mu.RUnlock()
value, exists := fm.data[key]
return value, exists
}
// load 从文件加载数据
func (fm *FileMap) load() error {
file, err := os.Open(fm.filePath)
if err != nil {
return err
}
defer file.Close()
decoder := json.NewDecoder(file)
return decoder.Decode(&fm.data)
}
// save 保存数据到文件
func (fm *FileMap) save() error {
file, err := os.Create(fm.filePath)
if err != nil {
return err
}
defer file.Close()
encoder := json.NewEncoder(file)
encoder.SetIndent("", " ")
return encoder.Encode(fm.data)
}
// Delete 删除键值对
func (fm *FileMap) Delete(key string) error {
fm.mu.Lock()
defer fm.mu.Unlock()
delete(fm.data, key)
return fm.save()
}
// GetAll 获取所有键值对
func (fm *FileMap) GetAll() map[string]string {
fm.mu.RLock()
defer fm.mu.RUnlock()
copied := make(map[string]string)
for k, v := range fm.data {
copied[k] = v
}
return copied
}
func main() {
// 创建FileMap实例
fm, err := NewFileMap("data.json")
if err != nil {
fmt.Printf("创建FileMap失败: %v\n", err)
return
}
// 写入数据
err = fm.Write("name", "Alice")
if err != nil {
fmt.Printf("写入失败: %v\n", err)
}
err = fm.Write("age", "30")
if err != nil {
fmt.Printf("写入失败: %v\n", err)
}
// 读取数据
if value, exists := fm.Read("name"); exists {
fmt.Printf("f.read(\"name\") = %s\n", value)
}
if value, exists := fm.Read("age"); exists {
fmt.Printf("f.read(\"age\") = %s\n", value)
}
// 读取不存在的键
if value, exists := fm.Read("nonexistent"); exists {
fmt.Println(value)
} else {
fmt.Println("键不存在")
}
// 获取所有数据
allData := fm.GetAll()
fmt.Printf("所有数据: %v\n", allData)
}
如果需要更简单的文本格式(非JSON),可以使用以下实现:
package main
import (
"bufio"
"fmt"
"os"
"strings"
"sync"
)
type TextFileMap struct {
filePath string
mu sync.RWMutex
}
func NewTextFileMap(filePath string) *TextFileMap {
return &TextFileMap{filePath: filePath}
}
func (tfm *TextFileMap) Write(key, value string) error {
tfm.mu.Lock()
defer tfm.mu.Unlock()
// 读取现有数据
data, err := tfm.readAll()
if err != nil && !os.IsNotExist(err) {
return err
}
// 更新数据
data[key] = value
// 写回文件
return tfm.writeAll(data)
}
func (tfm *TextFileMap) Read(key string) (string, bool) {
tfm.mu.RLock()
defer tfm.mu.RUnlock()
data, err := tfm.readAll()
if err != nil {
return "", false
}
value, exists := data[key]
return value, exists
}
func (tfm *TextFileMap) readAll() (map[string]string, error) {
file, err := os.Open(tfm.filePath)
if err != nil {
return nil, err
}
defer file.Close()
data := make(map[string]string)
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
parts := strings.SplitN(line, "=", 2)
if len(parts) == 2 {
data[parts[0]] = parts[1]
}
}
return data, scanner.Err()
}
func (tfm *TextFileMap) writeAll(data map[string]string) error {
file, err := os.Create(tfm.filePath)
if err != nil {
return err
}
defer file.Close()
writer := bufio.NewWriter(file)
for key, value := range data {
_, err := writer.WriteString(fmt.Sprintf("%s=%s\n", key, value))
if err != nil {
return err
}
}
return writer.Flush()
}
func main() {
f := NewTextFileMap("data.txt")
// 写入数据
f.Write("language", "Golang")
f.Write("version", "1.21")
// 读取数据
if value, exists := f.Read("language"); exists {
fmt.Printf("f.read(\"language\") = %s\n", value)
}
if value, exists := f.Read("version"); exists {
fmt.Printf("f.read(\"version\") = %s\n", value)
}
}
这两个示例分别展示了使用JSON格式和文本格式实现文件映射读写的方法。FileMap类型提供了Write和Read方法,完全符合你描述的使用方式。