** Abstract: ** This paper studies and discusses the Go language from the grammar, type system, coding style, language tools, coding tools and use cases.

After the release of Go language, many companies, especially cloud manufacturers, began to use Go language to reconstruct the product infrastructure, and many enterprises directly used Go language for development. Recently, the popular Docker was developed using Go language. In this article, we will discuss and learn the technical characteristics of Go language. Let’s start with an example:

Package main import (" FMT ""time") // The function to run in goroutine. The done channel will be used to notify that the work is complete. func worker(done chan bool) { fmt.Print("working..." ) time.sleep (time.second) fmt.println ("done") // The notification is complete. Done := make(chan bool, 1) go worker(done) // Wait for done to become true <-done}Copy the code

Here is an example of using Goroutine and channels in the Go language. Among them:

The fix go keyword is used to start a Goroutine

Fixed done < -true, pass value to channel

(3) <-done, and the channel value is read

I. [Overview]

Go is a statically typed, compile-to-run programming language designed by RobertGriesemer, RobPike, and KenThompson at Google.

Go is syntactically similar to C, but it has advantages that C does not, such as memory safety, garbage collection, structured typing, and CSP-style concurrency.

Its domain name is golang.org, so it is often referred to as “Golang”, but the correct name is Go.

Ii. [Design idea of GO]

Go’s design is influenced by the C language, but is simpler and more secure. The language includes the following features:

  • Use the syntax and environment patterns that are common in dynamic languages:
  • Optional concise variable declarations and initializations by type reasoning (if x := 0 is used instead of int x= 0; Or var x = 0) .
  • Fast compilation.
  • Remote package management (Go Get) and online package documentation.
  • A unique approach to a particular problem:
  • Built-in concurrency primitives: goroutines, channels, and SELECT statements.
  • Use interface system instead of virtual inheritance, use type embedding instead of non-virtual inheritance.
  • By default, a tool chain generates statically linked native binaries with no external dependencies.
  • You want to keep the language specification simple enough for programmers to learn.

2.1 Concise syntax

Go’s syntax includes features in C that keep code concise and readable.

2.1.1 Variable declaration

A joint declaration/initialization operator was introduced that allows programmers to write I := 3 or S :=”Hello, world!” Without specifying the type of variable to use.

This is similar to int I = 3 in C; Const char *s = “Hello, world!” ; A sharp contrast.

2.1.2 Semicolon implied

The semicolon is still a terminating statement, but is implied at the end of the line.

2.1.3 Return multiple values

In Go, a function method can return multiple values, and returning a result and an error-ERR pair is a common way to alert the caller to an error.

2.1.4 Range expression

Go’s range expressions allow neat iteration over arrays, dynamic arrays, strings, dictionaries, and channels, and in C, there are three types of loops to do this.

2.2 Type System

2.2.1 Built-in types

Go has a number of built-in types, including numeric types (byte, INT64, FLOAT32, and so on), Booleans, and strings.

Strings are immutable.

Built-in operators and keywords (not functions) provide concatenation, comparison, and UTF-8 encoding/decoding.

2.2.2 Structure Type

Record types can be defined using the struct keyword.

2.2.3 Array Types

For each type T and each non-negative integer constant n, there is an array type, represented as [n]T. Therefore, arrays of different lengths have different types.

Dynamic arrays can be used as “Slice”, as in []T for some type T. These arrays have a length and a capacity that specifies when new memory needs to be allocated to expand the array. Several slices can share their underlying memory.

2.2.4 pointer

All types can define Pointers. Pointers of type T can be defined as T. Address extraction and implicit access use the ampersand operators, as in C, or implicitly through method calls or attribute access.

With the exception of the special broadening.Pointer type in the library, normal Pointers have no Pointer operations.

2.2.5 Mapping Types

For a combined pair of types K, V, type map[K]V is the type of the hash table that maps the key of type K to the value of type V.

2.2.6 Channel Type

Chan T is a channel that allows values of type T to be sent between concurrent Go processes.

2.2.7 Explicit Type

