Serhioromano
@Serhioromano
Web Developer

Почему в результате дублируются цифры?

Вот такой код

package main

import (
	"encoding/json"
	"fmt"
)

type Test1 map[string]interface{}

var c chan Test1

func main() {
	val := Test1{
		"s": 1,
		"w": 2,
	}

	c = make(chan Test1, 3)

	go run()

	for i := 0; i < 10; i++ {
		val["v"] = i

		c <- val
	}
}
func run() {
	for {
		a := <-c
		out, _ := json.Marshal(a)
		fmt.Println(string(out))
	}
}


Возращает

{"s":1,"v":3,"w":2}
{"s":1,"v":4,"w":2}
{"s":1,"v":4,"w":2}
{"s":1,"v":4,"w":2}
{"s":1,"v":4,"w":2}
{"s":1,"v":9,"w":2}
{"s":1,"v":9,"w":2}
{"s":1,"v":9,"w":2}
{"s":1,"v":9,"w":2}
{"s":1,"v":9,"w":2}


Почему порядок не 1,2,3,4, ну или рэндом не обязательно по порядку, но главно почему пропущены некотрые цифры. Как это справить не меняя структуры? Это просто небольшая реплика проблемы большой программы.

Короче есть цикл, у нем идет обработка данных и отправка в канал. Оптарляется структура. Большоая часть струтуры заполняется до цикла. В цикле много условий, если там дублировать то будет месево.
  • Вопрос задан
  • 129 просмотров
Пригласить эксперта
Ответы на вопрос 1
uvelichitel
@uvelichitel Куратор тега Go
habrahabr.ru/users/uvelichitel
Потому что map ссылочный тип и вы все время посылаете в канал ссылку на одну и ту же мапу. Нужно копировать map и посылать новую копию. (Ну или использовать не map а struct)
for i := 0; i < 10; i++ {
	// Create new map
	val1 := make(map[string]interface{})
	// Copy from the original map to the target map
	for key, value := range val {
		val1[key] = value
	}
	val1["v"] = i
	c <- val1
}

Play https://play.golang.org/p/eIxdPQfkzCi
Версия 0.1
Поскольку map ссылочный тип передавать его через канал - мало смысла. Можно защитить и синхронизировать простым sync.Mutex например так
package main
import (
	"encoding/json"
	"fmt"
	"sync"
)
type Test1 map[string]interface{}
var R sync.Mutex
var W sync.Mutex
var val = Test1{
	"s": 1,
	"w": 2,
}
func main() {
	R.Lock()
	go run()
	for i := 0; i < 10; i++ {
		W.Lock()
		val["v"] = i
		R.Unlock()
	}
}
func run() {
	for {
		R.Lock()
		out, _ := json.Marshal(val)
		fmt.Println(string(out))
		W.Unlock()
	}
}

Playground https://play.golang.org/p/0uAOlhZuqjL
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы