Gehen Sie Beispiele und Redewendungen [geschlossen]
91
Es gibt nicht viel Go-Code, aus dem man die Sprache lernen kann, und ich bin sicher, dass ich nicht der einzige bin, der damit experimentiert. Wenn Sie also etwas Interessantes über die Sprache herausgefunden haben, posten Sie bitte hier ein Beispiel.
ARM-Unterstützung wie 8-Bit oder 16-Bit. D Sprache noch nicht.
1
Die Bibliothek ( golang.org/pkg ) ist eine hervorragende Quelle, um zu erfahren, wie go verwendet wird. Persönlich finde ich, dass das Lernen, wie Datenstrukturen implementiert werden, hilfreich ist, um die Sprache zu lernen.
Tkokasih
Antworten:
35
Anweisungen verschieben
Eine "defer" -Anweisung ruft eine Funktion auf, deren Ausführung auf den Moment verschoben wird, in dem die umgebende Funktion zurückkehrt.
DeferStmt = Ausdruck "verschieben".
Der Ausdruck muss ein Funktions- oder Methodenaufruf sein. Bei jeder Ausführung der Anweisung "defer" werden die Parameter des Funktionsaufrufs ausgewertet und neu gespeichert, die Funktion wird jedoch nicht aufgerufen. Aufgeschobene Funktionsaufrufe werden in LIFO-Reihenfolge unmittelbar vor der Rückkehr der umgebenden Funktion ausgeführt, jedoch nachdem die Rückgabewerte, falls vorhanden, ausgewertet wurden.
lock(l);
defer unlock(l);// unlocking happens before surrounding function returns// prints 3 2 1 0 before surrounding function returnsfor i :=0; i <=3; i++{
defer fmt.Print(i);}
Aktualisieren:
deferist jetzt der idiomatische Weg zu handhaben auch panicin einer Ausnahme wie Art und Weise:
package main
import"fmt"
func main(){
f()
fmt.Println("Returned normally from f.")}
func f(){
defer func(){if r := recover(); r !=nil{
fmt.Println("Recovered in f", r)}}()
fmt.Println("Calling g.")
g(0)
fmt.Println("Returned normally from g.")}
func g(i int){if i >3{
fmt.Println("Panicking!")
panic(fmt.Sprintf("%v", i))}
defer fmt.Println("Defer in g", i)
fmt.Println("Printing in g", i)
g(i+1)}
Sieht aus wie guter alter RAII (explizit gemacht).
Konrad Rudolph
4
+1 da ich viel über Go gelesen habe, aber ich habe das immer noch nicht gesehen (bis du es mir gezeigt hast)!
u0b34a0f6ae
Clever, obwohl es für mich sinnvoller wäre, wenn aufgeschobene Anweisungen in FIFO-Reihenfolge (von oben nach unten) ausgeführt würden, aber vielleicht
@ Mike: Wenn Sie mit Blöcken von "try: .. finally:" vergleichen, nistet LIFO auf die gleiche Weise. Bei Paaren zum Öffnen / Schließen von Ressourcen usw. ist eine solche Verschachtelung das einzige, was Sinn macht (Erstes Öffnen wird zuletzt schließen).
u0b34a0f6ae
25
Go-Objektdateien enthalten tatsächlich einen Klartext-Header:
jurily@jurily ~/workspace/go/euler31 $ 6g euler31.go
jurily@jurily ~/workspace/go/euler31 $ cat euler31.6
amd64
exports automatically generated from
euler31.go inpackage"main"import
$$ // exportspackage main
var main.coin [9]int
func main.howmany (amount int, max int)(?int)
func main.main ()var main.initdone· uint8
func main.init ()
$$ // local types
type main.dsigddd_1·1struct{?int}
$$
!<binary segment>
Das ist eher ein verstecktes Feature als ein idiomatisches Beispiel
hasen
22
Ich habe ein paar Leute gesehen, die sich über die for-Schleife beschwert haben, nach dem Motto "Warum sollten wir heutzutage etwas sagen müssen i = 0; i < len; i++?".
Ich bin anderer Meinung, ich mag das für Konstrukt. Sie können die lange Version verwenden, wenn Sie möchten, aber das idiomatische Go ist
var a =[]int{1,2,3}for i, v := range a {
fmt.Println(i, v)}
Das for .. rangeKonstrukt durchläuft alle Elemente und liefert zwei Werte - den Index iund den Wertv .
range funktioniert auch auf Karten und Kanälen.
Dennoch, wenn Sie nicht mögen forin jeder Form, können Sie festlegen each, mapusw. in ein paar Zeilen:
type IntArr[]int// 'each' takes a function argument.// The function must accept two ints, the index and value,// and will be called on each element in turn.
func (a IntArr) each(fn func(index,valueint)){for i, v := range a {
fn(i, v)}}
func main(){var a =IntArr([]int{2,0,0,9})// create int slice and cast to IntArrvar fnPrint = func(i, v int){
fmt.Println(i,":", v)}// create a function
a.each(fnPrint)// call on each element}
Ich bin mir nicht sicher, was mit der Formatierung falsch sein sollte. Ich habe es wiederhergestellt.
5
Die Go-Autoren empfehlen zu gofmtIhrem Code :-)
ℝaphink
Ich kann es nicht kompilieren: $ ../go/src/cmd/6g/6g SO.go SO.go: 34: undefined: json.StringToJson
ℝaphink
@Raphink: Die Sprache hat sich geändert, seit ich das gemacht habe.
Ja, wissen Sie vielleicht, was dem StringToJson am nächsten kommt? Früher wurde ein Builder intern eingerichtet, jetzt muss man seinen eigenen mit einer vordefinierten nativen Struktur versehen?
type ByteSize float64
const(
_ = iota;// ignore first value by assigning to blank identifier
KB ByteSize=1<<(10*iota)
MB
GB
TB
PB
YB
)// This implicitly repeats to fill in all the values (!)
Whoa, komplett aus VB herausgerissen. ;-) ( Switch True…)
Konrad Rudolph
@Konrad, schlag mich drauf! :) Ich habe dieses Idiom bereits in VB6-Code verwendet und es kann definitiv die Lesbarkeit in bestimmten Situationen verbessern.
switch i := x.(type){casenil:
printString("x is nil");caseint:
printInt(i);// i is an intcasefloat:
printFloat(i);// i is a floatcase func(int)float:
printFunction(i);// i is a functioncasebool,string:
printString("type is bool or string");// i is an interface{}default:
printString("don't know the type");}
Die Rückgabe- oder Ergebnis- "Parameter" einer Go-Funktion können wie die eingehenden Parameter benannt und als reguläre Variablen verwendet werden. Wenn sie benannt werden, werden sie zu Beginn der Funktion auf die Nullwerte für ihre Typen initialisiert. Wenn die Funktion eine return-Anweisung ohne Argumente ausführt, werden die aktuellen Werte der Ergebnisparameter als zurückgegebene Werte verwendet.
Die Namen sind nicht obligatorisch, können aber den Code kürzer und klarer machen: Sie sind Dokumentation. Wenn wir die Ergebnisse von nextInt benennen, wird klar, welches zurückgegebene int welches ist.
Da benannte Ergebnisse initialisiert und an eine schmucklose Rückgabe gebunden sind, können sie sowohl vereinfachen als auch verdeutlichen. Hier ist eine Version von io.ReadFull, die sie gut nutzt:
/*
* How many different ways can £2 be made using any number of coins?
* Now with 100% less semicolons!
*/package main
import"fmt"/* This line took me over 10 minutes to figure out.
* "[...]" means "figure out the size yourself"
* If you only specify "[]", it will try to create a slice, which is a reference to an existing array.
* Also, ":=" doesn't work here.
*/var coin =[...]int{0,1,2,5,10,20,50,100,200}
func howmany(amount int, max int)int{if amount ==0{return1}if amount <0{return0}if max <=0&& amount >=1{return0}// recursion works as expectedreturn howmany(amount, max-1)+ howmany(amount-coin[max], max)}
func main(){
fmt.Println(howmany(200, len(coin)-1))}
Ich würde vorschlagen, den Namen der Problemlösungsseite sowie die ID-Nummer zu entfernen. Vielleicht die Frage umformulieren. Um das Problem nicht jemandem zu verderben, der darüber stolpert. Oder versuchen Sie zu betrügen, indem Sie im Internet nach dem Problem suchen.
Ich finde es gut, dass Sie Typen, einschließlich Grundelemente wie int, beliebig oft neu definieren und verschiedene Methoden anhängen können. Wie beim Definieren eines RomanNumeral-Typs:
package main
import("fmt""strings")var numText ="zero one two three four five six seven eight nine ten"var numRoman ="- I II III IV V VI VII IX X"var aText = strings.Split(numText," ")var aRoman = strings.Split(numRoman," ")
type TextNumberint
type RomanNumberint
func (n TextNumber)String()string{return aText[n]}
func (n RomanNumber)String()string{return aRoman[n]}
func main(){var i =5
fmt.Println("Number: ", i,TextNumber(i),RomanNumber(i))}
Welches druckt aus
Number:5 five V
Der RomanNumber()Aufruf ist im Wesentlichen eine Umwandlung, er definiert den int-Typ als einen spezifischeren Typ von int neu. Und Println()ruft String()hinter die Kulissen.
Dies ist eine wahre Redewendung, die sehr wichtig ist: wie man Daten in einen Kanal einspeist und ihn danach schließt. Mit diesem können Sie einfache Iteratoren (da der Bereich einen Kanal akzeptiert) oder Filter erstellen.
// return a channel that doubles the values in the input channel
func DoublingIterator(input chan int) chan int{
outch := make(chan int);// start a goroutine to feed the channel (asynchronously)
go func(){for x := range input {
outch <-2*x;}// close the channel we created and control
close(outch);}();return outch;}
Achten Sie jedoch darauf, dass Sie nicht aus einer for x: = range chan {} -Schleife ausbrechen, da sonst die Goroutine und der gesamte Speicher, auf den sie verweist, verloren gehen.
Jeff Allen
3
@ JeffAllen wie wäre es defer close(outch);als erste Aussage der Goroutine?
1
Aufschieben stellt eine Anweisung zur Ausführung in die Warteschlange, wenn die Funktion zurückgegeben wird, unabhängig davon, welcher Rückgabepunkt verwendet wird. Wenn der Kanaleingang jedoch niemals geschlossen wird, verlässt die anonyme Funktion in diesem Beispiel niemals die for-Schleife.
Jeff Allen
11
Zeitüberschreitung für Kanallesungen:
ticker := time.NewTicker(ns);select{case v :=<- chan_target:
do_something_with_v;case<- ticker.C:
handle_timeout;}
Es gibt ein Make-System, das Sie in $ GOROOT / src verwenden können
Richten Sie Ihr Makefile mit ein
TARG=foobar # Name of package to compile
GOFILES=foo.go bar.go # Go sources
CGOFILES=bang.cgo # Sources to run cgo on
OFILES=a_c_file.$O # Sources compiled with $Oc# $O is the arch number (6 for x86_64)
include $(GOROOT)/src/Make.$(GOARCH)
include $(GOROOT)/src/Make.pkg
Sie können dann die automatisierten Testtools verwenden, indem Sie make test ausführen, oder das Paket und die freigegebenen Objekte von cgo mit make install zu Ihrem $ GOROOT hinzufügen.
Dies ist eine Implementierung eines Stapels. Es zeigt das Hinzufügen von Methoden zu einem Typ.
Ich wollte den Stack-Teil davon in ein Slice verwandeln und die Eigenschaften des Slice verwenden, aber obwohl ich das ohne das typezum Laufen gebracht habe, konnte ich die Syntax zum Definieren eines Slice mit einem nicht sehen type.
package main
import"fmt"import"os"const stack_max =100
type Stack2struct{
stack [stack_max]string
size int}
func (s *Stack2) push(pushed_string string){
n := s.size
if n >= stack_max-1{
fmt.Print("Oh noes\n")
os.Exit(1)}
s.size++
s.stack[n]= pushed_string
}
func (s *Stack2) pop()string{
n := s.size
if n ==0{
fmt.Print("Underflow\n")
os.Exit(1)}
top := s.stack[n-1]
s.size--return top
}
func (s *Stack2) print_all(){
n := s.size
fmt.Printf("Stack size is %d\n", n)for i :=0; i < n; i++{
fmt.Printf("%d:\t%s\n", i, s.stack[i])}}
func main(){
stack :=new(Stack2)
stack.print_all()
stack.push("boo")
stack.print_all()
popped := stack.pop()
fmt.Printf("Stack top is %s\n", popped)
stack.print_all()
stack.push("moo")
stack.push("zoo")
stack.print_all()
popped2 := stack.pop()
fmt.Printf("Stack top is %s\n", popped2)
stack.print_all()}
Anstatt zu verwenden fmt.Printf(...); os.Exit();, können Sie verwenden panic(...).
Notnoop
1
Das gibt eine Stapelverfolgung, die ich nicht will.
3
Warum ist es begrenzt? Go ist eine verwaltete Sprache. Ihr Stapel kann so tief sein, wie Sie möchten. Verwenden Sie das neue integrierte append (), das bei Bedarf so etwas wie Cs Realloc ausführt.
Jeff Allen
"Go braucht keine Generika", sagten sie.
cubuspl42
4
C-Code von unterwegs aufrufen
Mit der c-Laufzeit ist es möglich, auf die untere Ebene von go zuzugreifen.
C-Funktionen sind in der Form
voidpackage·function(...)
(Beachten Sie, dass der Punkttrenner ein Unicode-Zeichen ist.) Dabei können die Argumente grundlegende Go-Typen, Slices, Strings usw. sein. Um einen Wertaufruf zurückzugeben
FLUSH(&ret)
(Sie können mehr als einen Wert zurückgeben)
Zum Beispiel, um eine Funktion zu erstellen
package foo
bar( a int32, b string)(c float32 ){
c =1.3+ float32(a - int32(len(b))}
in C verwenden Sie
#include"runtime.h"void foo·bar(int32 a,String b, float32 c){
c =1.3+ a - b.len;
FLUSH(&c);}
Beachten Sie, dass Sie die Funktion weiterhin in einer go-Datei deklarieren sollten und dass Sie sich selbst um den Speicher kümmern müssen. Ich bin mir nicht sicher, ob es möglich ist, externe Bibliotheken damit aufzurufen. Es ist möglicherweise besser, cgo zu verwenden.
In $ GOROOT / src / pkg / runtime finden Sie Beispiele für die Laufzeit.
Siehe auch diese Antwort zum Verknüpfen von C ++ - Code mit go.
Verwendet es wirklich den "fliegenden Punkt"? Ich wage es nicht zu bearbeiten, aber das scheint ein bisschen unerwartet und radikal.
Entspannen Sie
Ja, Sie müssen mit 6c (oder 8c usw.) kompilieren. Ich glaube nicht, dass gcc Unicode-IDs verarbeitet.
Scott Wales
1
Ich denke, AltGr + -Periodentypen sind gleich · aber mit Unicode bin ich mir nicht sicher. War sehr überrascht zu sehen, dass ich in der Quelle gelesen habe .. warum nicht so etwas wie :: verwenden?
u0b34a0f6ae
Das Zeichen ist MIDDLE DOT U + 00B7. Der Parser wurde möglicherweise so verfälscht, dass er dies als Zeichen ansieht, um eine gültige c-Kennung zu erstellen, von der ich glaube, dass sie :: ausschließen würde.
Scott Wales
4
Das '·' ist nur ein vorübergehender Hack, Rob war sogar überrascht, dass es noch da war, er sagte, es würde durch etwas weniger Eigenartiges ersetzt werden.
Ja, habe ich. Es läuft darauf hinaus: "Da ist noch viel mehr drin, lasst uns zum nächsten Thema übergehen."
György Andrasek
Ja, anscheinend viel zu sagen mit wenig Zeit
3
Ein Stapel, der auf der anderen Antwort basiert, aber ein Slice verwendet, an das keine Größenbeschränkung angehängt ist.
package main
import"fmt"import"os"
type Stack2struct{// initial storage space for the stack
stack [10]string
cur []string}
func (s *Stack2) push(pushed_string string){
s.cur = append(s.cur, pushed_string)}
func (s *Stack2) pop()(popped string){if len(s.cur)==0{
fmt.Print("Underflow\n")
os.Exit(1)}
popped = s.cur[len(s.cur)-1]
s.cur = s.cur[0: len(s.cur)-1]return}
func (s *Stack2) print_all(){
fmt.Printf("Stack size is %d\n", len(s.cur))for i, s := range s.cur {
fmt.Printf("%d:\t%s\n", i, s)}}
func NewStack()(stack *Stack2){
stack =new(Stack2)// init the slice to an empty slice of the underlying storage
stack.cur = stack.stack[0:0]return}
func main(){
stack :=NewStack()
stack.print_all()
stack.push("boo")
stack.print_all()
popped := stack.pop()
fmt.Printf("Stack top is %s\n", popped)
stack.print_all()
stack.push("moo")
stack.push("zoo")
stack.print_all()
popped2 := stack.pop()
fmt.Printf("Stack top is %s\n", popped2)
stack.print_all()}
Natürlich. Genau das passiert hier. Ich mag nur das foreverSchlüsselwort. Sogar Qt hat ein Makro dafür.
György Andrasek
6
Aber Go braucht dazu kein Makro oder einen niedlichen Alias von true.
u0b34a0f6ae
@ kaizer.se: Jurily meint, dass for ever(nach dem Deklarieren der Variablen) etwas Süßes ist, das Sie in Go tun können, wenn Sie möchten. Es sieht aus wie Englisch (Modulo the Blank).
Frank
8
es ist etwas süßes, das du auch in C machen kannst .. :-)#define ever (;;)
u0b34a0f6ae
2
Es gibt viele kleine Programme im testHauptverzeichnis. Beispiele:
peano.go druckt Fakultäten.
hilbert.go hat eine Matrixmultiplikation.
iota.go hat Beispiele für die seltsame Iota-Sache.
Antworten:
Anweisungen verschieben
Aktualisieren:
defer
ist jetzt der idiomatische Weg zu handhaben auchpanic
in einer Ausnahme wie Art und Weise:quelle
Go-Objektdateien enthalten tatsächlich einen Klartext-Header:
quelle
Ich habe ein paar Leute gesehen, die sich über die for-Schleife beschwert haben, nach dem Motto "Warum sollten wir heutzutage etwas sagen müssen
i = 0; i < len; i++
?".Ich bin anderer Meinung, ich mag das für Konstrukt. Sie können die lange Version verwenden, wenn Sie möchten, aber das idiomatische Go ist
Das
for .. range
Konstrukt durchläuft alle Elemente und liefert zwei Werte - den Indexi
und den Wertv
.range
funktioniert auch auf Karten und Kanälen.Dennoch, wenn Sie nicht mögen
for
in jeder Form, können Sie festlegeneach
,map
usw. in ein paar Zeilen:druckt
Ich fange an, Go sehr zu mögen :)
quelle
range
es nur schön ist, wenn es mit dem gleichen Code wie die for-3-Schleife kompiliert wird.Holen Sie sich Ihren Stackoverflow-Ruf
Dies ist eine Übersetzung dieser Antwort .
Vielen Dank an Scott Wales für die Hilfe bei .Read ().
Das sieht mit den zwei Saiten und zwei Puffern immer noch ziemlich klobig aus. Wenn also Go-Experten Ratschläge haben, lassen Sie es mich wissen.
quelle
gofmt
Ihrem Code :-)Hier ist ein schönes Beispiel für iota aus Kinopikos Beitrag :
quelle
Sie können Variablen durch parallele Zuordnung austauschen:
einfach aber effektiv.
quelle
Hier ist eine Redewendung von der Seite " Effective Go "
Die switch-Anweisung schaltet true ein, wenn kein Ausdruck angegeben wird. Das ist also gleichbedeutend mit
Im Moment sieht die Switch-Version für mich etwas sauberer aus.
quelle
Switch True
…)Typschalter :
quelle
Beim Importieren von Paketen können Sie den Namen nach Belieben neu definieren:
quelle
Benannte Ergebnisparameter
quelle
Aus James Antills Antwort :
Auch eine mögliche Gefahr: der subtile Unterschied zwischen den Empfangs- und Sendeoperatoren:
quelle
quelle
Ich finde es gut, dass Sie Typen, einschließlich Grundelemente wie int, beliebig oft neu definieren und verschiedene Methoden anhängen können. Wie beim Definieren eines RomanNumeral-Typs:
Welches druckt aus
Der
RomanNumber()
Aufruf ist im Wesentlichen eine Umwandlung, er definiert den int-Typ als einen spezifischeren Typ von int neu. UndPrintln()
ruftString()
hinter die Kulissen.quelle
Kanal zurückgeben
Dies ist eine wahre Redewendung, die sehr wichtig ist: wie man Daten in einen Kanal einspeist und ihn danach schließt. Mit diesem können Sie einfache Iteratoren (da der Bereich einen Kanal akzeptiert) oder Filter erstellen.
quelle
defer close(outch);
als erste Aussage der Goroutine?Zeitüberschreitung für Kanallesungen:
Von Davies Liu gestohlen .
quelle
Da der Bereich automatisch nach einem geschlossenen Kanal sucht, können wir Folgendes verkürzen:
quelle
Es gibt ein Make-System, das Sie in $ GOROOT / src verwenden können
Richten Sie Ihr Makefile mit ein
Sie können dann die automatisierten Testtools verwenden, indem Sie make test ausführen, oder das Paket und die freigegebenen Objekte von cgo mit make install zu Ihrem $ GOROOT hinzufügen.
quelle
Eine andere interessante Sache in Go ist das
godoc
. Sie können es als Webserver auf Ihrem Computer ausführenDabei ist 8080 die Portnummer, und die gesamte Website unter golang.org ist dann unter verfügbar
localhost:8080
.quelle
Dies ist eine Implementierung eines Stapels. Es zeigt das Hinzufügen von Methoden zu einem Typ.
Ich wollte den Stack-Teil davon in ein Slice verwandeln und die Eigenschaften des Slice verwenden, aber obwohl ich das ohne das
type
zum Laufen gebracht habe, konnte ich die Syntax zum Definieren eines Slice mit einem nicht sehentype
.quelle
fmt.Printf(...); os.Exit();
, können Sie verwendenpanic(...)
.C-Code von unterwegs aufrufen
Mit der c-Laufzeit ist es möglich, auf die untere Ebene von go zuzugreifen.
C-Funktionen sind in der Form
(Beachten Sie, dass der Punkttrenner ein Unicode-Zeichen ist.) Dabei können die Argumente grundlegende Go-Typen, Slices, Strings usw. sein. Um einen Wertaufruf zurückzugeben
(Sie können mehr als einen Wert zurückgeben)
Zum Beispiel, um eine Funktion zu erstellen
in C verwenden Sie
Beachten Sie, dass Sie die Funktion weiterhin in einer go-Datei deklarieren sollten und dass Sie sich selbst um den Speicher kümmern müssen. Ich bin mir nicht sicher, ob es möglich ist, externe Bibliotheken damit aufzurufen. Es ist möglicherweise besser, cgo zu verwenden.
In $ GOROOT / src / pkg / runtime finden Sie Beispiele für die Laufzeit.
Siehe auch diese Antwort zum Verknüpfen von C ++ - Code mit go.
quelle
Hier ist ein Go-Beispiel mit dem Paket sqlite3.
http://github.com/bikal/gosqlite-example
quelle
Hast du diesen Vortrag gesehen ? Es zeigt eine Menge cooler Sachen, die du machen kannst (Ende des Gesprächs)
quelle
Ein Stapel, der auf der anderen Antwort basiert, aber ein Slice verwendet, an das keine Größenbeschränkung angehängt ist.
quelle
quelle
for { /* infinite loop */ }
reicht.forever
Schlüsselwort. Sogar Qt hat ein Makro dafür.for ever
(nach dem Deklarieren der Variablen) etwas Süßes ist, das Sie in Go tun können, wenn Sie möchten. Es sieht aus wie Englisch (Modulo the Blank).#define ever (;;)
Es gibt viele kleine Programme im
test
Hauptverzeichnis. Beispiele:peano.go
druckt Fakultäten.hilbert.go
hat eine Matrixmultiplikation.iota.go
hat Beispiele für die seltsame Iota-Sache.quelle