Go (programming language)

from Wikipedia, the free encyclopedia
Go
Go-Logo 2018-04-26
Basic data
Paradigms : concurrent , imperative , structured , modular , object-oriented
Publishing year: 2009; first stable version 2012
Designer: Rob Pike , Ken Thompson , Robert Griesemer
Developer: Robert Griesemer , Rob Pike , Ken Thompson and others a.
Current  version 1.15   (August 11, 2020)
Typing : strong , static
Important implementations : Gc, gccgo
Influenced by: C , Newsqueak , Alef , Limbo , Oberon
Operating system : Linux , macOS , FreeBSD , Windows , Experimental: DragonFly BSD , Plan 9 , Solaris
License : BSD license
golang.org

Go is a compilable programming language that supports concurrency and has automatic garbage collection . Go was developed by employees of Google Inc. The designs come from Robert Griesemer , Rob Pike and Ken Thompson .

overview

Go was developed out of dissatisfaction with the existing languages ​​for software development such as C ++ or Java in the context of today's computer systems, especially with regard to scalable network services , cluster and cloud computing . Compared to C ++, Go has far fewer keywords. One of the problems Go wants to solve is compiler inefficiency in C and C ++. Important goals in the development were, among other things, the support of concurrency with native language elements and the facilitation of software development with large development teams and large code bases. Go has its own garbage collector , allows the use of pointers , but dispenses with pointer arithmetic . Go is a compiled language with a focus on high translation speed.

Go is syntactically based on the programming language C with some influence from the Wirth language family ( Pascal , Modula and especially Oberon ). The support for concurrency was modeled on the Communicating Sequential Processes (CSP) introduced by Tony Hoare and is in the tradition of the programming languages Newsqueak , Alef and Limbo .

Features and language resources

Go offers closures and reflection, as well as type safety and automatic garbage collection. Go supports object orientation through interfaces and mixins . In classes and inheritance of classes is deliberately avoided. It is also possible to modularize the source code using packages as with Java .

Concurrency is Communicating Sequential Processes realized that Goroutinen be called and via channels (Channels) can communicate. There are no generic types , but later integration cannot be ruled out.

Unicode is supported in the form of UTF-8 , both for strings and for variable identifiers in the source text (but only Unicode letters and numbers), Δt = t1 - t2so it is possible.

syntax

The syntax of Go is essentially based on the syntax of the C programming language , but differs from it in some places. For example, statements do not need to be terminated with a semicolon. In declarations, data types are written after the identifier instead of in front of it in order to simplify the declaration of function types . Code blocks are separated with curly braces. In addition to the simple equal sign as an assignment operator, there is also an operator :=that combines declaration with type inference and assignment. The language includes 25 keywords fewer keywords as ANSI C .

Comments are marked with slashes as in C or C ++; /*to */denotes a comment area , which can also contain several lines, introduces //a comment area up to the end of the line.

Each source file belongs to exactly one package, which is packagespecified at the beginning of the file with the instruction.

The key word for functions is functhat the function mainin the “main” package is the starting point of the Go program.

Each variable has a defined type.

Simple examples

package main

import "fmt"

func main() {
    fmt.Println("Hallo Welt")
}

The above source text outputs the string on the output medium Hallo Welt.

Another example calculates the circle number Pi approximately using the Leibniz series . Parallel Go routines and a channel are used for the calculation:

package main

import (
    "fmt"
    "math"
)

func main() {
    fmt.Println(calcpi(5000))
}

// calcpi startet n Goroutinen, um eine
// Näherung von Pi zu berechnen.
func calcpi(n int) float64 {
    ch := make(chan float64, n)
    for k := 0; k < n; k++ {
        // alle n Werte parallel berechnen
        go calcsubterm(ch, float64(k))
    }
    // das Ergebnis mit Null initialisieren
    f := float64(0.0)
    for k := 0; k < n; k++ {
        // alle n Werte addieren
        f += <- ch
    }
    return f
}

func calcsubterm(ch chan <- float64, k float64) {
    ch <- 4 * math.Pow(-1, k) / (2*k + 1)
}

The individual summands of the mathematical series are executed in parallel and each write their results in the channel ch. At the same time, the values ​​from the channel are added to an overall result. The sequence of digits appears on the output device 3.141392653591793. The deviation from the actual circle number from the fourth decimal place is mainly due to the slow convergence of the Leibniz series .

Type conversion

In contrast to the C language, types must always be converted. For example, it is not possible to store a value of the type integer in a variable of the type float without first converting the value. In the following example, a variable of the type Integer is declared and the value of this variable is assigned to another variable of the type Float. Note that a distinction is made between “int” and “uint”. "Unsigned Integer" "uint8" cover a range from (0 ... 255) while "int8" cover a range from (−128 ... 127). This procedure of strict typing is very useful because programming errors that are difficult to find can be identified more easily.

var int_variable1 int = 100
var float_variable1 float64 = float64(int_variable1)
var int_variable2 uint = uint(float_variable1)