In addition to support for interfaces, Go’s type system is explicit: the type keyword can be used to define a new named type that is different from other named types that have the same layout (the same members are arranged in the same order for structures). Some conversions between types (such as conversions between various integer types) are predefined, and adding a new type can define additional conversions, but conversions between named types must always be invoked explicitly. For example, the type keyword can be used to define the type of IPv4 address, based on 32-bit unsigned integers:

type ipv4addr uint32
Copy the code

Based on this type definition, ipv4Addr (x) interprets the value x as an IP address. It would be a type error to simply assign x to a variable of type IPV4Addr.

Constant expressions can be typed or “untyped”; If the values they represent pass compile-time checks, they are assigned a type when assigned to a typed variable.

2.2.8 Function Types

Function types are represented by the func keyword; They take zero or more arguments and return zero or more values of the type to be declared.

Parameters and return values determine the type of a function; For example, func(string, int32)(int, error) is a function type that takes a string and a 32-bit signed integer and returns a signed integer and an error (built-in interface type) value.

2.2.9 Method extensions on types

Any named type has a collection of methods associated with it. The IP address example above can be extended with a way to check if its value is a known standard:

// ZeroBroadcast reports whether addr is 255.255.255.255.255. func (addr ipv4addr) ZeroBroadcast() bool { return addr == 0xFFFFFFFF }Copy the code

The above function adds a method to ipv4Addr that does not exist on the uint32.

2.2.10 Interface System

Go provides two functions to replace class inheritance.

The first is the embedding method, which can be viewed as an automated form of composition or principal-agent.

The second type is the interface, which provides runtime polymorphism.

An interface is a type that provides a limited form of typed structure in Go’s type system.

An object of an interface type also has a corresponding definition of another type, just as C++ objects have the characteristics of both base and derived classes.

The Go interface is based on the protocol of the Smalltalk programming language.

The term canard fill is used to describe the Go interface.

Although the term canard padding is not precisely defined, it usually means that the type consistency of these objects is not statically checked.

Because the consistency of the Go interface is checked statically by the Go compiler, Go authors prefer to use the term structural typing.

The definition of the interface type lists the required methods by name and type. Any object of type T that has a function that matches the required method of interface type I is also an object of type I. The definition of type T does not require or recognize type I. For example, if Shape, Square, and Circle are defined as:

