一个 map 数据竞争的实际问题

并发请求go写的接口程序就会出现fatal error: concurrent map read and map write

地址:https://segmentfault.com/q/1010000020650005/a-1020000020661018

标签:Go

详情描述

这是别人破解的谷歌翻译接口,我用go再次封装成api供我并发调用,然而就会用并发请求后,就会出现fatal error: concurrent map read and map write错误

atal error: concurrent map read and map write

goroutine 280 [running]:
runtime.throw(0xccee49, 0x21)
    /usr/local/go/src/runtime/panic.go:774 +0x72 fp=0xc00057d898 sp=0xc00057d868 pc=0x42f3e2
runtime.mapaccess2_faststr(0xbb0da0, 0xc00017b050, 0xc000529000, 0x1, 0xa7a6cc, 0xb87640)
    /usr/local/go/src/runtime/map_faststr.go:116 +0x48f fp=0xc00057d908 sp=0xc00057d898 pc=0x41452f
github.com/robertkrimen/otto.(*_dclStash).hasBinding(0xc00017b020, 0xc000529000, 0x1, 0x0)
    /go/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/stash.go:159 +0x4f fp=0xc00057d948 sp=0xc00057d908 pc=0xa8844f
github.com/robertkrimen/otto.getIdentifierReference(0xc000222180, 0xe20b20, 0xc00017b020, 0xc000529000, 0x1, 0x0, 0x201, 0x8, 0x203000)
    /go/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/type_reference.go:99 +0x52 fp=0xc00057d9a0 sp=0xc00057d948 pc=0xa95682
github.com/robertkrimen/otto.(*_runtime).cmpl_evaluate_nodeExpression(0xc000222180, 0xdff260, 0xc000481f20, 0x8, 0xbe7b80, 0xc000574030)
    /go/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/cmpl_evaluate_expression.go:69 +0x11e fp=0xc00057da58 sp=0xc00057d9a0 pc=0xa2ebbe
github.com/robertkrimen/otto.(*_runtime).cmpl_evaluate_nodeCallExpression(0xc000222180, 0xc0001830b0, 0x0, 0x0, 0x0, 0x1, 0xc000528f00, 0x1f0)
    /go/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/cmpl_evaluate_expression.go:193 +0x12c fp=0xc00057dce8 sp=0xc00057da58 pc=0xa307bc
github.com/robertkrimen/otto.(*_runtime).cmpl_evaluate_nodeExpression(0xc000222180, 0xdff120, 0xc0001830b0, 0xc000528fef, 0x1, 0x0)
    /go/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/cmpl_evaluate_expression.go:44 +0x583 fp=0xc00057dda0 sp=0xc00057dce8 pc=0xa2f023
github.com/robertkrimen/otto.(*_runtime).cmpl_evaluate_nodeVariableExpression(0xc000222180, 0xc0001830e0, 0xa953d7, 0x40a6fb, 0xc000380000)
    /go/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/cmpl_evaluate_expression.go:454 +0xf0 fp=0xc00057de08 sp=0xc00057dda0 pc=0xa335a0
github.com/robertkrimen/otto.(*_runtime).cmpl_evaluate_nodeStatement(0xc000222180, 0xdff440, 0xc000481ee0, 0x0, 0x0, 0x0)
    /go/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/cmpl_evaluate_statement.go:103 +0x12a fp=0xc00057e010 sp=0xc00057de08 pc=0xa3372a
github.com/robertkrimen/otto.(*_runtime).cmpl_evaluate_nodeForStatement(0xc000222180, 0xc0001ae460, 0xc000182f30, 0x2, 0xb86880)
    /go/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/cmpl_evaluate_statement.go:263 +0x23f fp=0xc00057e118 sp=0xc00057e010 pc=0xa3568f
