Imwe yemasiginecha eGo yakavakirwa-mukati tsigiro ye concurrency. Goroutines uye chiteshi zviri nyore uye zvinoshanda zvekutanga zvekunyora zvirongwa panguva imwe chete.
Nekudaro, kuyedza zvirongwa panguva imwe chete zvinogona kunetsa uye kukanganisa kukanganisa.
MuGo 1.24, tiri kuunza itsva, testing/synctest
package yekutsigira yekuyedza kodhi yakafanana. Iyi posvo inotsanangura kukurudzira kuseri kwechiyedzo ichi, kuratidza mashandisiro esynctest package, uye kukurukura ramangwana rayo ringave.
MuGo 1.24, iyo testing/synctest
package ndeyekuyedza uye haisi pasi peGo kuenderana vimbiso. Haioneki nekusingaperi. Kuti uishandise, unganidza kodhi yako GOEXPERIMENT=synctest
yakaiswa munzvimbo yako.
Kuedza mapurogiramu panguva imwe chete kwakaoma
Kutanga, ngationei muenzaniso uri nyore.
The context.AfterFunc
function inoronga kuti basa ridaidzwe nenzira yaro pachayo mushure mekunge mamiriro akadzimwa. Heino bvunzo inokwanisika AfterFunc
:
func TestAfterFunc(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) calledCh := make(chan struct{}) // closed when AfterFunc is called context.AfterFunc(ctx, func() { close(calledCh) }) // TODO: Assert that the AfterFunc has not been called. cancel() // TODO: Assert that the AfterFunc has been called. }
Tinoda kutarisa mamiriro maviri muyedzo iyi: Basa racho haridanwe mamiriro ezvinhu asati adzimwa, uye basa racho rinodanwa mushure mekunge mamiriro akadzimwa.
Kutarisa zvakaipa mune imwe nguva system kwakaoma. Tinogona kuyedza zviri nyore kuti basa harisati radaidzwa, asi tinotarisa sei kuti harizodaidzwa ?
Mutoo unozivikanwa kumirira kwenguva yakati usati wagumisa kuti chimwe chinhu hachisati chichizoitika. Ngatiedzei kuunza basa remubatsiri kubvunzo yedu inoita izvi.
// funcCalled reports whether the function was called. funcCalled := func() bool { select { case <-calledCh: return true case <-time.After(10 * time.Millisecond): return false } } if funcCalled() { t.Fatalf("AfterFunc function called before context is canceled") } cancel() if !funcCalled() { t.Fatalf("AfterFunc function not called after context is canceled") }
Muedzo uyu unononoka: gumi milliseconds haisi nguva yakawanda, asi inowedzera pamusoro pebvunzo dzakawanda.
Muedzo uyu zvakare hauna kujeka: 10 milliseconds inguva yakareba pakombuta inokurumidza, asi hazvina kujairika kuona kumbomira kunotora masekonzi akati wandei pane akagovaniswa uye akaremerwa eCI masisitimu.
Isu tinokwanisa kuita kuti bvunzo iite zvishoma nemutengo wekuita kuti inonoke, uye isu tinogona kuita kuti iite zvishoma nemutengo wekuita kuti iite flakier, asi isu hatigone kuzviita nekukurumidza uye nekuvimbika.
Kuunza iyo yekuyedza/synctest package
Iyo testing/synctest
package inogadzirisa dambudziko iri. Inotibvumira kunyora zvakare bvunzo iyi kuti ive nyore, nekukurumidza, uye yakavimbika, pasina chero shanduko kukodhi iri kuedzwa.
Iyo package ine mabasa maviri chete: Run
uye Wait
.
Run
inodaidza basa mune goroutine nyowani. Iyi goroutine uye chero goroutines yakatangwa nayo iripo munzvimbo iri yoga yatinodaidza kuti bubble . Wait
kuti goroutine yega yega mububble regoroutine rivhare pane imwe goroutine mububble.
Ngatinyoreizve bvunzo yedu pamusoro tichishandisa testing/synctest
package.
func TestAfterFunc(t *testing.T) { synctest.Run(func() { ctx, cancel := context.WithCancel(context.Background()) funcCalled := false context.AfterFunc(ctx, func() { funcCalled = true }) synctest.Wait() if funcCalled { t.Fatalf("AfterFunc function called before context is canceled") } cancel() synctest.Wait() if !funcCalled { t.Fatalf("AfterFunc function not called after context is canceled") } }) }
Izvi zvakada kufanana nebvunzo yedu yepakutanga, asi takapeta bvunzo mu synctest.Run
call todaidza synctest.Wait
usati wataura kuti basa radaidzwa kana kuti kwete.
Iyo Wait
basa inomirira yega yega goroutine mububble reanofona kuti avhare. Kana yadzoka, tinoziva kuti dingindira remukati rakadaidzira basa, kana kusaridaidza kudzamara tatora chimwe chiito.
Uyu muedzo ikozvino wave nekukurumidza uye wakavimbika.
Muedzo uri nyore, zvakare: isu takatsiva calledCh
chiteshi ne boolean. Pakutanga taifanira kushandisa chiteshi kudzivirira mujaho wedhata pakati peyeyedzo goroutine AfterFunc
goroutine, asi Wait
basa ikozvino rinopa kuyananisa.
Mujaho wedetector unonzwisisa Wait
mafoni, uye bvunzo iyi inodarika kana ichimhanya ne -race
. Kana isu tikabvisa yechipiri Wait
kufona, iyo nhangemutange yedhivha inotaura nemazvo mujaho wedata muyedzo.
Nguva yekuedza
Cocurrent code kazhinji inobata nenguva.
Kuedza kodhi inoshanda nenguva inogona kuve yakaoma. Kushandisa nguva chaiyo mubvunzo kunokonzeresa bvunzo dzinononoka uye dzisina kusimba, sezvataona pamusoro. Kushandisa nguva yekunyepera kunoda kudzivirira time
pasuru mabasa, uye kugadzira kodhi iri pasi pekuyedzwa kuti ushande neinosarudzika fake wachi.
Iyo testing/synctest
package inoita kuti zvive nyore kuyedza kodhi inoshandisa nguva.
Goroutines mububble rakatangwa Run
shandisa wachi yekunyepera. Mukati mebubble, mabasa ari mupakeji time
anoshanda pane iyo fake wachi. Nguva inofambira mberi mububble apo ese goroutines akavharwa.
Kuratidza, ngatinyore bvunzo yemamiriro context.WithTimeout
function. WithTimeout
inogadzira mwana wemamiriro ezvinhu, anopera mushure menguva yakatarwa.
func TestWithTimeout(t *testing.T) { synctest.Run(func() { const timeout = 5 * time.Second ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() // Wait just less than the timeout. time.Sleep(timeout - time.Nanosecond) synctest.Wait() if err := ctx.Err(); err != nil { t.Fatalf("before timeout, ctx.Err() = %v; want nil", err) } // Wait the rest of the way until the timeout. time.Sleep(time.Nanosecond) synctest.Wait() if err := ctx.Err(); err != context.DeadlineExceeded { t.Fatalf("after timeout, ctx.Err() = %v; want DeadlineExceeded", err) } }) }
Isu tinonyora bvunzo iyi sekunge tiri kushanda nenguva chaiyo. Musiyano chete ndewekuti tinoputira bvunzo mu synctest.Run
, uye tofonera synctest.Wait
mushure menguva yega time.Sleep
kufona kumirira kuti zvibatiso zvepasuru yemamiriro ekunze zvipedze kushanda.
Kuvhara uye bubble
Pfungwa yakakosha testing/synctest
ibubble rinovharika zvakasimba . Izvi zvinoitika kana yega yega goroutine mububble yakavharwa, uye inogona chete kuvhurwa neimwe goroutine mububble.
Kana bubble rikavharika zvachose:
- Kana paine
Wait
call yasara, inodzoka. - Zvikasadaro, nguva inofambira mberi kusvika panguva inotevera iyo inogona kuvhura goroutine, kana iripo.
- Zvikasadaro, bubble rakavharwa uye
Run
panics.
Bubble harivharidzirwe zvachose kana chero goroutine yakavharwa asi inogona kumutswa nechimwe chiitiko kubva kunze kwebubble.
Rondedzero yakazara yemashandiro ayo anogara achivharira goroutine ndeiyi:
- kutumira kana kugamuchira pane nil chiteshi
- kutumira kana kugamuchira kwakavharwa pachiteshi chakagadzirwa mukati mebubble rimwechete
- chirevo chekusarudza apo nyaya dzese dziri kuvharika
-
time.Sleep
-
sync.Cond.Wait
-
sync.WaitGroup.Wait
Mutexes
Ma Operations pa sync.Mutex
haivharidziki.
Zvakajairika kuti mabasa awane nyika mutex. Semuyenzaniso, akati wandei emabasa mureflect package anoshandisa cache yepasi rose inochengetedzwa nemutex. Kana goroutine mu synctest bubble ichivhara paunenge uchitora chimumumu chakabatwa negoroutine kunze kwebubble, haina kuvharika zvakasimba-inovharika, asi inozovhurwa negoroutine kubva kunze kwebubble rayo.
Sezvo zvimumumu zvisingawanzo kubatwa kwenguva yakareba, tinongozvibvisa kubva testing/synctest
kufunga.
Channels
Matanho akagadzirwa mukati mebubble anoita zvakasiyana kubva kune akagadzirwa kunze.
Kuitwa kwechiteshi kuri kuvharira kwenguva refu chete kana chiteshi chakaputirwa (chakagadzirwa mububble). Kushanda pane bubbled channel kubva kunze kwebubble panic.
Mitemo iyi inovimbisa kuti goroutine inovharika kwenguva refu chete kana ichitaura nema goroutines mukati mebubble rayo.
I/O
Ekunze maI/O mashandiro, akadai sekuverenga kubva kunetiweki yekubatanidza, haana kuvharika kwenguva refu.
Network kuverenga inogona kuvhurwa nekunyora kubva kunze kwebubble, pamwe kunyangwe kubva kune mamwe maitiro. Kunyangwe kana iye ega munyori kune network yekubatanidza ariwo mububble rimwechete, nguva yekumhanya haigone kusiyanisa pakati pekubatana kwakamirira kuti data rakawanda risvike uye imwe iyo kernel yakagamuchira data uye iri munzira yekuiendesa.
Kuyedza sevha yetiweki kana mutengi ane synctest kazhinji zvinoda kupa fake network kuita. Semuyenzaniso, iyo net.Pipe
function inogadzira peya net.Conn
s anoshandisa in-memory network yekubatanidza uye anogona kushandiswa musynctest tests.
Bubble hupenyu hwose
Iyo Run
basa rinotanga goroutine mune nyowani bubble. Inodzoka kana goroutine yega yega mububble yabuda. Zvinotyisa kana bubble rakavharwa nguva dzose uye risingakwanise kuvhurwa nekufamba kwenguva.
Zvinodikanwa kuti goroutine yese mububble ibude Run isati yadzoka zvinoreva kuti bvunzo dzinofanirwa kungwarira kuchenesa chero kumashure goroutines isati yapedza.
Kuedza networked code
Ngatitarisei mumwe muenzaniso, panguva ino tichishandisa testing/synctest
package yekuyedza chirongwa chinetiweki. Kune uyu muenzaniso, isu tichaedza net/http
mabatiro epasuru ye100 Ramba mhinduro.
Mutengi weHTTP anotumira chikumbiro anogona kusanganisira "Tarisira: 100-enderera" musoro wekuudza sevha kuti mutengi ane imwe data yekutumira. Sevha inogona kuzopindura ne100 Ramba uchipindura ruzivo kukumbira chimwe chikumbiro, kana neimwewo mamiriro ekuudza mutengi kuti zvirimo hazvidiwe. Semuenzaniso, mutengi ari kurodha faira hombe anogona kushandisa chimiro ichi kuratidza kuti sevha inoda kugamuchira faira isati yatumira.
Muedzo wedu unosimbisa kuti kana uchitumira "Tarisira: 100-enderera" musoro mutengi weHTTP haatumire zvirimo mukukumbira server isati yakumbira, uye kuti inotumira zvirimo mushure mekugamuchira zana Ramba mhinduro.
Kazhinji bvunzo dzemutengi anotaurirana uye sevha inogona kushandisa loopback network yekubatanidza. Paunenge uchishanda testing/synctest
, zvisinei, isu tinowanzo kuda kushandisa fake network yekubatanidza kutibvumira kuona kana goroutines ese akavharwa pane network. Tichatanga bvunzo iyi nekugadzira http.Transport
(mutengi weHTTP) inoshandisa chinongedzo chemukati mememory chinogadzirwa net.Pipe
.
func Test(t *testing.T) { synctest.Run(func() { srvConn, cliConn := net.Pipe() defer srvConn.Close() defer cliConn.Close() tr := &http.Transport{ DialContext: func(ctx context.Context, network, address string) (net.Conn, error) { return cliConn, nil }, // Setting a non-zero timeout enables "Expect: 100-continue" handling. // Since the following test does not sleep, // we will never encounter this timeout, // even if the test takes a long time to run on a slow machine. ExpectContinueTimeout: 5 * time.Second, }
Isu tinotumira chikumbiro pachifambiso ichi ne "Tarisira: 100-enderera" musoro seti. Chikumbiro chinotumirwa mune itsva goroutine, sezvo isingapedzi kusvika pakupera kwebvunzo.
body := "request body" go func() { req, _ := http.NewRequest("PUT", "http://test.tld/", strings.NewReader(body)) req.Header.Set("Expect", "100-continue") resp, err := tr.RoundTrip(req) if err != nil { t.Errorf("RoundTrip: unexpected error %v", err) } else { resp.Body.Close() } }()
Isu tinoverenga misoro yekukumbira yakatumirwa nemutengi.
req, err := http.ReadRequest(bufio.NewReader(srvConn)) if err != nil { t.Fatalf("ReadRequest: %v", err) }
Zvino tasvika pamwoyo wechiyedzo. Tinoda kutaura kuti mutengi haasati atumira mutumbi wekukumbira.
Isu tinotanga nzira itsva yekukopa muviri wakatumirwa kuseva kuita strings.Builder
, mirira kuti magoroutines ari mububble avharwe, uye ona kuti hatisati taverenga chero chinhu kubva mumuviri.
Kana tikakanganwa iyo synctest.Wait
kufona, mujaho we detector uchanyunyuta nemazvo nezverudzi rwe data, asi Wait
izvi zvakachengeteka.
var gotBody strings.Builder go io.Copy(&gotBody, req.Body) synctest.Wait() if got := gotBody.String(); got != "" { t.Fatalf("before sending 100 Continue, unexpectedly read body: %q", got) }
Isu tinonyora mhinduro ye "100 Ramba" kumutengi uye tinoona kuti ikozvino yatumira mutumbi wekukumbira.
srvConn.Write([]byte("HTTP/1.1 100 Continue\r\n\r\n")) synctest.Wait() if got := gotBody.String(); got != body { t.Fatalf("after sending 100 Continue, read body %q, want %q", got, body) }
Uye pakupedzisira, tinopedzisa nekutumira "200 OK" mhinduro yekupedzisa chikumbiro.
Tatanga ma goroutine akati wandei panguva yebvunzo iyi. The synctest.Run
call inomirira kuti vese vabude vasati vadzoka.
srvConn.Write([]byte("HTTP/1.1 200 OK\r\n\r\n")) }) }
Uyu muedzo unogona kuwedzerwa nyore nyore kuedza mamwe maitiro, sekuona kuti chikwata chekukumbira hachina kutumirwa kana sevha ikasakumbira, kana kuti inotumirwa kana sevha ikasapindura mukati menguva.
Mamiriro ekuedza
Tiri kuunza testing/synctest
muGo 1.24 seyedzero pasuru. Zvichienderana nemhinduro uye ruzivo tinogona kuiburitsa tiine kana tisina zvigadziriso, kuenderera mberi nekuyedza, kana kuibvisa mune ramangwana reGo.
Iyo pasuru haionekwe neyakagadzika. Kuti uishandise, unganidza kodhi yako GOEXPERIMENT=synctest
yakaiswa munzvimbo yako.
Tinoda kunzwa mhinduro yako! Kana ukaedza testing/synctest
, ndapota taura zvawakasangana nazvo, zvakanaka kana zvakaipa, on go.dev/issue/67434 .
Credits: Damien Neil
Mufananidzo naGabriel Gusmao paUnsplash
Ichi chinyorwa chinowanikwa pa