40 votes

Que pouvez-vous faire en 30 lignes de Go ? Pouvez-vous créer un programme utile et complet qui démontre ses fonctionnalités ?

Donc, le grand buzz de ces derniers jours est Allez sur le nouveau langage de Google. En supposant que vous êtes tous des geeks obsessionnels du langage de programmation comme moi, vous l'avez tous téléchargé, construit, et exécuté votre programme "Hello, 世界" (n'est-ce pas agréable d'utiliser un langage écrit par les inventeurs de l'UTF-8 ?). Vous avez tous lu le tutoriel , Go efficace et d'autres documents.

Maintenant, qu'allez-vous en faire ?

J'aimerais voir des démos qui montrent la puissance de Go. Que pouvez-vous faire dans un programme bref ? Montrez vos meilleurs exemples de code. Alors que la véritable mesure d'un langage ne peut pas vraiment être prise jusqu'à ce que vous ayez écrit et maintenu une grande base de code avec une équipe de nombreux programmeurs au cours d'un projet avec des exigences changeantes, voir ce que vous pouvez faire dans une quantité limitée de code aide à démontrer la puissance expressive d'un langage. J'aimerais voir des programmes courts et complets qui utilisent réellement les nouvelles fonctionnalités uniques de Go ; pas seulement des extraits ou des "Hello, World".

Alors, postez un code sympa que vous avez écrit avec Go. Tirez parti de ses caractéristiques uniques, comme ses goroutines et ses canaux pour la concurrence, ou son système de types basé sur des interfaces. Pouvez-vous écrire un serveur de chat primitif, ou un robot IRC cool ? Implémenter un ensemble Mandelbrot parallèle qui s'étend à de nombreux cœurs ? Écrire un interpréteur pour un petit langage ? Et pouvez-vous faire tout cela en 30 lignes ?

J'ai choisi 30 arbitrairement car c'est à peu près tout ce que l'on peut faire tenir dans un bloc de code Stack Overflow sans qu'il déborde et qu'il y ait une barre de défilement ; cela devrait être suffisant pour faire quelque chose d'intéressant sans faire trop de golf, mais assez court pour garder l'attention de tous pour une démonstration rapide. Par exemple, avec un peu de reformatage, l'exemple serveur web devrait pouvoir s'adapter (sans compter les données).

Montrez-nous votre code Go !

11voto

Dustin Points 35205

C'est un proxy web que j'ai écrit pour fournir un accès non authentifié à un service web qui nécessite une authentification HTTP de base. J'en avais besoin pour un truc interne (et je l'utilise toujours) :

package main

import (
    "flag"
    "log"
    "net/http"
    "net/url"
)

var target = flag.String("target", "http://www.google.com/", "Where to go.")
var addr = flag.String("listen", ":12345", "Address/port on which to listen.")
var auth = flag.String("auth", "", "Authorization header to add (optional).")

func main() {
    flag.Parse()

    targetUrl, uerr := url.Parse(*target)
    if uerr != nil {
        log.Fatalf("Error parsing target ``%s'': ", target, uerr.String())
    }

    proxy := http.ReverseProxy{Director: func(req *http.Request) {
        req.URL.Scheme = targetUrl.Scheme
        req.URL.Host = targetUrl.Host
        req.Host = targetUrl.Host
        if *auth != "" {
            req.Header.Set("Authorization", *auth)
        }
    }}

    log.Fatal(http.ListenAndServe(*addr, &proxy))
}

8voto

Cela crée un PNG (sur stdout) d'un cadran d'horloge indiquant l'heure actuelle. Elle est à peine gérée pour tenir sur trente lignes, donc le code n'est pas aussi propre qu'il devrait l'être.

package main
import ("image"; "image/png"; "math"; "bufio"; "os"; "time")
const clock_size = 200;
const radius = clock_size / 3;
var colour image.RGBAColor;
func circle (clock *image.RGBA) {
    for angle := float64(0); angle < 360; angle++ {
        radian_angle := math.Pi * 2 * angle / 360;
        x := radius * math.Sin (radian_angle) + clock_size/2;
        y := radius * math.Cos (radian_angle) + clock_size/2;
        clock.Set (int (x), int (y), colour);}}
func hand (clock *image.RGBA, angle float64, length float64) {
    radian_angle := math.Pi * 2 * angle;
    x_inc := math.Sin (radian_angle);
    y_inc := -math.Cos (radian_angle);
    for i := float64(0); i < length; i++ {
        x := i * x_inc + clock_size/2;
        y := i * y_inc + clock_size/2;
        clock.Set (int (x), int (y), colour);}}
func main () {
    clock := image.NewRGBA (clock_size, clock_size);
    colour.A = 255;
    circle (clock);
    time := time.LocalTime ();
    hand (clock, (float64(time.Hour) + float64(time.Minute)/60)/12, radius*0.6); // hour hand
    hand (clock, (float64(time.Minute) + float64(time.Second)/60)/60, radius*0.8); // minute hand
    out := bufio.NewWriter(os.Stdout);
    defer out.Flush();
    png.Encode(out, clock);
}

Exécutez-le comme

8.out > clock.png

Vous avez remarqué tous ces moulages en float64 ? Je n'ai JAMAIS vu un langage aussi strict que Go concernant les types.