Import "math" type Shape interface {Area() float64} type Square struct {// Func (Sq Square) Area() float64 {return sq.side * sq.side} type Circle struct {// there is no "implementation" here "Radius float64} func (c Circle) Area() float64 {return math.pi * math.pow (c.adius, 2)}Copy the code

A square and a circle both imply a Shape and can be assigned to a Shape variable.

The Go interface system uses structure types. Interfaces can also be embedded into other interfaces, creating a composite interface that is satisfied by the addition of methods that implement the type of the embedded interface and the newly defined interface.

The Go library uses interfaces to provide generality in several places, including I/O systems based on Reader and Writer concepts.

In addition to invoking methods through interfaces, Go also allows interface values to be converted to other types through runtime type checking. This is type assertion and type switching.

The empty interface {} is an important base case because it can reference any type of option. It is similar to the Object class in Java or C# and can satisfy any type, including built-in types like int.

Code that uses an empty interface cannot simply call a method or built-in operator on the referenced object, but it can store interface{} values, try to convert them to a more useful type by type assertion or type switching, or check it with Go’s Reflect package.

Because interface{} can refer to any value, it is an efficient way to get rid of static typing restrictions, like void* in C, but with additional type checking at run time.

The interface value is implemented using a pointer to the data and a second pointer to the runtime type information. As with some other types in Go that use Pointers, the interface value is zero if uninitialized.

2.3 Package system

In Go’s package system, each package has a path (such as “compress/bzip2 “or “golang.org/x/net/html”) and a name (such as bzip2 or HTML).

References to definitions of other packages must always be prefixed with the names of other packages, and only the uppercase names of other packages can be accessed: IO.Reader is public, but bzip2.reader is not.

The go get command retrieves packages stored in a remote repository, encouraging developers to develop packages in the base path corresponding to the source repository

(such as example.com/user_name/p…

It has been proposed that Go introduce a proper package management solution similar to CPANfor Perl or Rust’s Cargo system or Node’s NPM system.

2.4 Concurrency: Goroutines and channels

2.4.1 [CSP Concurrent Mode]

3. In computer science, Communicating sequential processes (CSP) is a formal language for describing interaction patterns in concurrent systems. It is a member of the mathematical theory family of concurrency, known as Process algebras, Process Calculate, or process Calculate, is a mathematical theory based on the passage of messages.

CSP has been very influential in the design of Oceam programming languages, as well as Limbo, RaftLib, Go, Crystal and Clojure’s Core.async programming languages.

CSP was first described by TonyHoare in a 1978 paper, and has since evolved considerably.

CSP is being used in industry as a tool to specify and validate concurrent capabilities for a variety of different systems, such as T9000Transputer and secure e-commerce systems.

The theory of CSP itself is still the subject of active research, including efforts to increase its practical scope of application, such as increasing the scale of systems that can be analyzed.

The Go language has built-in mechanisms and library support for writing concurrent programs. Concurrency refers not only to parallelism of cpus, but also to asynchronous processing: having relatively slow operations, such as database or network reads, run alongside other work, which is common in event-based servers.

The main concurrency construct is Goroutine, which is a lightweight type of processing. A function call prefixed with the go keyword starts the function in a new Goroutine.

The language specification does not specify how to implement goroutine, but current implementations reuse the Goroutine of the Go process over a smaller set of operating system threads, similar to scheduling in Erlang.

While a standard library package has most of the classic concurrency control structures (mutex locks, etc.), the Go concurrency program is more channel-based, providing messaging between Goroutines.

The optional buffer stores messages in FIFO order, allowing the sent Goroutines to continue until the message is received.

Channels are typed, so channels of type CHAN T can only be used to transport messages of type T.

Special syntactic conventions operate on them; <-ch is an expression that causes the executing Goroutine to block on channel CH until a value comes in, and ch< -x is the sending value x (which may block until another Goroutine receives the value).

Built-in switch-like select statements can be used to implement non-blocking communication over multiple channels. Go has a memory model that describes how Goroutine must use channels or other operations to securely share data.

The presence of channels sets Go apart from actor-based concurrency languages like Erlang, where messages are directed to actors (as opposed to Goroutine). In Go, this can be done by maintaining a one-to-one correspondence between goroutine and channel. The Go language also allows multiple Goroutines to share a channel, or a goroutine to send and receive messages on multiple channels.

With these capabilities, one can build concurrent constructs like workerpools, pipelines (for example, decompression and parsing of files as they are downloaded), background calls with timeouts, and fan-out parallel calls to a set of services.

Channels also have uses that go beyond the usual concepts of interprocess communication, such as serving as a concurrency safe list of reclaim buffers, implementing coroutines, and implementing iterators.

The concurrency-related structural conventions for Go (channels and alternative channel inputs) are derived from TonyHoare’s communication sequential process model.

Unlike previous concurrent programming languages such as Occam or Limbo, on which Go co-designer RobPike worked, Go does not offer any built-in concepts of secure or verifiable concurrency.

While the communication processing model described above is recommended in Go, it is not unique: all goroutines in a program share a single address space. This means that mutable objects and Pointers can be shared between Goroutines.

2.5 Comfort of parallel programming

One study compared the size (in lines of code) and speed of programs written by a seasoned programmer unfamiliar with Go, and the modifications made to those programs by a Go expert (from the Google development team), and did the same for Chapel, Cilk, and IntelTBB.

It was found that non-experts tend to write disintegration-solution algorithms with one Go statement per recursion, while experts write distributed work synchronization programs with one Go statement per processor. Go specialists’ procedures are usually faster, but also longer.

2.6 Conditional competition security issues

Goroutine has no restrictions on how shared data can be accessed, making conditional races a possible problem.

Specifically, unless the program is explicitly synchronized via channels or otherwise, multiple Goroutines sharing reading and writing to a memory region can be problematic.

In addition, Go’s internal data structures, such as interface values, dynamic array headers, hash tables, and strings, are not immune to conditional races, so in multithreaded programs, there are type and memory safety implications if shared instances of these types are modified without synchronization.

2.7 Binary Generation

The linker in the GC toolchain creates statically linked binaries by default, so all Go binaries contain what is needed to run Go.

2.8 Abandoned language features

Go intentionally omits some features common in other languages, including inheritance, general-purpose programming, assertions, pointer operations, implicit type conversions, untagged unions, and tag unions.

2.9 Go style features

Go writers put a lot of effort into the style of the Go program:

  • The GofMT tool automatically regulates code indentation, spacing, and other surface level details.
  • The tools and libraries distributed with Go recommend some standard methods, such as API documentation (GODoc), testing (Go Test), build (Go Build), package management (Go Get), and so on.
  • Some of Go’s rules differ from those of other languages, such as disallowing circular dependencies, unused variables or imports, and implicit type conversions.
  • The omission of certain features (for example, some shortcuts to function programming, such as Map and Java-style try/ Finally blocks) programming style explicit, specific, and simple.
  • The Go team published a collection of Go syntax usage from day one, and later collected code reviews, lectures, and official blog posts to promote the Go style and coding philosophy.

Iii. [Go Tools]

Major Go releases include tools for building, testing, and analyzing code.

 Go build, which only uses information from the source file to build the GO binaries, not separate makefiles.

 gotest, for unit testing and microbenchmarks

 go FMT, for formatting code

 go get, used to retrieve and install remote packages.

 go Vet, a static analyzer that looks for potential errors in code.

 go Run, a shortcut to build and execute code

 godoc, for displaying documents or over HTTP

 gorename, used to rename variables, functions, and so on in a type-safe manner.

 go generate, a standard method of calling code generators.

It also includes analysis and debugging support, runtime diagnostics (for example, tracking garbage collection pauses), and conditional race testers.

An ecosystem of third-party tools enhances standard publishing systems such as:

Gocode, which automates code in many text editors,

Goimports (provided by Go team members), which automatically adds/removes package imports as needed, and ErrCheck, which detects error codes that might have been inadvertently ignored.

Iv. [Editing Environment]

Popular Go code tools:

 GoLand: JetBrains IDE.

 VisualStudio Code

 LiteIDE: A “simple, open source, cross-platform GoIDE”

 Vim: Users can install plug-ins:

 vim – go

V. [Application Case]

Some notable open source applications written with Go include:

 Caddy, an open source HTTP/2web server with automatic HTTPS capabilities.

 CockroachDB, an open source, liveable, highly consistent, extensible SQL database.

 Docker, a set of tools for deploying Linux containers.

 Ethereum, go-Ethereum implementation of virtual machine blockchain.

 Hugo, a static website generator

 InfluxDB, an open source database dedicated to handling time series data for high availability and high performance requirements.

 InterPlanetaryFile System, a content-addressable, point-to-point hypermedia protocol.

 Juju, a service coordination tool from Canonical, the packaging company behind UbuntuLinux.

 Kubernetes Container management system

 LND, bitcoin lightning network implementation.

 Mattermost, a team chat system

 NATSMessaging is an open source messaging system whose core design principles are performance, scalability, and ease of use.

 OpenShift, cloud computing service platform

 Snappy, a UbuntuTouch package manager developed by Canonical.

 Syncthing, an open source file synchronization client/server application.

 Terraform is an open source multi-cloud infrastructure configuration tool from HashiCorp.

Other well-known companies and websites that use Go include:

 Cacoo, rendering user dashboard pages and microservices using Go and gRPC.

 Chango, a programmatic advertising company, uses Go in its real-time bidding system.

 CloudFoundry, platform as a service

 Cloudflare, triangulation coding proxy Railgun, distributed DNS service, and tools for cryptography, logging, streaming, and accessing SPDY sites.

 Container Linux (formerly CoreOS), is a Linux-based operating system that uses Docker containers and RKT containers.

 Couchbase, query and indexing services within the Couchbase server.

 Dropbox, which migrates some key components from Python to Go.

 Google, many projects, especially the download server dl.google.com.

 Heroku,Doozer, a lock service company

 HyperledgerFabric, an open source enterprise level distributed ledger project.

 MongoDB, a tool for managing MongoDB instances.

 Two parts of Netflix’s server architecture.

 Nutanix for various microservices in its enterprise cloud operating system.

 Plug. DJ, an interactive online social music streaming site.

 SendGrid is a transactional email delivery and management service based in Boulder, Colorado.

 SoundCloud, “Dozens of Systems”

 Splice, the entire back end (API and parser) of its online music collaboration platform.

 ThoughtWorks, tools and applications for continuous and instant messaging (CoyIM).

 Twitch, their IRC based chat system (ported from Python).

 Uber, which handles a lot of queries based on geographic information.

Vi. [Code Examples]

6.1 Hello World

package main

import "fmt"

func main() {
    fmt.Println("Hello, world!")
}
Copy the code

6.2 concurrent

package main

import (
    "fmt"
    "time"
)

func readword(ch chan string) {
    fmt.Println("Type a word, then hit Enter.")
    var word string
    fmt.Scanf("%s", &word)
    ch <- word
}

func timeout(t chan bool) {
    time.Sleep(5 * time.Second)
    t <- false
}

func main() {
    t := make(chan bool)
    go timeout(t)

    ch := make(chan string)
    go readword(ch)

    select {
    case word := <-ch:
        fmt.Println("Received", word)
    case <-t:
        fmt.Println("Timeout.")
    }
}
Copy the code

6.3 Code Testing

No code is complete without tests, so we need to look at writing the test part of the code.

Code:

func ExtractUsername(email string) string {
    at := strings.Index(email, "@")
    return email[:at]
}
Copy the code

Test cases:

func TestExtractUsername(t *testing.T) { type args struct { email string } tests := []struct { name string args args want string }{ {"withoutDot", args{email: "[email protected]"}, "r"}, {"withDot", args{email: "[email protected]"}, "jonh.smith"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := ExtractUsername(tt.args.email); got ! = tt.want { t.Errorf("ExtractUsername() = %v, want %v", got, tt.want) } }) } }Copy the code

6.4 Creating back-end Services

Let me write an example to create a REST API back-end service:

Our service provides the following apis:

### GET http://localhost:10000/ ### GET http://localhost:10000/all ### GET http://localhost:10000/article/1 ### POST http://localhost:10000/article HTTP / 1.1 {" Id ":" 3 ", "Title" : "2" Hello, "desc" : "Article Description" and "content" : "Article Content"} # # # PUT http://localhost:10000/article HTTP / 1.1 {" Id ":" 2 ", "Title" : "Hello 2 Update", "desc" : "Article Description Update", "content": "Article Content Update" }Copy the code

Complete code:

package main import ( "encoding/json" "fmt" "io/ioutil" "log" "net/http" "github.com/gorilla/mux" ) type Article struct { Id string `json:"Id"` Title string `json:"Title"` Desc string `json:"desc"` Content string `json:"content"` } var MapArticles map[string]Article var Articles []Article func returnAllArticles(w http.ResponseWriter, r *http.Request) { fmt.Println("Endpoint Hit: returnAllArticles") json.NewEncoder(w).Encode(Articles) } func homePage(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Welcome to the HomePage!" ) fmt.Println("Endpoint Hit: homePage") } func createNewArticle(w http.ResponseWriter, r *http.Request) { reqBody, _ := ioutil.ReadAll(r.Body) var article Article json.Unmarshal(reqBody, &article) Articles = append(Articles, article) MapArticles[article.Id] = article json.NewEncoder(w).Encode(article) } func updateArticle(w http.ResponseWriter, r *http.Request) { reqBody, _ := ioutil.ReadAll(r.Body) var article Article json.Unmarshal(reqBody, &article) found := false for index, v := range Articles { if v.Id == article.Id { // Found! found = true Articles[index] = article } } if ! found { Articles = append(Articles, article) } MapArticles[article.Id] = article json.NewEncoder(w).Encode(article) } func returnSingleArticle(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) key := vars["id"] fmt.Fprintf(w, "Key: %s \n", key) json.NewEncoder(w).Encode(MapArticles[key]) } func handleRequests() { myRouter := mux.NewRouter().StrictSlash(true)  myRouter.HandleFunc("/", homePage) myRouter.HandleFunc("/all", returnAllArticles) myRouter.HandleFunc("/article", createNewArticle).Methods("POST") myRouter.HandleFunc("/article", updateArticle).Methods("PUT") myRouter.HandleFunc("/article/{id}", returnSingleArticle) log.Fatal(http.ListenAndServe(":10000", myRouter)) } func main() { fmt.Println("Rest API is ready ..." ) MapArticles = make(map[string]Article) Articles = []Article{ Article{Id: "1", Title: "Hello", Desc: "Article Description", Content: "Article Content"}, Article{Id: "2", Title: "Hello 2", Desc: "Article Description", Content: "Article Content"}, } for _, a := range Articles { MapArticles[a.Id] = a } handleRequests() }Copy the code

Call add, update API to return all data test results:

Seven, [mixed]

7.1 praise

MicheleSimionato is full of praise for Go:

The interface system is concise and deliberately omits inheritance.

Dave Eastels of EngineYard writes:

Go is very easy to learn. There are few basic language concepts, and the syntax is clean and clearly designed. Go is still experimental and rough in some places.

In 2009, Go was named programming Language of the Year by the TIOBE Programming Community Index.

By January 2010, Go had reached 13th place, surpassing established languages such as Pascal.

But by June 2015, it had fallen below 50th, below COBOL and Fortran.

But as of January 2017, it had shot up to 13th in the rankings, showing significant growth in its penetration and adoption.

Go was named TIOBE programming Language of the Year 2016.

BruceEckel has stated:

The complexity of C++ (with even more added in the new C++), and the resulting impact on productivity, no longer makes any sense to continue using C++. The enhancements C++ programmers made to overcome some of C’s problems don’t make sense now, and Go makes more sense now.

In 2011, r. hundt, a Google engineer, evaluated the Go language and its GC implementation against C++(GCC), Java and Scala.

Go provides interesting language features that make it concise and standardized. The compiler for this language is still immature, both in terms of performance and binary size.

This comment received a quick response from the Go development team.

IanLance Taylor improved the Go code because of Hundt’s comments;

RussCox then optimized the Go code, as well as the C++ code, and made the Go code run slightly faster than C++ and an order of magnitude faster than the code used in the review.

7.2 Naming Dispute

On November 10, 2009, Go! On the day of the programming language’s full release, Go! Programming language developer FrancisMcCabe (note the exclamation mark) requested that the name of Google’s language be changed to avoid confusion with the language he had spent 10 years developing.

McCabe’s concern that the ‘big Google’ will eventually run over him “resonated with more than 120 developers who commented on Google’s official question thread that they should change their name, with some even saying that the question went against Google’s motto:” Don’t be evil.”

On October 12, 2010, Google developer RussCox turned off the issue with a custom status of “unfortunate”, along with the following comment:

“There are a number of computing products and services named Go. In the 11 months since we launched, there has been very little confusion between the two languages.”

7.3 [Criticism]

What Go’s critics say:

  • Generic programming lacks parameter polymorphism, leading to code duplication or unsafe type conversions and disruptive randomness of the process.
  • Nil for Go, coupled with the absence of algebraic types, makes troubleshooting and basic problem avoidance difficult.
  • Go does not allow opening parentheses in the current line, forcing all Go programmers to use the same parenthesis style.

Viii. [Summary]

This paper studies and discusses Go language from the aspects of Go grammar, type system, coding style, language tools, coding tools and use cases, hoping to shed light on it and benefit colleagues who are interested in Go language.

Click to follow, the first time to learn about Huawei cloud fresh technology ~