github.com/robertkrimen/otto.(*_runtime).cmpl_evaluate_nodeStatement(0xc000222180, 0xdff220, 0xc0001ae460, 0x0, 0x0, 0x0)
    /go/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/cmpl_evaluate_statement.go:68 +0x11ba fp=0xc00057e320 sp=0xc00057e118 pc=0xa347ba
github.com/robertkrimen/otto.(*_runtime).cmpl_evaluate_nodeStatementList(0xc000222180, 0xc00036e000, 0xf, 0xf, 0x7, 0x0, 0x1)
    /go/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/cmpl_evaluate_statement.go:121 +0x8e fp=0xc00057e388 sp=0xc00057e320 pc=0xa349be
github.com/robertkrimen/otto.(*_runtime).cmpl_evaluate_nodeStatement(0xc000222180, 0xdff0c0, 0xc000481660, 0x0, 0x0, 0x0)
    /go/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/cmpl_evaluate_statement.go:30 +0x587 fp=0xc00057e590 sp=0xc00057e388 pc=0xa33b87
github.com/robertkrimen/otto.(*_runtime).cmpl_call_nodeFunction(0xc000222180, 0xc0000745a0, 0xc000168f00, 0xc0002d6a00, 0x5, 0xc991a0, 0xc0001989c0, 0xc000407d40, 0x1, 0x1, ...)
    /go/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/cmpl_evaluate.go:61 +0x48c fp=0xc00057e640 sp=0xc00057e590 pc=0xa2e6cc
github.com/robertkrimen/otto.(*_object).call(0xc0000745a0, 0x5, 0xc991a0, 0xc0001989c0, 0xc000407d40, 0x1, 0x1, 0x0, 0x0, 0x0, ...)
    /go/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/type_function.go:226 +0xa8a fp=0xc00057ea58 sp=0xc00057e640 pc=0xa8f8ba
github.com/robertkrimen/otto.(*_runtime).cmpl_evaluate_nodeCallExpression(0xc000222180, 0xc000182180, 0x0, 0x0, 0x0, 0xb87400, 0x1, 0xc0004dcc90)
    /go/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/cmpl_evaluate_expression.go:244 +0x47a fp=0xc00057ece8 sp=0xc00057ea58 pc=0xa30b0a
github.com/robertkrimen/otto.(*_runtime).cmpl_evaluate_nodeExpression(0xc000222180, 0xdff120, 0xc000182180, 0xb87640, 0xc0004dcc90, 0xc00057ee10)
    /go/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/cmpl_evaluate_expression.go:44 +0x583 fp=0xc00057eda0 sp=0xc00057ece8 pc=0xa2f023
github.com/robertkrimen/otto.(*_runtime).cmpl_evaluate_nodeStatement(0xc000222180, 0xdff1e0, 0xc0004dc730, 0x0, 0x0, 0x0)
    /go/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/cmpl_evaluate_statement.go:62 +0xf10 fp=0xc00057efa8 sp=0xc00057eda0 pc=0xa34510
github.com/robertkrimen/otto.(*_runtime).cmpl_evaluate_nodeStatementList(0xc000222180, 0xc0001ae2d0, 0x5, 0x5, 0xc00057f0f0, 0xa3b2c8, 0xb87640)
    /go/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/cmpl_evaluate_statement.go:121 +0x8e fp=0xc00057f010 sp=0xc00057efa8 pc=0xa349be
github.com/robertkrimen/otto.(*_runtime).cmpl_evaluate_nodeProgram(0xc000222180, 0xc000110150, 0xc000110100, 0x0, 0x0, 0x0)
    /go/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/cmpl_evaluate.go:17 +0x10b fp=0xc00057f0a0 sp=0xc00057f010 pc=0xa2e0cb
github.com/robertkrimen/otto.(*_runtime).cmpl_runOrEval.func1()
    /go/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/runtime.go:767 +0x44 fp=0xc00057f0e8 sp=0xc00057f0a0 pc=0xaa6db4
