Não há muito código Go para aprender a linguagem, e tenho certeza de que não sou o único fazendo experiências com isso. Então, se você descobriu algo interessante sobre o idioma, poste um exemplo aqui.
Suporte a ARM, como 8 bits ou 16 bits. A linguagem D ainda não.
1
A biblioteca ( golang.org/pkg ) é uma excelente fonte para aprender como o go é usado. Pessoalmente, acho que aprender como as estruturas de dados são implementadas é útil para aprender a linguagem.
tkokasih
Respostas:
35
Adiar declarações
Uma instrução "adiar" invoca uma função cuja execução é adiada para o momento em que a função circundante retorna.
DeferStmt = "adiar" Expressão.
A expressão deve ser uma função ou chamada de método. Cada vez que a instrução "adiar" é executada, os parâmetros da chamada de função são avaliados e salvos novamente, mas a função não é chamada. Chamadas de função adiadas são executadas em ordem LIFO imediatamente antes do retorno da função circundante, mas depois que os valores de retorno, se houver, forem avaliados.
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);}
Atualizar:
deferé agora também a maneira idiomática de manusear panicem uma excepção semelhante forma:
package mainimport"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)}
@Mike: se você comparar com blocos de "try: .. finally:" ninhos LIFO da mesma maneira. Para pares de recursos abertos / fechados, etc., aninhar assim é a única coisa que faz sentido (a primeira abertura fecha por último).
u0b34a0f6ae
25
Os arquivos de objeto Go na verdade incluem um cabeçalho de texto não criptografado:
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>
Isso é mais um recurso oculto do que um exemplo idiomático
hasen
22
Tenho visto algumas pessoas reclamando do loop for, do tipo "por que deveríamos dizer i = 0; i < len; i++nos dias de hoje?".
Eu discordo, gosto da construção for. Você pode usar a versão longa se desejar, mas a idiomática Go é
var a =[]int{1,2,3}for i, v := range a {
fmt.Println(i, v)}
A for .. rangeconstrução percorre todos os elementos e fornece dois valores - o índice ie o valor v.
range também funciona em mapas e canais.
Ainda assim, se você não gostar forde alguma forma, você pode definir each, mapetc. em algumas linhas:
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}
Não tenho certeza do que deveria estar errado com a formatação; Eu o restaurei.
5
Os autores do Go recomendam para o gofmtseu código :-)
ℝaphink
Não consigo compilá-lo: $ ../go/src/cmd/6g/6g SO.go SO.go: 34: undefined: json.StringToJson
ℝaphink
@Raphink: a linguagem mudou desde que fiz isso.
Sim, você sabe o que é o equivalente mais próximo do StringToJson? Costumava configurar um construtor internamente, agora é preciso fornecer o seu próprio com uma estrutura nativa predefinida?
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 (!)
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");}
Os "parâmetros" de retorno ou resultado de uma função Go podem receber nomes e usados como variáveis regulares, assim como os parâmetros de entrada. Quando nomeados, eles são inicializados com os valores zero para seus tipos quando a função começa; se a função executa uma instrução de retorno sem argumentos, os valores atuais dos parâmetros de resultado são usados como os valores retornados.
Os nomes não são obrigatórios, mas podem tornar o código mais curto e claro: eles são documentação. Se nomearmos os resultados de nextInt, ficará óbvio qual int retornado é qual.
Como os resultados nomeados são inicializados e vinculados a um retorno sem adornos, eles podem simplificar e esclarecer. Esta é uma versão de io.ReadFull que os usa bem:
/*
* 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))}
Eu sugeriria remover o nome do site de solução de problemas, bem como o número de identificação. Talvez reformule a pergunta. Para não estragar o problema para quem está tropeçando nele. Ou tentando trapacear procurando o problema na net.
Gosto que você possa redefinir tipos, incluindo primitivos como int, quantas vezes quiser e anexar métodos diferentes. Como definir um tipo 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 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))}
Que imprime
Number:5 five V
A RomanNumber()chamada é essencialmente uma conversão, ela redefine o tipo int como um tipo mais específico de int. E Println()ligações String()nos bastidores.
Este é um verdadeiro idioma muito importante: como inserir dados em um canal e fechá-lo depois. Com isso, você pode fazer iteradores simples (já que o intervalo aceitará um canal) ou filtros.
// 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;}
+1. Além disso, você pode passar canais por canais também.
György Andrasek
5
Mas tome cuidado para não quebrar um loop for x: = range chan {}, você vazará a goroutine e toda a memória a que ela faz referência.
Jeff Allen
3
@JeffAllen que tal defer close(outch);como a primeira declaração do goroutine?
1
Adiar enfileira uma instrução para execução quando a função retornar, não importa qual ponto de retorno seja obtido. Mas se a entrada do canal nunca for fechada, a função anônima neste exemplo nunca sairá do loop for.
Jeff Allen
11
Tempo limite para leituras de canal:
ticker := time.NewTicker(ns);select{case v :=<- chan_target:
do_something_with_v;case<- ticker.C:
handle_timeout;}
Existe um make system configurado que você pode usar em $ GOROOT / src
Configure seu makefile com
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
Você pode então usar as ferramentas de teste automatizadas executando make test ou adicionar o pacote e objetos compartilhados de cgo ao seu $ GOROOT com make install.
Esta é uma implementação de uma pilha. Ele ilustra a adição de métodos em um tipo.
Eu queria transformar a pilha em uma fatia e usar as propriedades da fatia, mas embora tenha feito isso funcionar sem o type, não consegui ver a sintaxe para definir uma fatia com um 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()}
Em vez de usar fmt.Printf(...); os.Exit();, você pode usar panic(...).
notnoop
1
Isso fornece um rastreamento de pilha, o que eu não quero.
3
Por que é limitado? Go é uma linguagem gerida, gc'd. Sua pilha pode ser tão grande quanto você quiser. Use o novo append () embutido, que fará algo como o realloc do C quando for necessário.
Jeff Allen
“Go não precisa de genéricos”, disseram.
cubuspl42
4
Chamando o código c de início
É possível acessar o nível inferior de go usando o tempo de execução c.
As funções C estão na forma
voidpackage·function(...)
(note que o separador de pontos é um caractere Unicode) onde os argumentos podem ser tipos básicos de go, fatias, strings etc. Para retornar uma chamada de valor
FLUSH(&ret)
(você pode retornar mais de um valor)
Por exemplo, para criar uma função
package foo
bar( a int32, b string)(c float32 ){
c =1.3+ float32(a - int32(len(b))}
em C você usa
#include"runtime.h"void foo·bar(int32 a,String b, float32 c){
c =1.3+ a - b.len;
FLUSH(&c);}
Observe que você ainda deve declarar a função em um arquivo go e que terá que cuidar da memória sozinho. Não tenho certeza se é possível chamar bibliotecas externas usando isso, talvez seja melhor usar cgo.
Ele usa o "ponto voador", realmente? Não me atrevo a editar, mas isso parece um pouco inesperado e radical.
relaxe
Sim, você precisa compilar com 6c (ou 8c, etc). Eu não acho que o gcc lida com identificadores Unicode.
Scott Wales
1
Acho que AltGr + tipos de período são iguais, mas com Unicode não tenho certeza. Fiquei muito surpreso ao ver que li na fonte .. por que não usar algo como ::?
u0b34a0f6ae
O personagem é MIDDLE DOT U + 00B7. O analisador pode ter sido falsificado para que ele veja isso como um caractere a fim de fazer um identificador c válido, o que eu acredito que impediria ::.
Scott Wales
4
O '·' é apenas um hack temporário, o roubo até ficou surpreso por ele ainda estar lá, ele disse que seria substituído por algo menos idiossincrático.
Sim eu fiz. Tudo se resume a "Há muito mais aí, vamos passar para o próximo tópico."
György Andrasek
Sim, aparentemente muito a dizer em pouco tempo
3
Uma pilha baseada na outra resposta, mas usando acréscimo de fatia para não ter limite de tamanho.
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()}
Claro. Isso é exatamente o que está acontecendo aqui. Eu apenas gosto da foreverpalavra - chave. Até o Qt tem uma macro para isso.
György Andrasek
6
mas Go não precisa de uma macro ou um apelido fofo de true para fazer isso.
u0b34a0f6ae
@ kaizer.se: O ponto de Jurily é que for ever(depois de declarar a variável) é algo bonito que você pode fazer no Go, se quiser. Parece inglês (modulo the blank).
Frank de
8
é algo fofo que você também pode fazer em C .. :-)#define ever (;;)
u0b34a0f6ae
2
Existem vários pequenos programas no testdiretório principal. Exemplos:
Respostas:
Adiar declarações
Atualizar:
defer
é agora também a maneira idiomática de manusearpanic
em uma excepção semelhante forma:fonte
Os arquivos de objeto Go na verdade incluem um cabeçalho de texto não criptografado:
fonte
Tenho visto algumas pessoas reclamando do loop for, do tipo "por que deveríamos dizer
i = 0; i < len; i++
nos dias de hoje?".Eu discordo, gosto da construção for. Você pode usar a versão longa se desejar, mas a idiomática Go é
A
for .. range
construção percorre todos os elementos e fornece dois valores - o índicei
e o valorv
.range
também funciona em mapas e canais.Ainda assim, se você não gostar
for
de alguma forma, você pode definireach
,map
etc. em algumas linhas:estampas
Estou começando a gostar muito do Go :)
fonte
range
só é bom se for compilado com o mesmo código do loop for-3.Vá e obtenha sua reputação de stackoverflow
Esta é uma tradução desta resposta .
Agradecimentos a Scott Wales pela ajuda com .Read ().
Isso ainda parece bastante desajeitado, com as duas strings e dois buffers, então, se algum especialista em Go tiver conselhos, me avise.
fonte
gofmt
seu código :-)Aqui está um bom exemplo de iota da postagem de Kinopiko :
fonte
Você pode trocar variáveis por atribuição paralela:
simples mas efetivo.
fonte
Aqui está um idioma da página Effective Go
A instrução switch muda para true quando nenhuma expressão é fornecida. Então, isso é equivalente a
No momento, a versão switch parece um pouco mais limpa para mim.
fonte
Switch True
…)Interruptores de tipo :
fonte
Ao importar pacotes, você pode redefinir o nome para o que quiser:
fonte
Parâmetros de resultado nomeados
fonte
Da resposta de James Antill :
Além disso, uma armadilha potencial: a diferença sutil entre os operadores de recebimento e envio:
fonte
fonte
Gosto que você possa redefinir tipos, incluindo primitivos como int, quantas vezes quiser e anexar métodos diferentes. Como definir um tipo RomanNumeral:
Que imprime
A
RomanNumber()
chamada é essencialmente uma conversão, ela redefine o tipo int como um tipo mais específico de int. EPrintln()
ligaçõesString()
nos bastidores.fonte
Retornando um canal
Este é um verdadeiro idioma muito importante: como inserir dados em um canal e fechá-lo depois. Com isso, você pode fazer iteradores simples (já que o intervalo aceitará um canal) ou filtros.
fonte
defer close(outch);
como a primeira declaração do goroutine?Tempo limite para leituras de canal:
Roubado de Davies Liu .
fonte
Como o alcance verifica automaticamente se há um canal fechado, podemos encurtar para isso:
fonte
Existe um make system configurado que você pode usar em $ GOROOT / src
Configure seu makefile com
Você pode então usar as ferramentas de teste automatizadas executando make test ou adicionar o pacote e objetos compartilhados de cgo ao seu $ GOROOT com make install.
fonte
Outra coisa interessante no Go é isso
godoc
. Você pode executá-lo como um servidor web em seu computador usandoonde 8080 é o número da porta e todo o site em golang.org está disponível em
localhost:8080
.fonte
Esta é uma implementação de uma pilha. Ele ilustra a adição de métodos em um tipo.
Eu queria transformar a pilha em uma fatia e usar as propriedades da fatia, mas embora tenha feito isso funcionar sem o
type
, não consegui ver a sintaxe para definir uma fatia com umtype
.fonte
fmt.Printf(...); os.Exit();
, você pode usarpanic(...)
.Chamando o código c de início
É possível acessar o nível inferior de go usando o tempo de execução c.
As funções C estão na forma
(note que o separador de pontos é um caractere Unicode) onde os argumentos podem ser tipos básicos de go, fatias, strings etc. Para retornar uma chamada de valor
(você pode retornar mais de um valor)
Por exemplo, para criar uma função
em C você usa
Observe que você ainda deve declarar a função em um arquivo go e que terá que cuidar da memória sozinho. Não tenho certeza se é possível chamar bibliotecas externas usando isso, talvez seja melhor usar cgo.
Veja $ GOROOT / src / pkg / runtime para exemplos usados em runtime.
Veja também esta resposta para vincular o código c ++ a go.
fonte
Aqui está um exemplo go usando o pacote sqlite3.
http://github.com/bikal/gosqlite-example
fonte
Você assistiu a essa palestra ? Mostra muitas coisas legais que você pode fazer (fim da palestra)
fonte
Uma pilha baseada na outra resposta, mas usando acréscimo de fatia para não ter limite de tamanho.
fonte
fonte
for { /* infinite loop */ }
basta.forever
palavra - chave. Até o Qt tem uma macro para isso.for ever
(depois de declarar a variável) é algo bonito que você pode fazer no Go, se quiser. Parece inglês (modulo the blank).#define ever (;;)
Existem vários pequenos programas no
test
diretório principal. Exemplos:peano.go
imprime fatoriais.hilbert.go
tem alguma multiplicação de matriz.iota.go
tem exemplos da coisa estranha do iota.fonte