If a value is assigned directly in the declaration, the explicit naming of the type is optional. The compiler determines this based on the value or the specified type converter functions. At the package level, each instruction must begin with a keyword, which is why the following short form can only be used within functions:

int_variable1 := 100
float_variable1 := float64(int_variable1)
int_variable2 := uint(float_variable1)

pointer

In contrast to many high-level languages ​​such as Java, the GO programming language works with pointers. A pointer ( English pointer) whose value is the address of a storage area . Certain tasks cannot be programmed without a pointer. This includes the transfer of values ​​to functions (call by reference). In the following example, a variable of the type “Integer” with the name “number” and the value 100 is initialized. Then the memory address, i.e. the address in the computer memory, is output. The address of the variable “number” is called up with “& number”. The pointer syntax is very reminiscent of the C language.

var nummer int = 100
fmt.Printf("Die Adresse der Variable: %x\n", &nummer)

In the next example, a variable of the type “Integer” with the name “number” and the value 100 is initialized. Then a pointer variable of the type integer pointer is declared. The type of a pointer variable is declared by a leading asterisk (*) in front of the variable type. “Int” becomes “* int”. Then the memory address of the variable “number” is declared as the value of the pointer variable “integer_pointer”. The address of the memory which was occupied by the variable “number” is then output. Finally, the value that is in the memory address is output. The value of a memory location that is declared in the pointer variable “integer_pointer” can be determined with “* integer_pointer”.

var nummer int = 100
var integer_pointer *int
integer_pointer = &nummer
fmt.Printf("Adresse gespeichert in der integer_pointer Variable: %x\n", integer_pointer) /* gibt eine Speicheradresse aus z.B. 10888000 */
fmt.Printf("Wert der Speicheradresse gespeichert in integer_pointer : %d\n", *integer_pointer) /* Gibt den Wert an welcher in der Speicheradresse steht */

A pointer address without a stored pointer is called a "nil pointer". You can simply query whether a pointer address has a memory address as its content or not.

if(integer_pointer != nil)    /* Wenn zutreffend Zeiger Variable speichert einen Zeiger auf einen Speicherbereich */
if(integer_pointer == nil)    /* Wenn zutreffend Zeiger Variable speichert keinen Zeiger auf einen Speicherbereich */

The last example shows the usage when calling a function. First, two variables of the "Integer" type are declared. The content of these two variables should be swapped.

var nummer1 int = 10
var nummer2 int = 50
// Anzeige vor dem Tausch
fmt.Printf("Wert der Variable nummer1: %x\n", nummer1)
fmt.Printf("Wert der Variable nummer2: %x\n", nummer2)
// Aufruf der Funktion tauschen
tauschen(&nummer1,&nummer2)
// Anzeige des Tausches
fmt.Printf("Wert der Variable nummer1: %x\n", nummer1)
fmt.Printf("Wert der Variable nummer2: %x\n", nummer2)
//Funktion tauschen
func tauschen(nummer1_pointer *int, nummer2_pointer *int) {
    var zwischenspeicher int
    zwischenspeicher = *nummer1_pointer
    *nummer1_pointer = *nummer2_pointer
    *nummer2_pointer = zwischenspeicher
}

You can roughly summarize that "&" determines the memory address of a variable, while "*" determines the stored value of a memory address.

Object orientation

Go supports object-oriented programming, but it is not class-based . Data types can have methods in Go . Polymorphism is interfaces ( interfaces reached), are linked via the method calls at run time to the specific implementation ( Dynamic binding ). A data type does not have to be explicitly declared that it fulfills a specific interface. Instead, this relationship is determined implicitly at compile time in order to achieve loose coupling .

Instead of inheritance and type hierarchies, Go uses composition. For this purpose, Go supports a form of mix-ins, which in Go is called embedding : a data structure can embed any number of other data types so that it contains their methods and data fields.

Example of types, interfaces and mixins:

package main

import "fmt"

// Definieren zweier Typen
type User struct {
	Name string
}

type Admin struct {
	User // Admin bettet zudem den Typ 'User' ein
	Email string
}

// Ein Interface mit der Methode 'Notify()'
type Notifier interface {
	Notify()
}

// User und Admin implementieren das Interface 'Notifier'
// Eine vorherige Deklaration zur Implementierung ist nicht notwendig
func (u User) Notify() {
	fmt.Printf("User : Sending User Email To %s\n",
		u.Name)
}

func (a Admin) Notify() {
	fmt.Printf("Admin: Sending Admin Email To %s. His address is \"%s\".\n",
		a.Name, // Verwenden des eingebetteten Feldes 'Name' vom User
		a.Email)
}

func main() {
	// Einen User und einen Admin erstellen
	user := User{
		Name: "john smith",
	}
	admin := Admin{
		User: user,
		Email: "john@email.com",
	}

	// Die implementierte Notify-Methode aufrufen
	// Mittels dynamischer Bindung wird die Methode am richtigen Typ aufgerufen
	user.Notify()
	admin.Notify()
}

Concurrency