github.com/robertkrimen/otto.catchPanic(0xc00057f1a8, 0x0, 0x0)
    /go/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/error.go:251 +0x5f fp=0xc00057f138 sp=0xc00057f0e8 pc=0xa3cc5f
github.com/robertkrimen/otto.(*_runtime).cmpl_runOrEval(0xc000222180, 0xb87640, 0xdec1e0, 0x0, 0x0, 0xc000222100, 0xcc0f37, 0xb, 0x3, 0xb87640, ...)
    /go/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/runtime.go:766 +0x10f fp=0xc00057f1e0 sp=0xc00057f138 pc=0xa86c2f
github.com/robertkrimen/otto.(*_runtime).cmpl_run(...)
    /go/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/runtime.go:779
github.com/robertkrimen/otto.Otto.Run(0x0, 0xc000222180, 0xb87640, 0xdec1e0, 0xcaa3a0, 0xc0003e8360, 0x0, 0x0, 0x0)
    /go/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/otto.go:295 +0x53 fp=0xc00057f248 sp=0xc00057f1e0 pc=0xa7b503
github.com/bregydoc/gtranslate.sM(0x3, 0xb87640, 0xc0004dc1a0, 0xc0002f9320, 0x1, 0x1, 0x0, 0x0, 0xb87640, 0xc0004dc1a0, ...)
    /go/pkg/mod/github.com/bregydoc/gtranslate@v0.0.0-20190803100511-2942db9d3610/token.go:29 +0x19a fp=0xc00057f2c8 sp=0xc00057f248 pc=0xaaf85a
github.com/bregydoc/gtranslate.get(0x3, 0xb87640, 0xc0004dc1a0, 0x3, 0xb87640, 0xc00019d210, 0x0, 0x0)
    /go/pkg/mod/github.com/bregydoc/gtranslate@v0.0.0-20190803100511-2942db9d3610/token.go:144 +0xce fp=0xc00057f348 sp=0xc00057f2c8 pc=0xaafe7e
github.com/bregydoc/gtranslate.translate(0xc0001da440, 0x20, 0xcbae36, 0x4, 0xc0002e8cad, 0x2, 0xc000178401, 0x2, 0x0, 0x413d5e, ...)
    /go/pkg/mod/github.com/bregydoc/gtranslate@v0.0.0-20190803100511-2942db9d3610/apiv2.go:49 +0x116 fp=0xc00057f688 sp=0xc00057f348 pc=0xaadf86
github.com/bregydoc/gtranslate.TranslateWithParams(0xc0001da440, 0x20, 0xcbae36, 0x4, 0xc0002e8cad, 0x2, 0x0, 0x0, 0xc0004ba4e0, 0xcbe553, ...)
    /go/pkg/mod/github.com/bregydoc/gtranslate@v0.0.0-20190803100511-2942db9d3610/gtranslate.go:28 +0x92 fp=0xc00057f710 sp=0xc00057f688 pc=0xaaf622
main.language_recognition(0xc0001da440, 0x20, 0xc0002e8cad, 0x2, 0x2, 0xc0002e8cad, 0x2, 0x40, 0x40, 0xc6c6c0)
    /go/src/uploads_image/save_to_redis2.go:159 +0xca fp=0xc00057f7e0 sp=0xc00057f710 pc=0xb0fa9a
main.main.func3(0xc0000b82c0)
    /go/src/uploads_image/save_to_redis2.go:84 +0x284 fp=0xc00057f898 sp=0xc00057f7e0 pc=0xb10b74
github.com/gin-gonic/gin.(*Context).Next(0xc0000b82c0)
    /go/pkg/mod/github.com/gin-gonic/gin@v1.4.0/context.go:124 +0x3b fp=0xc00057f8b8 sp=0xc00057f898 pc=0x996ccb
github.com/gin-gonic/gin.RecoveryWithWriter.func1(0xc0000b82c0)
    /go/pkg/mod/github.com/gin-gonic/gin@v1.4.0/recovery.go:83 +0x64 fp=0xc00057f918 sp=0xc00057f8b8 pc=0x9a9f04
