No hay mucho código Go para aprender el idioma, y estoy seguro de que no soy el único que está experimentando con él. Entonces, si descubrió algo interesante sobre el idioma, publique un ejemplo aquí.
Soporte ARM como 8 bits o 16 bits. El lenguaje D todavía no lo hace.
1
La biblioteca ( golang.org/pkg ) es una fuente excelente para aprender cómo se usa go. Personalmente, encuentro que aprender cómo se implementan las estructuras de datos es útil para aprender el idioma.
tkokasih
Respuestas:
35
Aplazar declaraciones
Una instrucción "diferir" invoca una función cuya ejecución se aplaza hasta el momento en que regresa la función circundante.
DeferStmt = "aplazar" Expresión.
La expresión debe ser una función o una llamada a un método. Cada vez que se ejecuta la instrucción "aplazar", los parámetros de la llamada a la función se evalúan y se guardan de nuevo, pero la función no se invoca. Las llamadas a funciones diferidas se ejecutan en orden LIFO inmediatamente antes de que regrese la función circundante, pero después de que se hayan evaluado los valores devueltos, si los hay.
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);}
Actualizar:
deferahora también es la forma idiomática de manejar panicde una manera similar a una excepción :
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)}
+1 ya que leí mucho sobre Go, ¡pero todavía no vi esto (hasta que me lo mostraste)!
u0b34a0f6ae
Inteligente, aunque tendría más sentido para mí si las declaraciones diferidas se ejecutaran en orden FIFO (de arriba a abajo), pero tal vez sea solo yo ...
@Mike: si lo comparas con bloques de "prueba: .. finalmente:" LIFO anida de la misma manera. Para los pares de recursos abiertos / cerrados, etc., anidar como este es lo único que tiene sentido (la primera apertura se cerrará al final).
u0b34a0f6ae
25
Los archivos de objetos Go en realidad incluyen un encabezado de texto sin formato:
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>
Eso es más una característica oculta que un ejemplo idiomático
hasen
22
He visto a un par de personas quejarse del bucle for, en la línea de "¿por qué deberíamos tener que decir i = 0; i < len; i++en estos tiempos?".
No estoy de acuerdo, me gusta la construcción. Puede usar la versión larga si lo desea, pero la idiomática Go es
var a =[]int{1,2,3}for i, v := range a {
fmt.Println(i, v)}
La for .. rangeconstrucción recorre todos los elementos y proporciona dos valores: el índice iy el valor v.
range también funciona en mapas y canales.
Aún así, si no le gusta forde alguna forma, puede definir each, mapetc.en unas pocas líneas:
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}
No estoy seguro de qué se suponía que estaba mal con el formato; Lo he restaurado.
5
Los autores de Go recomiendan gofmtsu código :-)
ℝaphink
No puedo compilarlo: $ ../go/src/cmd/6g/6g SO.go SO.go: 34: undefined: json.StringToJson
ℝaphink
@Raphink: el idioma ha cambiado desde que hice esto.
Sí, ¿sabes cuál es el equivalente más cercano al StringToJson? Solía configurar un constructor internamente, ¿ahora uno tiene que proporcionar el suyo con una estructura 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");}
Los "parámetros" de retorno o resultado de una función Go pueden recibir nombres y usarse como variables regulares, al igual que los parámetros entrantes. Cuando se nombran, se inicializan a los valores cero para sus tipos cuando comienza la función; si la función ejecuta una declaración de retorno sin argumentos, los valores actuales de los parámetros de resultado se utilizan como valores devueltos.
Los nombres no son obligatorios pero pueden hacer que el código sea más corto y claro: son documentación. Si nombramos los resultados de nextInt, resulta obvio qué int devuelto es cuál.
Debido a que los resultados con nombre se inicializan y vinculan a una devolución sin adornos, pueden simplificar y aclarar. Aquí hay una versión de io.ReadFull que los usa bien:
/*
* 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))}
Sugeriría eliminar el nombre del sitio de resolución de problemas, así como el número de identificación. Quizás reformule la pregunta. Para no estropear el problema a alguien que se tropieza con él. O tratando de hacer trampa buscando el problema en la red.
Me gusta que puedas redefinir tipos, incluidas primitivas como int, tantas veces como quieras y adjuntar diferentes métodos. Como definir un 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
La RomanNumber()llamada es esencialmente un molde, redefine el tipo int como un tipo más específico de int. Y Println()llama String()entre bastidores.
Este es un verdadero idioma que es bastante importante: cómo introducir datos en un canal y cerrarlo después. Con esto puede hacer iteradores simples (ya que el rango aceptará un canal) o 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. Además, también puede pasar canales a través de canales.
György Andrasek
5
Pero tenga cuidado de no salirse de un bucle for x: = range chan {}, perderá la goroutine y toda la memoria a la que hace referencia.
Jeff Allen
3
@JeffAllen ¿qué defer close(outch);tal como la primera declaración de la goroutine?
1
Aplazar pone en cola una instrucción para su ejecución cuando la función regresa, sin importar qué punto de retorno se tome. Pero si la entrada del canal nunca se cierra, entonces la función anónima en este ejemplo nunca abandonará el bucle for.
Jeff Allen
11
Tiempo de espera para las lecturas del canal:
ticker := time.NewTicker(ns);select{case v :=<- chan_target:
do_something_with_v;case<- ticker.C:
handle_timeout;}
Hay una configuración de sistema de creación que puede usar en $ GOROOT / src
Configure su archivo MAKE con
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
Luego, puede usar las herramientas de prueba automatizadas ejecutando make test, o agregar el paquete y los objetos compartidos de cgo a su $ GOROOT con make install.
Esta es una implementación de una pila. Ilustra la adición de métodos a un tipo.
Quería convertir la pila en parte de ella en un segmento y usar las propiedades del segmento, pero aunque logré que funcionara sin el type, no pude ver la sintaxis para definir un segmento con 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()}
En lugar de usar fmt.Printf(...); os.Exit();, puede usar panic(...).
notnoop
1
Eso da un rastro de pila, que no quiero.
3
¿Por qué es limitado? Go es un idioma controlado por GC. Tu pila puede ser tan profunda como quieras. Use el nuevo append () incorporado, que hará algo como la reasignación de C cuando sea necesario.
Jeff Allen
"Go no necesita genéricos", dijeron.
cubuspl42
4
Llamar al código c desde ir
Es posible acceder al nivel inferior de go utilizando el tiempo de ejecución de c.
Las funciones C tienen la forma
voidpackage·function(...)
(tenga en cuenta que el separador de puntos es un carácter Unicode) donde los argumentos pueden ser tipos básicos, cortes, cadenas, etc. Para devolver un valor, llame
FLUSH(&ret)
(puede devolver más de un valor)
Por ejemplo, para crear una función
package foo
bar( a int32, b string)(c float32 ){
c =1.3+ float32(a - int32(len(b))}
en C usas
#include"runtime.h"void foo·bar(int32 a,String b, float32 c){
c =1.3+ a - b.len;
FLUSH(&c);}
Tenga en cuenta que aún debe declarar la función en un archivo go y que tendrá que ocuparse de la memoria usted mismo. No estoy seguro de si es posible llamar a bibliotecas externas usando esto, puede ser mejor usar cgo.
Mire $ GOROOT / src / pkg / runtime para ver ejemplos usados en el tiempo de ejecución.
Consulte también esta respuesta para vincular el código c ++ con go.
¿Realmente usa el "punto volador"? No me atrevo a editar, pero eso parece un poco inesperado y radical.
relajarse el
Sí, necesita compilar con 6c (o 8c, etc.). No creo que gcc maneje identificadores Unicode.
Scott Wales
1
Creo que los tipos de período AltGr + son iguales · pero con Unicode no estoy seguro. Me sorprendió mucho ver que en la fuente que leí ... ¿por qué no usar algo como ::?
u0b34a0f6ae
El carácter es MIDDLE DOT U + 00B7. El analizador puede haber sido manipulado para que lo vea como un carácter para hacer un identificador c válido, lo que creo que excluiría ::.
Scott Wales
4
El '·' es solo un truco temporal, Rob incluso se sorprendió de que todavía estuviera allí, dijo que iba a ser reemplazado por algo menos idiosincrásico.
uriel
4
Aquí hay un ejemplo de go usando el paquete sqlite3.
Sí, lo hice. Todo se reduce a "Hay mucho más ahí, pasemos al siguiente tema".
György Andrasek
Sí, aparentemente hay mucho que decir en poco tiempo
3
Una pila basada en la otra respuesta, pero usando un segmento que se agrega para no tener límite de tamaño.
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()}
Por supuesto. Eso es exactamente lo que está pasando aquí. Simplemente me gusta la foreverpalabra clave. Incluso Qt tiene una macro para eso.
György Andrasek
6
pero Go no necesita una macro o un lindo alias de verdadero para hacer esto.
u0b34a0f6ae
@ kaizer.se: El punto de Jurily es que for ever(después de declarar la variable) es algo lindo que puedes hacer en Go si quieres. Parece inglés (módulo en blanco).
Frank
8
es algo lindo que también puedes hacer en C .. :-)#define ever (;;)
u0b34a0f6ae
2
Hay muchos programas pequeños en test en el directorio principal. Ejemplos:
peano.go imprime factoriales.
hilbert.go tiene algo de multiplicación de matrices.
Respuestas:
Aplazar declaraciones
Actualizar:
defer
ahora también es la forma idiomática de manejarpanic
de una manera similar a una excepción :fuente
Los archivos de objetos Go en realidad incluyen un encabezado de texto sin formato:
fuente
He visto a un par de personas quejarse del bucle for, en la línea de "¿por qué deberíamos tener que decir
i = 0; i < len; i++
en estos tiempos?".No estoy de acuerdo, me gusta la construcción. Puede usar la versión larga si lo desea, pero la idiomática Go es
La
for .. range
construcción recorre todos los elementos y proporciona dos valores: el índicei
y el valorv
.range
también funciona en mapas y canales.Aún así, si no le gusta
for
de alguna forma, puede definireach
,map
etc.en unas pocas líneas:huellas dactilares
Me está empezando a gustar mucho Go :)
fuente
range
solo es bueno si se compila con el mismo código que el bucle for-3.Ve y obtén tu reputación de stackoverflow
Esta es una traducción de esta respuesta .
Gracias a Scott Wales por su ayuda con .Read ().
Esto todavía parece bastante torpe, con las dos cadenas y dos búferes, así que si algún experto en Go tiene un consejo, hágamelo saber.
fuente
gofmt
su código :-)Aquí hay un buen ejemplo de iota de la publicación de Kinopiko :
fuente
Puede intercambiar variables por asignación paralela:
simple pero efectivo.
fuente
Aquí hay un modismo de la página Effective Go
La instrucción switch se activa cuando no se proporciona ninguna expresión. Entonces esto es equivalente a
Por el momento, la versión conmutada me parece un poco más limpia.
fuente
Switch True
…)Interruptores de tipo :
fuente
Al importar paquetes, puede redefinir el nombre a lo que desee:
fuente
Parámetros de resultado con nombre
fuente
De la respuesta de James Antill :
Además, un error potencial: la sutil diferencia entre los operadores de envío y recepción:
fuente
fuente
Me gusta que puedas redefinir tipos, incluidas primitivas como int, tantas veces como quieras y adjuntar diferentes métodos. Como definir un tipo RomanNumeral:
Que imprime
La
RomanNumber()
llamada es esencialmente un molde, redefine el tipo int como un tipo más específico de int. YPrintln()
llamaString()
entre bastidores.fuente
Devolviendo un canal
Este es un verdadero idioma que es bastante importante: cómo introducir datos en un canal y cerrarlo después. Con esto puede hacer iteradores simples (ya que el rango aceptará un canal) o filtros.
fuente
defer close(outch);
tal como la primera declaración de la goroutine?Tiempo de espera para las lecturas del canal:
Robado de Davies Liu .
fuente
Dado que el rango busca automáticamente un canal cerrado, podemos acortarlo a esto:
fuente
Hay una configuración de sistema de creación que puede usar en $ GOROOT / src
Configure su archivo MAKE con
Luego, puede usar las herramientas de prueba automatizadas ejecutando make test, o agregar el paquete y los objetos compartidos de cgo a su $ GOROOT con make install.
fuente
Otra cosa interesante en Go es eso
godoc
. Puede ejecutarlo como servidor web en su computadora usandodonde 8080 es el número de puerto, y el sitio web completo en golang.org está disponible en
localhost:8080
.fuente
Esta es una implementación de una pila. Ilustra la adición de métodos a un tipo.
Quería convertir la pila en parte de ella en un segmento y usar las propiedades del segmento, pero aunque logré que funcionara sin el
type
, no pude ver la sintaxis para definir un segmento contype
.fuente
fmt.Printf(...); os.Exit();
, puede usarpanic(...)
.Llamar al código c desde ir
Es posible acceder al nivel inferior de go utilizando el tiempo de ejecución de c.
Las funciones C tienen la forma
(tenga en cuenta que el separador de puntos es un carácter Unicode) donde los argumentos pueden ser tipos básicos, cortes, cadenas, etc. Para devolver un valor, llame
(puede devolver más de un valor)
Por ejemplo, para crear una función
en C usas
Tenga en cuenta que aún debe declarar la función en un archivo go y que tendrá que ocuparse de la memoria usted mismo. No estoy seguro de si es posible llamar a bibliotecas externas usando esto, puede ser mejor usar cgo.
Mire $ GOROOT / src / pkg / runtime para ver ejemplos usados en el tiempo de ejecución.
Consulte también esta respuesta para vincular el código c ++ con go.
fuente
Aquí hay un ejemplo de go usando el paquete sqlite3.
http://github.com/bikal/gosqlite-example
fuente
¿Viste esta charla ? Muestra muchas cosas interesantes que puedes hacer (fin de la charla)
fuente
Una pila basada en la otra respuesta, pero usando un segmento que se agrega para no tener límite de tamaño.
fuente
fuente
for { /* infinite loop */ }
es suficiente.forever
palabra clave. Incluso Qt tiene una macro para eso.for ever
(después de declarar la variable) es algo lindo que puedes hacer en Go si quieres. Parece inglés (módulo en blanco).#define ever (;;)
Hay muchos programas pequeños en
test
en el directorio principal. Ejemplos:peano.go
imprime factoriales.hilbert.go
tiene algo de multiplicación de matrices.iota.go
tiene ejemplos de lo extraño de iota.fuente