Il s'agit du même code corrigé avec go fix (et quelques ajustements manuels) et ensuite formaté automatiquement à l'aide du logiciel go fmt . Certains retours à la ligne ont été insérés manuellement.

package main

import (
    "bufio"
    "image"
    "image/color"
    "image/png"
    "math"
    "os"
    "time"
)

const clock_size = 200
const radius = clock_size / 3

var colour color.RGBA

func circle(clock *image.RGBA) {
    for angle := float64(0); angle < 360; angle++ {
        radian_angle := math.Pi * 2 * angle / 360
        x := radius*math.Sin(radian_angle) + clock_size/2
        y := radius*math.Cos(radian_angle) + clock_size/2
        clock.Set(int(x), int(y), colour)
    }
}

func hand(clock *image.RGBA, angle float64, length float64) {
    radian_angle := math.Pi * 2 * angle
    x_inc := math.Sin(radian_angle)
    y_inc := -math.Cos(radian_angle)
    for i := float64(0); i < length; i++ {
        x := i*x_inc + clock_size/2
        y := i*y_inc + clock_size/2
        clock.Set(int(x), int(y), colour)
    }
}

func main() {
    clock := image.NewRGBA(image.Rect(0, 0, clock_size, clock_size))
    colour.A = 255
    circle(clock)
    time := time.Now()
    hand(clock, (float64(time.Hour())+float64(time.Minute())/60)/12, radius*0.6)   // hour hand
    hand(clock, (float64(time.Minute())+float64(time.Second())/60)/60, radius*0.8) // minute hand
    out := bufio.NewWriter(os.Stdout)
    defer out.Flush()
    png.Encode(out, clock)
}

5voto

jgeewax Points 3026

J'aime beaucoup les chaînes de go et le select Voici donc quelque chose qui montre à quel point il est facile d'exprimer le concept "aller chercher autant de choses que possible dans un certain temps".

Elle génère autant de nombres aléatoires que possible en 300 millisecondes et renvoie le plus grand nombre généré dans ce laps de temps.

package main

import (
  "fmt"
  "math/rand"
  "time"
)

func main() {
  timeout := time.After(300 * time.Millisecond)
  numbers := make(chan int) // This channel will be used 
  var numberCount int = 0
  var maxNumber int = 0

  // Start putting random numbers on the numbers channel
  go func() {
    for {
      numbers <- rand.Int()
    }
  }()

  for {
    select {
    case <- timeout:
      fmt.Printf("%v numbers generated. Max number found: %v.\n", numberCount, maxNumber)
      return

    case number := <- numbers:
      numberCount++
      if number > maxNumber {
        maxNumber = number
      }
    }
  }
}

4voto

Brian Campbell Points 101107

OK, je vais commencer. Voici mon premier programme Go. C'est un serveur de chat très primitif, et il tient en 30 lignes de 80 caractères si je le compresse un peu ; formaté avec gofmt Il est de 60 lignes. Il écoute sur un port codé en dur (4242), ne fait pratiquement aucune gestion d'erreur et ne gère pas la déconnexion du client, si ce n'est qu'il arrête d'essayer de lire depuis un client s'il obtient une erreur.

package main
import ("net";"container/vector";"bufio";"strings")
type client struct { conn net.Conn; send chan string; receive chan string }
func main() {
    if listener, err := net.Listen("tcp", "0.0.0.0:4242"); err == nil {
        master := make(chan string, 100);
        clients := vector.New(0);
        go runServer(master, clients);
        for {
            if conn, err := listener.Accept(); err == nil {
                c := client{ conn, master, make(chan string, 100) };
                clients.Push(c);
                go runClient(c);
            } else { break } } } }
func runServer(master chan string, clients *vector.Vector) {
    for { 
        message := <-master;
        clients.Do(func (c interface{}) { c.(client).receive <- message }); } }
func runClient(c client) {
    input := make(chan string, 10);
    go readLines(c, input);
    for {
        select {
        case inMessage := <-input: c.send <- inMessage;
        case outMessage := <-c.receive: c.conn.Write(strings.Bytes(outMessage));
        } } }
func readLines(c client, input chan string) {
    reader := bufio.NewReader(c.conn);
    for { if line, err := reader.ReadString('\n'); err == nil 
            { input <- line; } else { break } } }

Construisez et exécutez avec :

$ 6g server.go
$ 6l -o server server.6
$ ./server

Et puis dans quelques autres terminaux, se connecter avec

$ nc localhost 4242

0voto

brianoh Points 410

J'ai copié ceci de quelque part. Assez simple, mais qui montre quelques fonctionnalités.

package main
import ("fmt"; "os" ;"bufio")
func main() {
        if len(os.Args) < 2 {
                fmt.Printf("usage: catfile \n")
        } else if pFile, err := os.Open(os.Args[1], os.O_RDONLY, 0); err != nil {
                fmt.Printf("error opening file : %s\n", err)
        } else {
            defer pFile.Close()
        displayFile(pFile)
    }
}

func displayFile(pFile *os.File) {
        oReader := bufio.NewReader(pFile);
        for {
                if sLine, err := oReader.ReadString('\n'); err == nil {
            fmt.Printf("%s", sLine)
        } else {
            if err != os.EOF {fmt.Printf("error reading file : %s\n", err)}
                    break
        } 
        }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X