github.com/gin-gonic/gin.(*Context).Next(0xc0000b82c0)
    /go/pkg/mod/github.com/gin-gonic/gin@v1.4.0/context.go:124 +0x3b fp=0xc00057f938 sp=0xc00057f918 pc=0x996ccb
github.com/gin-gonic/gin.LoggerWithConfig.func1(0xc0000b82c0)
    /go/pkg/mod/github.com/gin-gonic/gin@v1.4.0/logger.go:240 +0xe1 fp=0xc00057fad8 sp=0xc00057f938 pc=0x9a8fb1
github.com/gin-gonic/gin.(*Context).Next(0xc0000b82c0)
    /go/pkg/mod/github.com/gin-gonic/gin@v1.4.0/context.go:124 +0x3b fp=0xc00057faf8 sp=0xc00057fad8 pc=0x996ccb
github.com/gin-gonic/gin.(*Engine).handleHTTPRequest(0xc0001cf400, 0xc0000b82c0)
    /go/pkg/mod/github.com/gin-gonic/gin@v1.4.0/gin.go:389 +0x5b2 fp=0xc00057fbe0 sp=0xc00057faf8 pc=0x9a0582
github.com/gin-gonic/gin.(*Engine).ServeHTTP(0xc0001cf400, 0xe103a0, 0xc000274380, 0xc0000f6300)
    /go/pkg/mod/github.com/gin-gonic/gin@v1.4.0/gin.go:351 +0x134 fp=0xc00057fc18 sp=0xc00057fbe0 pc=0x99fdb4
net/http.serverHandler.ServeHTTP(0xc000292000, 0xe103a0, 0xc000274380, 0xc0000f6300)
    /usr/local/go/src/net/http/server.go:2802 +0xa4 fp=0xc00057fc48 sp=0xc00057fc18 pc=0x6d17a4
net/http.(*conn).serve(0xc000594140, 0xe12920, 0xc00016c9c0)
    /usr/local/go/src/net/http/server.go:1890 +0x875 fp=0xc00057ffc8 sp=0xc00057fc48 pc=0x6cd045
runtime.goexit()
    /usr/local/go/src/runtime/asm_amd64.s:1357 +0x1 fp=0xc00057ffd0 sp=0xc00057ffc8 pc=0x45be61
created by net/http.(*Server).Serve
    /usr/local/go/src/net/http/server.go:2927 +0x38e

我的回答

这是一个实际案例的问题。先吐槽一句,我挺服气自己的,这种问题,我也答,真的是棒棒的。

先吐槽一句,我挺服气自己的,这种问题,我也答,真的是棒棒的。

问题已经很明白了,我测试了下这个包,确认有个问题。它里面使用了 otto 的 javascript 解析库。

测试代码非常简单。

package main

import (
	"fmt"
	"sync"

	"github.com/bregydoc/gtranslate"
)

func main() {
	params := gtranslate.TranslationParams{
		From: "en",
		To:   "zh",
	}

	wg := sync.WaitGroup{}

	for i := 0; i < 1000; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			fmt.Println(gtranslate.TranslateWithParams("I'm alive", params))
		}()
	}

	wg.Wait()
}

运行起来偶尔会报如下的错误:

