2010.07_Ready, Set, Go-Google Invents a New Programming Language.pdf

(673 KB) Pobierz
Ready, Set, Go! - Google invents a new programming language - Linux Magazine
Google invents a new programming language
Ready, Set, Go!
Google is good for more than just search results. The search engine giant is now in the blocks and set to
launch a new programming language. Will this advance be successful?
By Marcus Nutzinger and Rainer Poisel
Sergey Kandakov, 123RF
At a 2007 meeting of Google developers, former Bell Labs veterans Rob Pike and Ken Thompson wondered
whether the art of the programmer had gotten to be too much about waiting. According to Pike, "Things were
taking too long. Too long to code; too long to compile ..." [1].
One problem, according to Pike, was that programming languages haven't changed much during the past
several years, but the requirements and expectations have continued to evolve.
Contemporary programs must accommodate client-server networking, massive compute clusters, and
multicore processors, and at the same time, developers must pay additional attention to security and stability.
Also, the systems for testing and controlling data types continue to become increasingly complicated.
The Google developers wanted a language that was as efficient as statically typed languages like C and as
easy to use as dynamic languages like Python. They also wanted good support for concurrency, and they
wanted to include a garbage collection system (as in Java or C#) for automatically cleaning up memory.
After several months of planning and several more months of coding, the Google team unveiled a new
"expressive, concurrent, and garbage-collected" programming language called Go [2]. The tools you need for
getting started with the Go language are available right now through the project website.
If you feel like testing a new programming language, you can try your luck with this experimental language
designed for the next generation of programming.
Environment Design
The source code for the Go programming tools is available from a repository on the project homepage [3].
After compiling the various Go components (see the "Installation" box), the next task is to build the libraries.
Ready, Set, Go!
1
564684044.007.png 564684044.008.png
This step should give you an indication of how well Google's new language actually performs because the
libraries are written in Go. You should notice that an entire library builds in just a couple of seconds.
Currently, two compilers are available - namely, the gc compiler and gccgo . The gccgo tool interacts with
the GNU C compiler, but it is not as highly developed as the gc tools, whose naming scheme derives from
Plan 9 [5]. The number designates the platform, in which 5 stands for ARM, 6 for 64-bit x86 systems, and 8
for 32-bit x86 systems. The letter designates the tool itself (see Table 1).
Figure 1 shows the build and linking process, and Listing 1 contains the obligatory "Hello World" program
(but in German here). Line 3 contains an import , which you will be familiar with from Python and Java. Go
requires that programs have a main() function as the entry point, just like C or C++. The Println()
function in the fmt library finally outputs the text. The developers deliberately used a naming scheme with an
uppercase first letter for functions. One important feature of Go is that variables and functions automatically
have global visibility if their names begin with a capital letter.
Figure 1: The commands for compiling and linking a Go program are similar to the initially unfamiliar Plan 9
notation.
Listing 1: hello.go
01 package main
02
03 import "fmt"
04
05 func main () {
06 fmt.Println("Hallo, Welt!")
07 }
Installation
If a firewall blocks your Internet access during the installation, you will need a workaround. Disable the
http and net subsystem tests in the Makefile so that the results of their execution are not preconditions for
the success of the overall installation [4]. To do so, add http and net entries to the value of the NOTEST
variable in the $GOROOT/src/pkg/Makefile file.
Ready, Set, Go!
2
564684044.009.png 564684044.010.png 564684044.001.png
Easy Entry
In Go, the semicolon doesn't terminate an instruction; instead, it is a separator, as in a list. If the program is
only one instruction, a semicolon is not needed. Go inherits from various languages (e.g., C, C++, Python),
but the syntax differs at various points. Google offers both a general introduction to the language syntax [6]
and an overview of more advanced topics [7].
In this article, we describe a small programming project that demonstrates Go's client-server capabilities and
lays the foundation for a minimal chat program. The server process listens for TCP connections on a specific
port; when the connection is established, clients send messages to the server using the defined formats and
then terminate.
Server Tasks
The server, as implemented in Listing 2, starts importing packets in line 3 and later uses them as library calls.
Line 15 emphasizes that the developers have inverted the order of the keywords in the variable declaration.
According to the project document, this improves clarity of syntax and saves typing. Go also automatically
identifies types if declaration and initialization occur in one step, making additional type definitions
redundant. The code starts by defining two constants of the standard type int and a global variable of type
int * . The listenPort variable is thus a pointer. This functionality comes from C/C++.
Listing 2: server.go
001 package main
002
003 import (
004 "bytes";
005 "encoding/binary";
006 "flag";
007 "fmt";
008 "net";
009 "os";
010 "os/signal";
011 "syscall";
012 "./build/msg/msg"
013 )
014
015 const (
016 defPort = 7777;
017 bufSize = 1024
018 )
019
020 var listenPort *int = flag.Int("p", defPort, "port to listen for connections")
021
022 // wait for incoming tcp connections
023 func acceptor(listener *net.TCPListener, quit chan bool) {
024 var buf [bufSize]byte
025
026 for {
027 conn, e := listener.AcceptTCP()
028 if e != nil {
029 fmt.Fprintf(os.Stderr, "Error: %v\n", e)
030 continue
031 }
032
033 num, e := conn.Read(&buf)
034 if num < 0 {
035 fmt.Fprintf(os.Stderr, "Error: %v\n", e)
036 conn.Close()
037 continue
038 }
039
040 go handleClient(conn, buf[0:num])
Ready, Set, Go!
3
564684044.002.png
041 }
042 }
043
044 // handle a single client connection
045 func handleClient(conn *net.TCPConn, bytebuf []byte) {
046 message := new(msg.Message)
047 buf := bytes.NewBuffer(bytebuf)
048
049 binary.Read(buf, binary.LittleEndian, &message.SenderLen)
050 s := make([]byte, message.SenderLen)
051 buf.Read(s)
052 message.SetSender(string(s))
053 binary.Read(buf, binary.LittleEndian, &message.DataLen)
054 d := make([]byte, message.DataLen)
055 buf.Read(d)
056 message.SetData(string(d))
057
058 fmt.Printf("%s connected\n > %s\n\n", message.GetSender(),
059 message.GetData())
060
061 conn.Close()
062 }
063
064 // read from signal.Incoming channel and
065 // return SIGINT is received
066 func signalHandler(quit chan bool) {
067 for {
068 select {
069 case sig := <-signal.Incoming:
070 fmt.Printf("Received signal %d\n", sig)
071 if sig.(signal.UnixSignal) != syscall.SIGINT {
072 continue
073 }
074 quit<- true
075 return
076 }
077 }
078 }
079
080 func main() {
081 flag.Parse()
082 address := fmt.Sprintf("%s:%d", "127.0.0.1", *listenPort)
083 quit := make(chan bool)
084
085 socket, e := net.ResolveTCPAddr(address)
086 if e != nil {
087 fmt.Fprintf(os.Stderr, "Error: %v\n", e)
088 os.Exit(1)
089 }
090 listener, e := net.ListenTCP("tcp4", socket)
091 if e != nil {
092 fmt.Fprintf(os.Stderr, "Error: %v\n", e)
093 os.Exit(1)
094 }
095
096 go signalHandler(quit)
097
098 fmt.Printf("Listening on %s:%d\n\n", socket.IP.String(), socket.Port)
099 go acceptor(listener, quit)
100
101 for {
102 select {
103 case <-quit:
104 fmt.Printf("Shutting down\n")
105 listener.Close()
106 return
107 }
108 }
Ready, Set, Go!
4
564684044.003.png
109 }
Useful Modules
The main() function in line 80 parses the command-line parameters. To do this, it relies on the functions
provided by the flag package.
One of Go's special features is the system of channels used for communication between Goroutines, the
counterpart to threads (see Figure 2). Line 83 creates a new channel, which the individual threads can use to
exchange bool -type data. The box titled "Make vs. New" describes the make keyword, which is used to
create new instances, and how it differs from new .
Figure 2: Goroutines communicate via a channel. At time t1, A is reading from the channel and thus blocks until
time t2, when B writes data to the channel.
The := syntax, which Go borrows from Pascal, offers a shorter variant of variable declaration with
simultaneous initialization. The program uses this idiom in lines 85 and 90 to create a socket and a TCP
handler with the help of the net library.
Functions can return multiple values in Go; this explains the list of variables that you see on the left side of
the assignment in line 85.
The go keyword starts a Goroutine. The main program creates a parallel thread in line 96 with the
signalHandler() function while continuing to run normally itself. The program thus runs two
Goroutines.
One of them, starting in line 66, is responsible for signal handling; the other starts in 23 and listens on the
TCP port. An infinite loop at the end of main() uses select to wait on the channel for an incoming
message of quit .
Make vs. New
Go includes two keywords for a similar purpose: programmers can use both make and new to allocate
memory. The new keyword - which is popular in object-oriented languages like C++ and Java - allocates
memory for a new object and returns a pointer to the created instance of the requested object type as a return
value. The new parameters define the type for which Go is to allocate memory space.
In contrast, developers use make to create slices, maps, or channels. This keyword doesn't support other
types. The return value here is not a pointer to a new instance of the data type passed in, but the value itself.
Additionally, the resulting object is initialized internally and thus is available for use immediately. If new is
used for these three types, Go returns a nil pointer because the underlying data structures are not initialized
[7].
The make keyword also supports additional arguments. For slices, this is the length and the capacity of the
field in question. The former defines the current length of the slice when it is created, the latter is the length
of the underlying field (i.e., the length to which the slice can grow).
Ready, Set, Go!
5
564684044.004.png 564684044.005.png 564684044.006.png
Zgłoś jeśli naruszono regulamin