Web applications Go lang Web应用程序中的同步

Web applications Go lang Web应用程序中的同步,web-applications,concurrency,sqlite,synchronization,go,Web Applications,Concurrency,Sqlite,Synchronization,Go,我正在编写一个golang web应用程序。web应用程序访问文件系统(读写)和sqlite3数据库文件 问题1:如何在Go中同步文件系统访问 type DataObject struct { data []byte } func (*d DataObject) Write() { // // Synchronization ? // ioutil.WriteFile("file.name", d.data, 0644) // // Stop synch

我正在编写一个golang web应用程序。web应用程序访问文件系统(读写)和sqlite3数据库文件

问题1:如何在Go中同步文件系统访问

type DataObject struct {
  data []byte
}

func (*d DataObject) Write() {
   //
   // Synchronization ?
   //
   ioutil.WriteFile("file.name", d.data, 0644)
   //
   // Stop synchronization ?
   //
}

问题2:我是否需要同步sqlite3数据库文件访问

type SqlObject struct {
  sqldata string
}

func (*s SqlObject) Store() error {
  //
  // Open the file, do I need some sort of synchronization?
  //
  con, err := sqlite.Open("database/datafile.db")
  if err != nil {
    return err
  }
  defer con.Close()

  err = con.Exec("INSERT INTO data(sqldata) values(?)", s.sqldata)
  if err != nil {
    return err
  }
  return nil
}

我正在使用gosqlite3驱动程序()

问题1

该包提供锁和RWLock,用于以传统方式同步对资源的访问。虽然这没什么错,但我喜欢玩弄成语,所以我可能会做以下事情:

主程序包
输入“fmt”

func SyncFile(路径字符串)chan对于文件,它取决于您的应用程序。如果只有一个goroutine写入文件,则不需要这样做。如果不止一个,则取决于:

如果你在不同的过程(程序)之间进行协调,你可以使用(而且可能不会很有趣)

如果您正在协调程序中的多个goroutine,您可以使用或查看是否可以重新组织程序,以便只将一个例程写入文件,其他例程通过通道发送更新

对于SQLite,我相信最简单的方法就是保持一个SQLite连接打开,并使用来自各种Goroutine的连接;虽然它支持多个进程同时打开,并且如果您的系统执行多个并发读取,则可能会更快(它使用全局锁进行写入)。

1)您应该使用读/写互斥锁(在go std库中)。 代码看起来像:

import "sync" // http://golang.org/pkg/sync/
const (
    filename = "file.name"
)
var globalFileLock sync.RWMutex

type DataObject struct {
  data []byte
}

func (*d DataObject) Write() {
   globalFileLock.Lock()
   defer globalFileLock.Unlock()
   ioutil.WriteFile(filename, d.data, 0644)
}

func (*d DataObject) Read() {
   globalFileLock.RLock()
   defer globalFileLock.RUnlock()
   d.data = ioutil.ReadFile(filename)
}
2) 由于您还没有发布程序中的“导入”部分,我不知道您使用的是哪个sqlite驱动程序


如果您使用database/sql打开数据库连接,则驱动程序将提供Goroutine之间的并发控制。

我知道这是一个老问题,但由于我遇到了相同的“db锁”问题,并且有一个事务为我解决了这个问题,我想在这里提及它:

db, err := sql.Open("sqlite3", db_path)
if err != nil {
    log.Printf("Cannot connect to database: %s\n", err ) 
}
defer db.Close()
tx, _ := db.Begin() 
var value string
err = tx.QueryRow("SELECT X FROM Y").Scan(&value)
tx.Rollback() // or: tx.Commit()

你对问题2的回答是错误的。如果只打开一次数据库连接,则可以同时重复使用它。如果您不能,那么您的“数据库/sql”驱动程序实现有一个bug:谢谢您的回答@voidlogic那么,一旦我有了一个连接,我就可以一直使用它,并且有许多go例程在使用它?@Kiril:是的,如果你的应用程序创建了一个*sql.DB的实例,那么你就可以从许多GoRoutine中使用它,而无需在代码中进行任何额外的同步。如果您在执行此操作时遇到问题,请确保向SQL驱动程序实现者报告此问题,因为这意味着他们的实现不是恭维的/存在错误。您好,谢谢。我正在使用此驱动程序:。导入人:import“code.google.com/p/gosqlite/sqlite”谢谢。我假设Go中的web应用程序是并发的,并且每个请求都在一个新的Go例程中处理,因此我应该进行同步?是的,每个http请求都在其自己的goroutine中运行,因此您必须在它们之间进行同步,或者使用单独的“helper”goroutine(带通道)来处理需要序列化的事情。
db, err := sql.Open("sqlite3", db_path)
if err != nil {
    log.Printf("Cannot connect to database: %s\n", err ) 
}
defer db.Close()
tx, _ := db.Begin() 
var value string
err = tx.QueryRow("SELECT X FROM Y").Scan(&value)
tx.Rollback() // or: tx.Commit()