WARNING: DATA RACE
Read at 0x00c0001a0b20 by goroutine 220:
  github.com/robertkrimen/otto.objectGetOwnProperty()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/object.go:127 +0xba
  github.com/robertkrimen/otto.objectGetProperty()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/object.go:32 +0x86
  github.com/robertkrimen/otto.objectHasProperty()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/object.go:37 +0x8b
  github.com/robertkrimen/otto.(*_objectStash).hasBinding()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/object.go:57 +0xa8
  github.com/robertkrimen/otto.(*_runtime).cmpl_functionDeclaration()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/cmpl_evaluate.go:77 +0x19a
  github.com/robertkrimen/otto.(*_runtime).cmpl_evaluate_nodeProgram()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/cmpl_evaluate.go:14 +0xb1
  github.com/robertkrimen/otto.(*_runtime).cmpl_runOrEval.func1()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/runtime.go:767 +0x5f
  github.com/robertkrimen/otto.catchPanic()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/error.go:251 +0x66
  github.com/robertkrimen/otto.(*_runtime).cmpl_runOrEval()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/runtime.go:766 +0x131
  github.com/robertkrimen/otto.Otto.Run()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/runtime.go:779 +0x78
  github.com/bregydoc/gtranslate.sM()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/bregydoc/gtranslate@v0.0.0-20190803100511-2942db9d3610/token.go:29 +0x266
  github.com/bregydoc/gtranslate.get()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/bregydoc/gtranslate@v0.0.0-20190803100511-2942db9d3610/token.go:136 +0xec
  github.com/bregydoc/gtranslate.translate()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/bregydoc/gtranslate@v0.0.0-20190803100511-2942db9d3610/apiv2.go:47 +0x175
  github.com/bregydoc/gtranslate.TranslateWithParams()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/bregydoc/gtranslate@v0.0.0-20190803100511-2942db9d3610/gtranslate.go:28 +0xb0
  main.main.func1()
      /Users/polo/gomodules/translate/main.go:22 +0xdc

Previous write at 0x00c0001a0b20 by goroutine 184:
  [failed to restore the stack]

Goroutine 220 (running) created at:
  main.main()
      /Users/polo/gomodules/translate/main.go:20 +0x14d

Goroutine 184 (running) created at:
  main.main()
      /Users/polo/gomodules/translate/main.go:20 +0x14d
==================
==================
WARNING: DATA RACE
Read at 0x00c0001a0f58 by goroutine 220:
  github.com/robertkrimen/otto.objectGetOwnProperty()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/object.go:127 +0xba
  github.com/robertkrimen/otto.objectGetProperty()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/object.go:32 +0x86
  github.com/robertkrimen/otto.objectHasProperty()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/object.go:37 +0x8b
  github.com/robertkrimen/otto.(*_objectStash).hasBinding()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/object.go:57 +0xa8
  github.com/robertkrimen/otto.(*_runtime).cmpl_variableDeclaration()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/cmpl_evaluate.go:92 +0x114
  github.com/robertkrimen/otto.(*_runtime).cmpl_evaluate_nodeProgram()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/cmpl_evaluate.go:15 +0xfa
  github.com/robertkrimen/otto.(*_runtime).cmpl_runOrEval.func1()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/runtime.go:767 +0x5f
  github.com/robertkrimen/otto.catchPanic()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/error.go:251 +0x66
  github.com/robertkrimen/otto.(*_runtime).cmpl_runOrEval()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/runtime.go:766 +0x131
  github.com/robertkrimen/otto.Otto.Run()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/runtime.go:779 +0x78
  github.com/bregydoc/gtranslate.sM()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/bregydoc/gtranslate@v0.0.0-20190803100511-2942db9d3610/token.go:29 +0x266
  github.com/bregydoc/gtranslate.get()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/bregydoc/gtranslate@v0.0.0-20190803100511-2942db9d3610/token.go:136 +0xec
  github.com/bregydoc/gtranslate.translate()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/bregydoc/gtranslate@v0.0.0-20190803100511-2942db9d3610/apiv2.go:47 +0x175
  github.com/bregydoc/gtranslate.TranslateWithParams()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/bregydoc/gtranslate@v0.0.0-20190803100511-2942db9d3610/gtranslate.go:28 +0xb0
  main.main.func1()
      /Users/polo/gomodules/translate/main.go:22 +0xdc

Previous write at 0x00c0001a0f58 by goroutine 184:
  [failed to restore the stack]

