Nie ma zbyt wiele kodu Go, z którego można by się nauczyć języka, i jestem pewien, że nie tylko ja z nim eksperymentuję. Jeśli więc znalazłeś coś interesującego w tym języku, zamieść tutaj przykład.
Obsługa ARM, na przykład 8-bitowa lub 16-bitowa. Język D nadal nie.
1
Biblioteka ( golang.org/pkg ) jest doskonałym źródłem informacji o używaniu go. Osobiście uważam, że poznanie sposobu implementacji struktur danych jest pomocne w nauce języka.
tkokasih
Odpowiedzi:
35
Odrocz oświadczenia
Instrukcja „defer” wywołuje funkcję, której wykonanie jest odroczone do momentu powrotu funkcji otaczającej.
DeferStmt = "defer" Wyrażenie.
Wyrażenie musi być funkcją lub wywołaniem metody. Za każdym razem, gdy wykonywana jest instrukcja „defer”, parametry wywołania funkcji są oceniane i zapisywane na nowo, ale funkcja nie jest wywoływana. Odroczone wywołania funkcji są wykonywane w kolejności LIFO bezpośrednio przed zwróceniem funkcji otaczającej, ale po oszacowaniu wartości zwracanych, jeśli istnieją.
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);
}
Aktualizacja:
deferjest teraz również idiomatycznym sposobem obsługi panicw sposób podobny do wyjątków :
package main
import"fmt"funcmain() {
f()
fmt.Println("Returned normally from f.")
}
funcf() {
deferfunc() {
if r := recover(); r != nil {
fmt.Println("Recovered in f", r)
}
}()
fmt.Println("Calling g.")
g(0)
fmt.Println("Returned normally from g.")
}
funcg(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)
}
Wygląda na stary dobry RAII (wyraźnie zaznaczony).
Konrad Rudolph
4
+1, ponieważ dużo czytałem o Go, ale nadal tego nie widziałem (dopóki mi nie pokazałeś)!
u0b34a0f6ae
Sprytne, chociaż dla mnie bardziej sensowne byłoby, gdyby odraczanie instrukcji było wykonywane w kolejności FIFO (od góry do dołu), ale może to tylko ja ...
@Mike: jeśli porównasz z blokami „try: .. w końcu:” LIFO zagnieżdża się w ten sam sposób. W przypadku par otwierania / zamykania zasobów itp. Takie zagnieżdżanie jest jedyną rzeczą, która ma sens (pierwsze otwarcie zamknie się jako ostatnie).
u0b34a0f6ae
25
Pliki obiektów Go zawierają w rzeczywistości nagłówek w postaci zwykłego tekstu:
jurily@jurily ~/workspace/go/euler31 $ 6g euler31.go
jurily@jurily ~/workspace/go/euler31 $ cat euler31.6
amd64
exports automatically generated from
euler31.go in package"main"import
$$ // exportspackage main
var main.coin [9]intfuncmain.howmany(amount int, max int)(? int)funcmain.main()var main.initdone· uint8funcmain.init()
$$ // local typestype main.dsigddd_1·1struct { ? int }
$$
!
<binary segment>
To bardziej jak ukryte cechy niż na przykład idiomatyczne
hasen
22
Widziałem kilka osób narzekających na pętlę for, w stylu „dlaczego powinniśmy mówić i = 0; i < len; i++w dzisiejszych czasach?”.
Nie zgadzam się, podoba mi się konstrukcja for. Jeśli chcesz, możesz użyć długiej wersji, ale idiomatyczny Go jest
var a = []int{1, 2, 3}
for i, v := range a {
fmt.Println(i, v)
}
for .. rangeKonstrukt pętle nad wszystkimi elementami i zasila dwie wartości - indeksi oraz wartośćv .
range działa również na mapach i kanałach.
Mimo to, jeśli nie podoba forw jakiejkolwiek formie, można określić each, mapitd. W kilku zdaniach:
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, value int)) {
for i, v := range a {
fn(i, v)
}
}
funcmain() {
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
}
Nie jestem pewien, co powinno być nie tak z formatowaniem; Przywróciłem to.
5
Autorzy Go polecają gofmtTwój kod :-)
ℝaphink
Nie mogę tego skompilować: $ ../go/src/cmd/6g/6g SO.go SO.go: 34: undefined: json.StringToJson
ℝaphink
@Raphink: język się zmienił, odkąd to zrobiłem.
Tak, czy wiesz, może co jest najbliższym odpowiednikiem StringToJson? Kiedyś wewnętrznie konfigurował program budujący, teraz trzeba zapewnić jego własną z predefiniowaną natywną strukturą?
type ByteSize float64const (
_ = 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 (!)
switch {
case'0' <= c && c <= '9':
return c - '0'case'a' <= c && c <= 'f':
return c - 'a' + 10case'A' <= c && c <= 'F':
return c - 'A' + 10
}
return0
Instrukcja switch włącza wartość true, gdy nie jest podane żadne wyrażenie. Więc to jest równoważne
if'0' <= c && c <= '9' {
return c - '0'
} elseif'a' <= c && c <= 'f' {
return c - 'a' + 10
} elseif'A' <= c && c <= 'F' {
return c - 'A' + 10
}
return0
W tej chwili wersja na Switcha wygląda dla mnie trochę czyściej.
switch i := x.(type) {
casenil:
printString("x is nil");
caseint:
printInt(i); // i is an intcase float:
printFloat(i); // i is a floatcasefunc(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");
}
Zwracającym lub wynikowym „parametrom” funkcji Go można nadać nazwy i używać ich jako zwykłych zmiennych, tak jak parametry przychodzące. Gdy są nazwane, są inicjowane z zerowymi wartościami dla ich typów, gdy rozpoczyna się funkcja; jeśli funkcja wykonuje instrukcję return bez argumentów, bieżące wartości parametrów wynikowych są używane jako wartości zwracane.
Nazwy nie są obowiązkowe, ale mogą sprawić, że kod będzie krótszy i bardziej przejrzysty: są dokumentacją. Jeśli nazwiemy wyniki nextInt, stanie się oczywiste, który zwrócony int jest który.
Ponieważ nazwane wyniki są inicjalizowane i powiązane z nie zdobionym zwrotem, mogą one zarówno upraszczać, jak i wyjaśniać. Oto wersja io.ReadFull, która dobrze je wykorzystuje:
/*
* 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}
funchowmany(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)
}
funcmain() {
fmt.Println(howmany(200, len(coin)-1))
}
Sugerowałbym usunięcie nazwy strony rozwiązywania problemów oraz numeru identyfikacyjnego. Może przeformułuj pytanie. Żeby nie zepsuć problemu komuś, kto się o to potyka. Lub próbować oszukiwać, szukając problemu w sieci.
Podoba mi się, że możesz przedefiniować typy, w tym prymitywy, takie jak int, tyle razy, ile chcesz, i dołączyć różne metody. Podobnie jak definiowanie typu RomanNumeral:
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 TextNumber inttype RomanNumber intfunc(n TextNumber)String()string {
return aText[n]
}
func(n RomanNumber)String()string {
return aRoman[n]
}
funcmain() {
var i = 5
fmt.Println("Number: ", i, TextNumber(i), RomanNumber(i))
}
Który się drukuje
Number: 5 five V
RomanNumber()Wezwanie jest w istocie obsada, to redefiniuje typu int jako bardziej konkretnego typu int. I Println()dzwoni String()za kulisami.
To prawdziwy idiom, który jest dość ważny: jak wprowadzić dane do kanału, a następnie go zamknąć. Dzięki temu możesz tworzyć proste iteratory (ponieważ zakres zaakceptuje kanał) lub filtry.
// return a channel that doubles the values in the input channelfuncDoublingIterator(input chanint)chanint {
outch := make(chanint);
// start a goroutine to feed the channel (asynchronously)gofunc() {
for x := range input {
outch <- 2*x;
}
// close the channel we created and controlclose(outch);
}();
return outch;
}
+1. Możesz także przepuszczać kanały przez kanały.
György Andrasek
5
Ale uważaj, aby nie wyrwać się z pętli for x: = range chan {}, ponieważ wycieknie goroutine i cała pamięć, do której się odnosi.
Jeff Allen,
3
@JeffAllen co powiesz defer close(outch);na pierwsze stwierdzenie goroutine?
1
Odroczenie kolejki instrukcji do wykonania, gdy funkcja zwraca, bez względu na to, który punkt powrotu zostanie przyjęty. Ale jeśli wejście kanału nigdy nie zostanie zamknięte, funkcja anonimowa w tym przykładzie nigdy nie opuści pętli for.
Jeff Allen
11
Limit czasu odczytu kanałów:
ticker := time.NewTicker(ns);
select {
case v := <- chan_target:
do_something_with_v;
case <- ticker.C:
handle_timeout;
}
Jest skonfigurowany system make, którego możesz użyć w $ GOROOT / src
Skonfiguruj swój plik makefile za pomocą
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 (6for x86_64)
include $(GOROOT)/src/Make.$(GOARCH)
include $(GOROOT)/src/Make.pkg
Następnie możesz użyć narzędzi do automatycznego testowania, uruchamiając make test lub dodać pakiet i obiekty udostępnione z cgo do $ GOROOT za pomocą polecenia make install.
To jest implementacja stosu. Ilustruje dodawanie metod do typu.
Chciałem przekształcić część stosu w plasterek i użyć właściwości tego wycinka, ale chociaż udało mi się to działać bez type, nie widziałem składni definiowania plasterka za pomocą type.
package main
import"fmt"import"os"const stack_max = 100type Stack2 struct {
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])
}
}
funcmain() {
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()
}
Zamiast używać fmt.Printf(...); os.Exit();, możesz użyć panic(...).
notnoop
1
To daje ślad stosu, którego nie chcę.
3
Dlaczego jest ograniczona? Go jest zarządzanym językiem. Twój stack może być tak głęboki, jak chcesz. Użyj nowej wbudowanej funkcji append (), która w razie potrzeby wykona coś w rodzaju ponownego przydzielenia w C.
Jeff Allen,
„Go nie potrzebuje leków generycznych” - powiedzieli.
cubuspl42
4
Dzwonię z kodu c z drogi
Dostęp do niższego poziomu go można uzyskać za pomocą środowiska uruchomieniowego c.
Funkcje C są w postaci
void package·function(...)
(zwróć uwagę, że separator kropek to znak Unicode), gdzie argumentami mogą być podstawowe typy go, plasterki, ciągi znaków itp. Aby zwrócić wywołanie wartości
FLUSH(&ret)
(możesz zwrócić więcej niż jedną wartość)
Na przykład, aby utworzyć funkcję
package foo
bar( a int32, b string )(c float32 ){
c = 1.3 + float32(a - int32(len(b))
}
w C używasz
#include "runtime.h"
void foo·bar(int32 a, String b, float32 c){
c = 1.3 + a - b.len;
FLUSH(&c);
}
Zwróć uwagę, że nadal powinieneś zadeklarować funkcję w pliku go i że będziesz musiał sam zadbać o pamięć. Nie jestem pewien, czy można przy użyciu tego wywoływać biblioteki zewnętrzne, może lepiej użyć cgo.
Spójrz na $ GOROOT / src / pkg / runtime, aby zobaczyć przykłady używane w środowisku wykonawczym.
Zobacz także tę odpowiedź, aby połączyć kod C ++ z go.
Czy naprawdę używa „latającej kropki”? Nie śmiem edytować, ale wydaje mi się to trochę nieoczekiwane i radykalne.
zrelaksuj się
Tak, musisz skompilować się z 6c (lub 8c itp.). Nie sądzę, że gcc obsługuje identyfikatory Unicode.
Scott Wales
1
Myślę, że AltGr + okresy są takie same · ale z Unicode nie jestem pewien. Byłem bardzo zaskoczony, widząc, że w źródle, które przeczytałem… dlaczego nie użyć czegoś takiego jak ::?
u0b34a0f6ae
Znak to ŚRODKOWA KROPKA U + 00B7. Parser mógł zostać sfałszowany tak, że widzi to jako znak w celu utworzenia prawidłowego identyfikatora c, co moim zdaniem wykluczałoby ::.
Scott Wales,
4
Znak „·” to tylko tymczasowe włamanie, Rob był nawet zaskoczony, że wciąż tam jest, powiedział, że zostanie zastąpiony czymś mniej osobliwym.
Oczywiście. Dokładnie to się tutaj dzieje. Po prostu podoba mi się foreversłowo kluczowe. Nawet Qt ma do tego makro.
György Andrasek
6
ale Go nie potrzebuje do tego makra ani uroczego aliasu true.
u0b34a0f6ae
@ kaizer.se: Jurily twierdzi, że for ever(po zadeklarowaniu zmiennej) jest to coś fajnego, co możesz zrobić w Go, jeśli chcesz. Wygląda jak angielski (modulo the blank).
Frank
8
to jest coś #define ever (;;)
fajnego,
2
W testgłównym katalogu znajduje się wiele małych programów . Przykłady:
Odpowiedzi:
Odrocz oświadczenia
lock(l); defer unlock(l); // unlocking happens before surrounding function returns // prints 3 2 1 0 before surrounding function returns for i := 0; i <= 3; i++ { defer fmt.Print(i); }
Aktualizacja:
defer
jest teraz również idiomatycznym sposobem obsługipanic
w sposób podobny do wyjątków :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) }
źródło
Pliki obiektów Go zawierają w rzeczywistości nagłówek w postaci zwykłego tekstu:
jurily@jurily ~/workspace/go/euler31 $ 6g euler31.go jurily@jurily ~/workspace/go/euler31 $ cat euler31.6 amd64 exports automatically generated from euler31.go in package "main" import $$ // exports package 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·1 struct { ? int } $$ ! <binary segment>
źródło
Widziałem kilka osób narzekających na pętlę for, w stylu „dlaczego powinniśmy mówić
i = 0; i < len; i++
w dzisiejszych czasach?”.Nie zgadzam się, podoba mi się konstrukcja for. Jeśli chcesz, możesz użyć długiej wersji, ale idiomatyczny Go jest
var a = []int{1, 2, 3} for i, v := range a { fmt.Println(i, v) }
for .. range
Konstrukt pętle nad wszystkimi elementami i zasila dwie wartości - indeksi
oraz wartośćv
.range
działa również na mapach i kanałach.Mimo to, jeśli nie podoba
for
w jakiejkolwiek formie, można określićeach
,map
itd. W kilku zdaniach: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, value int)) { for i, v := range a { fn(i, v) } } func main() { var a = IntArr([]int{2, 0, 0, 9}) // create int slice and cast to IntArr var fnPrint = func(i, v int) { fmt.Println(i, ":", v) } // create a function a.each(fnPrint) // call on each element }
wydruki
0 : 2 1 : 0 2 : 0 3 : 9
Zaczynam bardzo lubić Go :)
źródło
range
jest fajny tylko wtedy, gdy jest skompilowany do tego samego kodu co pętla for-3.Idź i zdobądź swoją reputację przepełnienia stosów
To jest tłumaczenie tej odpowiedzi .
package main import ( "json" "fmt" "http" "os" "strings" ) func die(message string) { fmt.Printf("%s.\n", message); os.Exit(1); } func main() { kinopiko_flair := "https://stackoverflow.com/users/flair/181548.json" response, _, err := http.Get(kinopiko_flair) if err != nil { die(fmt.Sprintf("Error getting %s", kinopiko_flair)) } var nr int const buf_size = 0x1000 buf := make([]byte, buf_size) nr, err = response.Body.Read(buf) if err != nil && error != os.EOF { die(fmt.Sprintf("Error reading response: %s", err.String())) } if nr >= buf_size { die ("Buffer overrun") } response.Body.Close() json_text := strings.Split(string(buf), "\000", 2) parsed, ok, errtok := json.StringToJson(json_text[0]) if ! ok { die(fmt.Sprintf("Error parsing JSON %s at %s", json_text, errtok)) } fmt.Printf("Your stackoverflow.com reputation is %s\n", parsed.Get ("reputation")) }
Dzięki Scotta Walesa za pomoc z .Read ().
To wciąż wygląda dość niezgrabnie, z dwoma ciągami i dwoma buforami, więc jeśli któryś z ekspertów Go ma radę, daj mi znać.
źródło
gofmt
Twój kod :-)Oto ładny przykład joty z postu Kinopiko :
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 (!)
źródło
Możesz zamieniać zmienne przez równoległe przypisanie:
x, y = y, x // or in an array a[j], a[i] = a[i], a[j]
proste ale efektywne.
źródło
Oto idiom z Skuteczna Go stronie
switch { case '0' <= c && c <= '9': return c - '0' case 'a' <= c && c <= 'f': return c - 'a' + 10 case 'A' <= c && c <= 'F': return c - 'A' + 10 } return 0
Instrukcja switch włącza wartość true, gdy nie jest podane żadne wyrażenie. Więc to jest równoważne
if '0' <= c && c <= '9' { return c - '0' } else if 'a' <= c && c <= 'f' { return c - 'a' + 10 } else if 'A' <= c && c <= 'F' { return c - 'A' + 10 } return 0
W tej chwili wersja na Switcha wygląda dla mnie trochę czyściej.
źródło
Switch True
…)Typ przełączników :
switch i := x.(type) { case nil: printString("x is nil"); case int: printInt(i); // i is an int case float: printFloat(i); // i is a float case func(int) float: printFunction(i); // i is a function case bool, string: printString("type is bool or string"); // i is an interface{} default: printString("don't know the type"); }
źródło
Importując pakiety, możesz zmienić nazwę na dowolną:
package main import f "fmt" func main() { f.Printf("Hello World\n") }
źródło
Nazwane parametry wyników
func nextInt(b []byte, pos int) (value, nextPos int) {
func ReadFull(r Reader, buf []byte) (n int, err os.Error) { for len(buf) > 0 && err == nil { var nr int; nr, err = r.Read(buf); n += nr; buf = buf[nr:len(buf)]; } return; }
źródło
Z Jamesa Antilla :
foo := <-ch // This blocks. foo, ok := <-ch // This returns immediately.
Potencjalna pułapka: subtelna różnica między operatorami odbierania i wysyłania:
a <- ch // sends ch to channel a <-ch // reads from channel ch
źródło
/* * 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 { return 1 } if amount < 0 { return 0 } if max <= 0 && amount >= 1 { return 0 } // recursion works as expected return howmany(amount, max-1) + howmany(amount-coin[max], max) } func main() { fmt.Println(howmany(200, len(coin)-1)) }
źródło
Podoba mi się, że możesz przedefiniować typy, w tym prymitywy, takie jak int, tyle razy, ile chcesz, i dołączyć różne metody. Podobnie jak definiowanie typu RomanNumeral:
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 TextNumber int type RomanNumber int 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)) }
Który się drukuje
Number: 5 five V
RomanNumber()
Wezwanie jest w istocie obsada, to redefiniuje typu int jako bardziej konkretnego typu int. IPrintln()
dzwoniString()
za kulisami.źródło
Zwracanie kanału
To prawdziwy idiom, który jest dość ważny: jak wprowadzić dane do kanału, a następnie go zamknąć. Dzięki temu możesz tworzyć proste iteratory (ponieważ zakres zaakceptuje kanał) lub filtry.
// 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; }
źródło
defer close(outch);
na pierwsze stwierdzenie goroutine?Limit czasu odczytu kanałów:
ticker := time.NewTicker(ns); select { case v := <- chan_target: do_something_with_v; case <- ticker.C: handle_timeout; }
Skradziony Daviesowi Liu .
źródło
for { v := <-ch if closed(ch) { break } fmt.Println(v) }
Ponieważ zakres automatycznie sprawdza zamknięty kanał, możemy skrócić do tego:
for v := range ch { fmt.Println(v) }
źródło
Jest skonfigurowany system make, którego możesz użyć w $ GOROOT / src
Skonfiguruj swój plik makefile za pomocą
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
Następnie możesz użyć narzędzi do automatycznego testowania, uruchamiając make test lub dodać pakiet i obiekty udostępnione z cgo do $ GOROOT za pomocą polecenia make install.
źródło
Inną interesującą rzeczą w Go jest to
godoc
. Możesz uruchomić go jako serwer WWW na swoim komputerze za pomocągodoc -http=:8080
gdzie 8080 to numer portu, a cała witryna internetowa pod adresem golang.org jest dostępna pod adresem
localhost:8080
.źródło
To jest implementacja stosu. Ilustruje dodawanie metod do typu.
Chciałem przekształcić część stosu w plasterek i użyć właściwości tego wycinka, ale chociaż udało mi się to działać bez
type
, nie widziałem składni definiowania plasterka za pomocątype
.package main import "fmt" import "os" const stack_max = 100 type Stack2 struct { 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() }
źródło
fmt.Printf(...); os.Exit();
, możesz użyćpanic(...)
.Dzwonię z kodu c z drogi
Dostęp do niższego poziomu go można uzyskać za pomocą środowiska uruchomieniowego c.
Funkcje C są w postaci
void package·function(...)
(zwróć uwagę, że separator kropek to znak Unicode), gdzie argumentami mogą być podstawowe typy go, plasterki, ciągi znaków itp. Aby zwrócić wywołanie wartości
(możesz zwrócić więcej niż jedną wartość)
Na przykład, aby utworzyć funkcję
package foo bar( a int32, b string )(c float32 ){ c = 1.3 + float32(a - int32(len(b)) }
w C używasz
#include "runtime.h" void foo·bar(int32 a, String b, float32 c){ c = 1.3 + a - b.len; FLUSH(&c); }
Zwróć uwagę, że nadal powinieneś zadeklarować funkcję w pliku go i że będziesz musiał sam zadbać o pamięć. Nie jestem pewien, czy można przy użyciu tego wywoływać biblioteki zewnętrzne, może lepiej użyć cgo.
Spójrz na $ GOROOT / src / pkg / runtime, aby zobaczyć przykłady używane w środowisku wykonawczym.
Zobacz także tę odpowiedź, aby połączyć kod C ++ z go.
źródło
Oto przykład go z użyciem pakietu sqlite3.
http://github.com/bikal/gosqlite-example
źródło
Oglądałeś tę rozmowę ? Pokazuje wiele fajnych rzeczy, które możesz zrobić (koniec rozmowy)
źródło
Stos oparty na drugiej odpowiedzi, ale przy użyciu dołączania plasterków nie ma ograniczenia rozmiaru.
package main import "fmt" import "os" type Stack2 struct { // 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() }
źródło
const ever = true for ever { // infinite loop }
źródło
for { /* infinite loop */ }
wystarczy.forever
słowo kluczowe. Nawet Qt ma do tego makro.for ever
(po zadeklarowaniu zmiennej) jest to coś fajnego, co możesz zrobić w Go, jeśli chcesz. Wygląda jak angielski (modulo the blank).#define ever (;;)
W
test
głównym katalogu znajduje się wiele małych programów . Przykłady:peano.go
drukuje silnie.hilbert.go
ma pewne mnożenie macierzy.iota.go
ma przykłady dziwnej joty.źródło