Go 持续接收JSON并根据时间段写入磁盘的最佳方式

Go 持续接收JSON并根据时间段写入磁盘的最佳方式,go,Go,我很难想出一个解决方案来不断地接收JSON并将其附加到一个切片,然后根据设置的时间周期性地将其写入磁盘。我想出了一个解决方案,但是在没有任何同步的情况下读/写同一个片 package main import ( "encoding/json" "fmt" "io/ioutil" "runtime" "strconv" "time" ) type Message map[string]interface{} type Messages []Mes

我很难想出一个解决方案来不断地接收JSON并将其附加到一个切片,然后根据设置的时间周期性地将其写入磁盘。我想出了一个解决方案,但是在没有任何同步的情况下读/写同一个片

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "runtime"
    "strconv"
    "time"
)

type Message map[string]interface{}
type Messages []Message

var (
    messages Messages
)

func main() {
    c := make(chan Message)

    var messages Messages

    go func() {
        tick := time.Tick(200 * time.Millisecond)
        for {
            select {
            case <-tick:
                mb := []byte(`{ "glossary": { "title": "example glossary", "GlossDiv": { "title": "S", "GlossList": { "GlossEntry": { "ID": "SGML", "SortAs": "SGML", "GlossTerm": "Standard Generalized Markup Language", "Acronym": "SGML", "Abbrev": "ISO 8879:1986", "GlossDef": { "para": "A meta-markup language, used to create markup languages such as DocBook.", "GlossSeeAlso": ["GML", "XML"] }, "GlossSee": "markup" } } } } }`)
                var message Message
                json.Unmarshal(mb, &message)
                c <- message
            }
        }
    }()

    go func() {
        tick := time.Tick(30 * time.Second)

        for {
            select {
            case <-tick:
                content, _ := json.Marshal(messages)
                now := time.Now().Unix()
                filename := "test" + strconv.FormatInt(now, 10) + ".json"
                err := ioutil.WriteFile(filename, content, 0644)
                if err != nil {
                    panic(err)
                }

                messages = nil
            }
        }
    }()

    for {
        newmessage := <-c
        messages = append(messages, newmessage)
    }
}


主程序包
进口(
“编码/json”
“fmt”
“io/ioutil”
“运行时”
“strconv”
“时间”
)
键入消息映射[字符串]接口{}
键入Messages[]消息
变量(
信息
)
func main(){
c:=制造(成龙信息)
var消息
go func(){
滴答声:=时间滴答声(200*时间毫秒)
为了{
挑选{

case您的解决方案看起来不错,但同步部分除外:

var (
    messages Messages
    lock sync.Mutex
)

...
 newmessage := <-c
 lock.Lock()
 messages = append(messages, newmessage)
 lock.Unlock()
var(
信息
锁同步
)
...

newmessage:=您的解决方案看起来不错,但同步部分除外:

var (
    messages Messages
    lock sync.Mutex
)

...
 newmessage := <-c
 lock.Lock()
 messages = append(messages, newmessage)
 lock.Unlock()
var(
信息
锁同步
)
...

newmessage:=这是一个尽可能少锁定并尽量减少分配的版本。它也相对简单且可移植

它使用单一选择来避免额外的锁定机制,并异步写入json文件以防止阻塞使用者通道

有一个专用JSON WorkWorkWork,它阻止了在主选择中间需要一个附加的JIT同步机制的异步调用。 我还添加了正确完成程序所需的机制(即:关闭生产者、耗尽消费者、耗尽消息、等待磁盘刷新)

主程序包
进口(
“编码/json”
“日志”
“操作系统”
“操作系统/信号”
“同步”
“时间”
)
键入消息映射[字符串]接口{}
键入Messages[]消息
func main(){
c:=制造(成龙信息)
go func(){
滴答声:=时间滴答声(200*时间毫秒)
s:=制造(转换操作信号)
信号。通知
为了{
挑选{

case这是一个尽可能少锁定并尽量减少分配的版本。它也相对简单和可移植

它使用单一选择来避免额外的锁定机制,并异步写入json文件以防止阻塞使用者通道

有一个专用JSON WorkWorkWork,它阻止了在主选择中间需要一个附加的JIT同步机制的异步调用。 我还添加了正确完成程序所需的机制(即:关闭生产者、耗尽消费者、耗尽消息、等待磁盘刷新)

主程序包
进口(
“编码/json”
“日志”
“操作系统”
“操作系统/信号”
“同步”
“时间”
)
键入消息映射[字符串]接口{}
键入Messages[]消息
func main(){
c:=制造(成龙信息)
go func(){
滴答声:=时间滴答声(200*时间毫秒)
s:=制造(转换操作信号)
信号。通知
为了{
挑选{
案例
package main

import (
    "encoding/json"
    "log"
    "os"
    "os/signal"
    "sync"
    "time"
)

type Message map[string]interface{}
type Messages []Message

func main() {
    c := make(chan Message)

    go func() {
        tick := time.Tick(200 * time.Millisecond)
        s := make(chan os.Signal)
        signal.Notify(s)
        for {
            select {
            case <-s:
                close(c)
                return
            case <-tick:
                mb := []byte(`{ "glossary": { "title": "example glossary", "GlossDiv": { "title": "S", "GlossList": { "GlossEntry": { "ID": "SGML", "SortAs": "SGML", "GlossTerm": "Standard Generalized Markup Language", "Acronym": "SGML", "Abbrev": "ISO 8879:1986", "GlossDef": { "para": "A meta-markup language, used to create markup languages such as DocBook.", "GlossSeeAlso": ["GML", "XML"] }, "GlossSee": "markup" } } } } }`)
                var message Message
                json.Unmarshal(mb, &message)
                c <- message
            }
        }
    }()

    var msgPool = sync.Pool{
        New: func() interface{} {
            return Messages{}
        },
    }
    var wg sync.WaitGroup
    wg.Add(1)
    defer wg.Wait()
    cMessages := make(chan Messages)
    go func() {
        defer wg.Done()
        for messages := range cMessages {
            log.Println("saved", len(messages), "messages")
            // content, _ := json.Marshal(messages)
            // now := time.Now().Unix()
            // filename := "test" + strconv.FormatInt(now, 10) + ".json"
            // err := ioutil.WriteFile(filename, content, 0644)
            // if err != nil {
            //     log.Println(err)
            // }
            msgPool.Put(messages)
        }
    }()

    messages := msgPool.Get().(Messages)
    save := time.Tick(1 * time.Second)
    for {
        select {
        case newmessage, ok := <-c:
            if !ok {
                <-save
                cMessages <- messages
                close(cMessages)
                return
            }
            messages = append(messages, newmessage)
        case <-save:
            cMessages <- messages

            messages = msgPool.Get().(Messages)
            messages = messages[:0]
        }
    }
}