Goroutine 220 (running) created at:
  main.main()
      /Users/polo/gomodules/translate/main.go:20 +0x14d

Goroutine 184 (running) created at:
  main.main()
      /Users/polo/gomodules/translate/main.go:20 +0x14d
==================
==================
WARNING: DATA RACE
Read at 0x00c0001622c8 by goroutine 220:
  github.com/robertkrimen/otto.(*_runtime).cmpl_evaluate_nodeStatement()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/cmpl_evaluate_statement.go:27 +0x4c6
  github.com/robertkrimen/otto.(*_runtime).cmpl_call_nodeFunction()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/cmpl_evaluate.go:61 +0x6c8
  github.com/robertkrimen/otto.(*_object).call()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/type_function.go:226 +0xdb7
  github.com/robertkrimen/otto.(*_runtime).cmpl_evaluate_nodeCallExpression()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/cmpl_evaluate_expression.go:244 +0x745
  github.com/robertkrimen/otto.(*_runtime).cmpl_evaluate_nodeExpression()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/cmpl_evaluate_expression.go:44 +0x960
  github.com/robertkrimen/otto.(*_runtime).cmpl_evaluate_nodeStatement()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/cmpl_evaluate_statement.go:62 +0x132f
  github.com/robertkrimen/otto.(*_runtime).cmpl_evaluate_nodeStatementList()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/cmpl_evaluate_statement.go:121 +0xb7
  github.com/robertkrimen/otto.(*_runtime).cmpl_evaluate_nodeProgram()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/cmpl_evaluate.go:17 +0x1c1
  github.com/robertkrimen/otto.(*_runtime).cmpl_runOrEval.func1()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/runtime.go:767 +0x5f
  github.com/robertkrimen/otto.catchPanic()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/error.go:251 +0x66
  github.com/robertkrimen/otto.(*_runtime).cmpl_runOrEval()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/runtime.go:766 +0x131
  github.com/robertkrimen/otto.Otto.Run()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/robertkrimen/otto@v0.0.0-20180617131154-15f95af6e78d/runtime.go:779 +0x78
  github.com/bregydoc/gtranslate.sM()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/bregydoc/gtranslate@v0.0.0-20190803100511-2942db9d3610/token.go:29 +0x266
  github.com/bregydoc/gtranslate.get()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/bregydoc/gtranslate@v0.0.0-20190803100511-2942db9d3610/token.go:136 +0xec
  github.com/bregydoc/gtranslate.translate()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/bregydoc/gtranslate@v0.0.0-20190803100511-2942db9d3610/apiv2.go:47 +0x175
  github.com/bregydoc/gtranslate.TranslateWithParams()
      /Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/bregydoc/gtranslate@v0.0.0-20190803100511-2942db9d3610/gtranslate.go:28 +0xb0
  main.main.func1()
      /Users/polo/gomodules/translate/main.go:22 +0xdc

包是别人写的,你可以追下代码。毕竟,上面的调用栈已经给你了,一点一点看吧。

通过调用栈观察,这里的数据冲突产生与 otto 中的某个 map。我突然在想,otto 应该不会有问题,毕竟那么多 star 的包。

那继续往调用方看吧。

gtranslate 中,最后调用在 token.go:29,也就是 token.go 中的 29 行,看看这样代码是啥吧。如下:

result, err := vm.Run(...)

启动了一个 javascript 解析器 vm,导致的原因肯定多个 goroutine 共用了一个 vm,想到 vm 定义的地方,果然,它是文件开头定义的一个全局的变量,只有一个。

现在怎么解决这个问题呢?稍微修改下代码吧。

一种方式是,vm 在每次使用的使用新创建一个 vm,即把 var vm = otto.New() 这段代码放到 SM 这个函数中。

还有一种方式,那就是使用 sync.Pool,创建一个对象池,实现 otto 的可重用。

但无论哪种方式,都是需要修改一下这个包,你可以改 gtranslate 提给 issue 或者 pull request。