To support concurrent programming in Go, the concept of channels (channels) used, which provides a relatively highly abstract possibility of synchronous or asynchronous communication between Go routines. A channel is a memory area that is secured by semaphores and provides a queue (buffered / asynchronous channel) or just an interface (unbuffered / synchronous channel). Only data of a fixed type can be transmitted over a channel. However, there is no limit to the type, channels for channels are also conceivable.

A channel is created through the call make(chan typ)(synchronous) or make(chan typ, größe)(asynchronous, if size > 0). Then go routines can write to the channel, read from it and close it.

In the case of synchronous channels, read access blocks until another Go routine writes to the channel, or write access blocks until another routine reads. With asynchronous channels, this behavior only occurs if the channel to be read is empty or the channel to be written is full. In Go, there is no limit to the number of Go routines that read and write a channel. Despite the sophisticated synchronization mechanisms, a deadlock can occur when using channels, which causes the Go runtime environment to terminate the program. A go routine can use the selectconstruct to listen on several channels at the same time, or try to write in several channels, whereby the casestatement is executed which no longer blocks at first or, in the case of several options, a pseudo-random choice is made.

Data are also kanal <- Wertwritten to and variable = <-kanalread in a channel , whereby the variable assignment can be omitted when reading. Listening to a channel can also be forautomated with the construct, whereby the loop is exited as soon as the channel is closed.

Example:

package main

import "fmt"

func zehnMal(kanal chan string) {
    // Argument empfangen
    sag := <-kanal

    // Zehnmal zurückschreiben
    for i := 0; i < 10; i++ {
        kanal <- sag
    }

    // Kanal schließen
    close(kanal)
}

func main() {
    // synchronen Kanal öffnen
    kanal := make(chan string) // oder make(chan string, 0)

    // Starten der parallelen Go-Routine „zehnMal()“
    go zehnMal(kanal)

    // Senden eines Strings
    kanal <- "Hallo"

    // Empfangen der Strings, bis der Channel geschlossen wird
    for s := range kanal {
        fmt.Println(s)
    }

    fmt.Println("Fertig!")
}

In the example, main()the Go routine zehnMal()is called, which returns a received string ten times over the same channel and then closes it. Due to the synchronous channel, the two go routines wait for each other so that main()the forloop does not enter the loop until zehnMal()the string has been received. If the channel were not synchronous, a deadlock could occur if main () immediately reads the written variable again (and removes it from the buffer) and zehnMal()waits in vain for its argument. It is also important that zehnMal()the channel closes after the strings have been written, main()otherwise the loop cannot exit.

Implementations

There are at least two compilers for Go that can run on Linux , macOS , Windows and FreeBSD and that fully implement the Go-1 specification:

Gc
is the official Go compiler and was initially written in C by Ken Thompson, based on the Plan 9 toolchain and used Yacc / Bison for parsing . With version 1.5 this compiler was translated from C to Go and is therefore self-hosting . The compiler originally consisted of several executable commands that had different names depending on the target architecture: 8g for x86 , 6g for x86_64 , 5g for ARM . With version 1.5 these were combined into a single executable command ( go tool compile ), and the target architecture can be selected via the environment variable GOARCH .
Gccgo
by Ian Taylor is a Go frontend for the GNU Compiler Collection (GCC). The front end, written in C ++ , uses a recursive descent for parsing . The following backend steps are those of standard GCC processing. This procedure increases the compilation time compared to the Gc compiler, but the code produced is more efficient. The GNU Compiler Collection (GCC) fully supports Go 1 with version 4.7.1, the GNU Debugger (gdb) supports Go from version 7.5.

Both compilers implement parallel mark-and-sweep garbage collection .

The official compiler is accompanied by the command line tool go , which serves as a facade for various tools, such as B. installing packages from source code repositories on the Internet such as GitHub or Google Code (go get) , automatically formatting source code (go fmt) , running tests (go test) , generating documentation from source text comments (go doc) or compiling the project (go build) , so that no makefiles are necessary if a recommended directory structure is adhered to.

history

The design phase began on September 21, 2007, initially as a 20 percent project on the initiative of Robert Griesemer, Rob Pike and Ken Thompson. Soon after, more developers joined and Go became a full-time project. On October 30, 2009, Go was presented by Rob Pike in a Google TechTalk and announced the release as free software , which then took place on November 10, as announced. Since then, numerous contributions have been made by developers from the Go community outside of Google. Version 1 was released on March 28, 2012. Since then, the language specification and standard library have been considered stable and should remain downward compatible at the source code level within the 1.x series. Go 1.1 was released on May 14, 2013, which mainly contains performance improvements to the implementation. Versions Go 1.2 to Go 1.10 were released six months later.

From April 24 to 26, 2014, the first Go conference, GopherCon, took place in Denver , which has been taking place annually since then.

mascot

Go's gopher mascot

The Go mascot is a pocket rat (English gopher ). It was designed by Renée French, who also designed Glenda, the Plan 9 bunny. The logo and the mascot are under the Creative Commons Attribution 3.0 license.

literature

Web links

Individual evidence