2015-02-13 6 views
14

In Go, wenn wir einen Typ mit einer Methode, die einige geschlungenen Mechanismus beginnt (Polling A und tun B für immer) ist es am besten, dies auszudrücken, wie:Idiomatic Golang goroutines

// Run does stuff, you probably want to run this as a goroutine 
func (t Type) Run() { 
    // Do long-running stuff 
} 

und dokumentieren, dass diese wahrscheinlich will als goroutine gestartet werden (und den Anrufer Deal mit, dass lassen)

Oder zu verstecken diese vom Anrufer:

// Run does stuff concurrently 
func (t Type) Run() { 
    go DoRunStuff() 
} 

ich bin neu zu gehen und ich nicht sicher, ob Konvention sagt lassen Sie den Anrufer pr efix mit 'go' oder tun Sie es für sie, wenn der Code async ausgeführt wird.

Meine aktuelle Ansicht ist, dass wir dokumentieren sollten und dem Anrufer eine Wahl geben. Mein Denken ist, dass in Go die Gleichzeitigkeit nicht Teil der exponierten Schnittstelle ist, sondern eine Eigenschaft, sie zu benutzen. Ist das richtig?

+0

Bisher zwei gegensätzliche Antworten mit gleichen Stimmen. Dies kann von Fall zu Fall so sein, es sei denn, Rob Pike oder jemand antwortet: P –

+0

Sie sind nicht unbedingt gegensätzliche Antworten. Ich denke, beide Antworten sagen, dass es unter bestimmten Umständen in Ordnung ist. Ich habe nur versucht, Ihnen über Ihr Beispiel hinaus einen allgemeineren Rat zu geben. – zmb

+0

Sie könnten in diesem Jahr ein ähnliches Video von GopherConIndia interessiert sein: https://www.youtube.com/watch?v=Y6KnnRh6wVo&list=PLxFC1MYuNgJTY3uQ5Ja4F5Sz305nnrBOq&index=14 – zmb

Antwort

9

Ich hatte Ihre Meinung dazu, bis ich begann, einen Adapter für einen Web-Service zu schreiben, den ich gleichzeitig machen möchte. Ich habe eine Go-Routine, die gestartet werden muss, um Ergebnisse zu analysieren, die von den Webaufrufen an den Kanal zurückgegeben werden. Es gibt absolut keinen Fall, in dem diese API funktionieren würde, ohne sie als Go-Routine zu verwenden.

Ich begann dann Pakete wie net/http zu betrachten. Innerhalb dieses Pakets ist ein gleichzeitiger Zugriff erforderlich. Es ist auf der Schnittstellenebene dokumentiert, dass es gleichzeitig verwendet werden kann, jedoch verwenden die Standardimplementierungen automatisch Go-Routinen.

Weil die Go-Standardbibliothek normalerweise Routinen innerhalb ihrer eigenen Pakete abfeuert, denke ich, dass, wenn Ihr Paket oder API dies rechtfertigt, Sie selbst damit umgehen können.

+0

Danke für die Antwort und die Verwendung von Beispielen in der Go-Standard-Bibliothek, werde ich gehen und rascheln sie aus –

9

Meine aktuelle Ansicht ist, dass wir dokumentieren sollten und dem Anrufer eine Wahl geben.

Ich neige dazu, Ihnen zuzustimmen.

Da Go es so einfach macht, Code gleichzeitig auszuführen, sollten Sie versuchen, die Parallelität in Ihrer API zu vermeiden (wodurch Clients gezwungen werden, sie gleichzeitig zu verwenden). Erstellen Sie stattdessen eine synchrone API, und dann haben Clients die Option, sie synchron oder gleichzeitig auszuführen.

Dieses in einem Vortrag vor ein paar Jahren diskutiert wurde: Twelve Go Best Practices

Slide 26, insbesondere, zeigt Code mehr wie Ihr erstes Beispiel.

Ich würde das net/http Paket als eine Ausnahme betrachten, weil in diesem Fall der Nebenläufigkeit fast obligatorisch ist. Wenn das Paket nicht intern Parallelität verwendet, müsste der Client-Code mit ziemlicher Sicherheit. Zum Beispiel, http.Client nicht (nach meinem Wissen) starten keine goroutines. Es ist nur der Server, der das tut.

In den meisten Fällen, es wird eine Zeile des Codes sein für den Anrufer oder so:

go Run() oder StartGoroutine()

Die synchrone API ist nicht schwieriger gleichzeitig zu bedienen und gibt den mehr Optionen Anrufer.

+0

Vielen Dank für Ihre Antwort. Folie 25 ist sehr hilfreich. Ich habe auch Probleme mit dem Edge-Case-Design im "http" -Paket, dessen Server/Client/Handler-Zweck ziemlich Standard ist. Hmm, das könnte ein heikles sein. –

+0

In meinem Fall ist Slide 28 (http://talks.golang.org/2013/bestpractices.slide#28) meinem Code sehr ähnlich, da mein "Konstruktor" für eine serverähnliche API ist und einen kill chan hat wie Folie 29. In Folie 28 startet der Konstruktor jedoch die Goroutine, die dem Benutzer die Wahl wegnimmt. –

+0

... könnte es sein, dass Server-APIs sind die Ausnahme zu Folie 25 –

1

Es gibt keine "richtige" Antwort, da sich die Umstände unterscheiden.

Offensichtlich gibt es Fälle, in denen eine API Dienstprogramme, einfache Algorithmen, Datensammlungen usw. enthalten könnte, die seltsam aussehen würden, wenn sie als Gououtines verpackt wären. Im Gegensatz dazu gibt es Fälle, in denen es natürlich ist, dass man "unter der Haube" Parallelität erwartet, wie etwa eine reichhaltige E/A-Bibliothek (http-Server ist das offensichtliche Beispiel).

Für einen extremeren Fall sollten Sie eine Bibliothek mit Plug-n-Play-Concurrent-Services erstellen. Eine solche API besteht aus Modulen, die jeweils über Kanäle eine gut beschriebene Schnittstelle aufweisen. Es ist klar, dass in diesem Fall zwangsläufig Gououtines als Teil der API involviert wären.

Ein Anhaltspunkt könnte das Vorhandensein oder Fehlen von Kanälen in den Funktionsparametern sein. Aber ich würde eine klare Dokumentation darüber erwarten, was ich auf jeden Fall erwarten würde.

+0

Ich stimme zu, natürlich können wir tun, was wir wollen. Ich habe nicht nach der richtigen Antwort gesucht, sondern nach allen Erwartungen, die andere haben könnten, wenn sie eine API aufrufen. –

Verwandte Themen