Всем привет! Я новичок в Go. Задача такая: во вход передаются данные, хешируются и передаются дальше в функцию MultiHash, дальше MultiHash должна их прочесть еще раз захешировать и передать следующей функции. Попытка реализовать pipeline. Анонимная функция в функции main, пытается прочесть данные и у нее это получается, но после прочтения всех данных программа все равно впадает в deadlock.
В этой статье сказано, что программа впадает в deadlock если мы пытаемся прочесть данные через range, если канал не закрыт. Правильно ли считаю, что у меня такая же ошибка? Я все перепробовал и бесконечный цикл и select и закрывать канал, если закрывать в MultiHash, у меня возникает паника. Могли бы вы объяснить в чем моя ошибка и как исправить?
signer.go
package main
import (
"fmt"
"os"
"strconv"
"sync"
)
// сюда писать код
func SingleHash(wg *sync.WaitGroup, done chan interface{}, in []string) {
defer close(done)
defer wg.Done()
fmt.Println(in)
wgsh := &sync.WaitGroup{}
mu := &sync.Mutex{}
for _, i := range in {
wgsh.Add(1)
go workerSingleHash(wgsh, mu, i, done)
}
wgsh.Wait()
fmt.Println("end singlehash")
}
func workerSingleHash(wg *sync.WaitGroup, mu *sync.Mutex, in string, done chan interface{}) {
defer wg.Done()
crc32Chan := make(chan string)
mu.Lock()
md5Data := DataSignerMd5(in)
mu.Unlock()
go asyncCrc32Signer(in, crc32Chan)
crc32Data := <-crc32Chan
crc32Md5Data := DataSignerCrc32(md5Data)
done <- crc32Data + "~" + crc32Md5Data
}
func asyncCrc32Signer(data string, out chan string) {
//defer close(out)
out <- DataSignerCrc32(data)
}
func MultiHash(wg *sync.WaitGroup, done chan interface{}, done2 chan string) chan string {
wgD := &sync.WaitGroup{}
defer wg.Done()
j := 0
for v := range done {
fmt.Println("v: ", v)
str := fmt.Sprintf("%v", v)
wgD.Add(1)
go asyncWorker(wgD, j, str, done2)
j++
}
wgD.Wait()
return done2
}
func asyncWorker(wgDone2 *sync.WaitGroup, increment int, in string, done2 chan string) {
wgDone2.Done()
j := strconv.Itoa(increment)
done2 <- DataSignerCrc32(j + in)
}
func main() {
wg := &sync.WaitGroup{}
wg.Add(2)
done := make(chan interface{})
done2 := make(chan string)
in := os.Args
go SingleHash(wg, done, in[1:])
result := MultiHash(wg, done, done2)
func(done2 chan string) {
for v := range done2 {
fmt.Println("combine result: ", v)
}
}(result)
wg.Wait()
fmt.Println("end")
}
Это функции которые хешируют, DataSignerCrc32 нельзя использовать сраза одну за одной, так как случается перегрев, их нужно распараллелить. этот файл не мой - это условие и я с ним справился, но проблема не в этом, просто выкладываю, что б могли понять что это за функции
common.go
package main
import (
"crypto/md5"
"fmt"
"hash/crc32"
"strconv"
"sync/atomic"
"time"
)
type job func(in, out chan interface{})
const (
MaxInputDataLen = 100
)
var (
dataSignerOverheat uint32 = 0
DataSignerSalt = ""
)
var OverheatLock = func() {
for {
if swapped := atomic.CompareAndSwapUint32(&dataSignerOverheat, 0, 1); !swapped {
fmt.Println("OverheatLock happend")
time.Sleep(time.Second)
} else {
break
}
}
}
var OverheatUnlock = func() {
for {
if swapped := atomic.CompareAndSwapUint32(&dataSignerOverheat, 1, 0); !swapped {
fmt.Println("OverheatUnlock happend")
time.Sleep(time.Second)
} else {
break
}
}
}
var DataSignerMd5 = func(data string) string {
OverheatLock()
defer OverheatUnlock()
data += DataSignerSalt
dataHash := fmt.Sprintf("%x", md5.Sum([]byte(data)))
time.Sleep(10 * time.Millisecond)
return dataHash
}
var DataSignerCrc32 = func(data string) string {
data += DataSignerSalt
crcH := crc32.ChecksumIEEE([]byte(data))
dataHash := strconv.FormatUint(uint64(crcH), 10)
time.Sleep(time.Second)
return dataHash
}
OUT:
[3 4 5 6]
v: 4088798008~2157876746
v: 498629140~3068393833
v: 2226203566~3690458478
v: 1842515611~1684880638
end singlehash
combine result: 1341606222
combine result: 4202847257
combine result: 966776312
combine result: 1549563179
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main.func1(0xc000086120)
C:/Users/engis/OneDrive/Рабочий стол/Go-learn-master/Go-learn-master/hw2_signer/signer.go:91 +0xe5
main.main()
C:/Users/engis/OneDrive/Рабочий стол/Go-learn-master/Go-learn-master/hw2_signer/signer.go:94 +0x13b
exit status 2