Getting started with Go

Getting started with Go

This tutorial mainly explains the object-oriented foundation of Go language and its concurrent programming. It is suitable for those who have a basic programming language such as Java.

This tutorial mainly explains the object-oriented foundation of Go language and its concurrent programming. It is suitable for those who have a basic programming language such as Java. The Go language was created by Google to solve problems similar to Google-scale.

Go has the following characteristics:

  • Static typing,
  • Part of the C language family,
  • Garbage collection,
  • Statically compiled,
  • Object-Oriented,
  • Concurrency friendly.

First, download and install Go . Once the installation is successful, you need to set GOPATH.

$ echo 'export GOPATH = $ HOME' >> $ HOME / .profile
$ source $ HOME / .profile
$ go env | grep GOPATH
GOPATH = "/ Users / peter"

Create a main.go file as follows:

package main

func main () {
 println ("hello!")
}

Go is a statically compiled typed language, so it needs to be compiled and run:

$ go build
$ ./hello
hello!
Create a web server

Below we use Go to create a web server with the following code:

package main

import "net / http"

func main () {

    http.HandleFunc ("/", hello)

    http.ListenAndServe (": 8080", nil)

}

 

func hello (w http.ResponseWriter, r * http.Request) {

    w.Write ([] byte ("hello!"))

}

If you are familiar with languages such as Java, the first two lines should be familiar and import the net / http package.

http.HandleFunc ("/", hello) is to create a http route, the URL is the root path, and then listen on port 8080. Every time a new request is made for the HTTP server root path, the server will generate a new coroutine goroutine to execute the hello function. The hello function simply uses http.ResponseWriter to write the response to the client. The response is "hello!" We did a byte conversion.

After compiling and running, access via browser or curl:

$ curl http: // localhost: 8080
hello!

Coroutine goroutine is a lightweight threading concept in Go's concurrent programming. It is not a real operating system thread. Instead, it uses an operating system thread in segments and implements cooperative scheduling through a scheduler. Is a kind of green thread, micro thread.

Let's take a look at the object-oriented and concurrency features of Go.

Object-oriented

Go is object-oriented, but does not have the following concepts:

  • class
  • extends inheritance
  • implements

Let's first look at Go's use of type to express a type. The type keyword defines a new type, declared as a struct. Each field in a struct can have a name (such as Name and Main below), or another struct:

type weatherData struct {

    Name string `json:" name "`
		
}

All types are created equally. The way to define a type is as follows, unlike Java in Class:

type Door struct {

    opened bool

}

 

func (d * Door) Open () {

    d.opened = true

}

func (d * Door) Close () {

    d.opened = false

}

This is the Door structure type has two methods open() and close(). Similar to Java setter/getter.

It can also be created for the initial type:

type Door bool

func (d * Door) Open () {

    * d = true

}

func (d * Door) Close () {

    * d = false

}

The interface is an important feature of the Go language. It is more important than coroutines. It is similar to the Java interface, as follows:

In Java:

interface Switch {

    void open ();

    void close ();

}

In Go:

type OpenCloser interface {

    Open ()

    Close ()

}

Unlike Java's interface, Go's interface does not need to explicitly declare inheritance. It is implicitly matched by the compiler according to the method signature. For example, to implement the interface Switch in Java, you need to write code:

public class SwitchImpl implements Switch {// Implement specific content}

In Go, the interface is implicitly implemented by the compiler. In the previous type Door bool, we have defined Door. This type has two methods Open and Close, and here is an interface t ype OpenCloser interface declares that the two methods are also Open and Close, the compiler thinks Door implements OpenCloser .

The relationship between Go's interface and implementation is to implicitly satisfy implicit satisfaction. If a type defines all methods of an interface, it is considered that the type satisfies the interface. Implicit satisfaction == No explicit "implements" Code. It is a structural typing of duck typing, the benefits are:

  • Less dependent
  • Does not cause complicated type inheritance levels
  • Natural compositional properties non-inherited
    We can see from Go's interface that Go is more focused on composition than inheritance.
Composition is more important than inheritance

In SOLID object-oriented design principles, we have already talked about how composition is better than inheritance. Here we can prove it again with a case: Suppose there is a Java thread class:

class Runner {

        private String name;

        public Runner (String name) {

            this.name = name;

        }

        public String getName () {

            return this.name;

        }

        public void run (Task task) {

            task.run ();

        }

        public void runAll (Task [] tasks) {

            for (Task task: tasks) {

                run (task);

            }

        }

    }

RunCounter inherits Runner :

class RunCounter extends Runner {

        private int count;

        public RunCounter (String message) {

            super (message);

            this.count = 0;

        }

        @Override public void run (Task task) {

            count ++;

            super.run (task);

        }

        @Override public void runAll (Task [] tasks) {

            count + = tasks.length;

            super.runAll (tasks);

        }

        public int getCount () {

            return count;

        }

    }

Called by:

RunCounter runner = new RunCounter ("my runner");

Task tasks = {new Task ("one"), new Task ("two"), new Task ("three")}; runner.runAll (tasks);

System.out.printf ("% s ran% d tasks \ n", runner.getName (), runner.getCount ());

The result is:

running one
running two
running three
my runner ran 6 tasks

There are actually 6 thread tasks running. And we want to specify three. This is because inheritance leads to weak encapsulation, not strong encapsulation, and tight coupling, which leads to incredible bugs:

The solution is to combine Composition:

class RunCounter {

        private Runner runner;

        private int count;

        public RunCounter (String message) {

            this.runner = new Runner (message);

            this.count = 0;

        }

        public void run (Task task) {

            count ++;

            runner.run (task);

        }

        public void runAll (Task [] tasks) {

            count + = tasks.length;

            runner.runAll (tasks);

        }

 

        public int getCount () {

            return count;

        }

        public String getName () {

            return runner.getName ();

        }

    }

Although the problem is solved, the disadvantage is that the Runner method needs to be explicitly defined in RunCounter:

public String getName () {return runner.getName ();}

Causes a lot of duplication and introduces bugs.

There is no inheritance in Go, which is naturally a composition. The direct implementation is as follows:

type Runner struct {name string}

func (r * Runner) Name () string {return r.name}

func (r * Runner) Run (t Task) {

    t.Run ()

}

func (r * Runner) RunAll (ts [] Task) {

    for _, t: = range ts {

        r.Run (t)

    }

}

The implementation of RunCounter is as follows:

type RunCounter struct {

    runner Runner

    count int

}

func NewRunCounter (name string) * RunCounter {

    return & RunCounter {runner: Runner {name}}

}

func (r * RunCounter) Run (t Task) {

    r.count ++

    r.runner.Run (t)

}

func (r * RunCounter) RunAll (ts [] Task) {

    r.count + = len (ts)

    r.runner.RunAll (ts)

}

func (r * RunCounter) Count () int {return r.count}
unc (r * RunCounter) Name () string {return r.runner.Name ()}

Although there is also a Name () method here, we can remove it. First, let's take a look at Go's Struct embedding, which is struct embedding. The methods and fields of the embedded type are defined in the embedder type implementation. Although similar to inheritance, the embedded person does not know that it is embedded. For example a type Person:

type Person struct {Name string}

func (p Person) Introduce () {fmt.Println ("Hi, I'm", p.Name)}

We can define Employee to embed Person:

type Employee struct {

    Person

    EmployeeID int

}

In this way, all Person field methods are applicable to Employee:

var e Employee
e.Name = "Peter"
e.EmployeeID = 1234

e.Introduce ()

Now we use struct embedding to optimize the previous RunCounter:

type RunCounter2 struct {

    Runner

    count int

}

func NewRunCounter2 (name string) * RunCounter2 {

    return & RunCounter2 {Runner {name}, 0}

}

func (r * RunCounter2) Run (t Task) {

    r.count ++

    r.Runner.Run (t)

}

func (r * RunCounter2) RunAll (ts [] Task) {

    r.count + = len (ts)

    r.Runner.RunAll (ts)

}

func (r * RunCounter2) Count () int {return r.count}
Is embedding like inheritance? But it's not, it's better, it's the composion. You cannot go into another type to change the way it works. Its scheduling method is explicitly explicit.

From a certain perspective, struct embedding is similar to dependency injection (DI) or inversion mode, replacing previous inheritance by combining + dependency injection.

Take a look at the Struct embedding of the interface:

If a T type is embedded in a field of type E, all methods of E will be defined in the T type. In this way, if E is an interface, T must implicitly satisfy E. That is, T must implement interface E.

We define the loopBack type, the net.Conn type is embedded in the type loopBack, and net.Conn is an interface:

type loopBack struct {

    net.Conn

    buf bytes.Buffer

}

Any method that calls net.Conn will fail because this field is an empty nil. Let's define its operation:

func (c * loopBack) Read (b [] byte) (int, error) {

    return c.buf.Read (b)

}

func (c * loopBack) Write (b [] byte) (int, error) {

    return c.buf.Write (b)

}

Then you can think of loopBack as an implementation of the interface net.Conn.

Concurrency

Concurrency is characterized by the need for Lock and Mutex. Locking and unlocking in Java is a complex process. The code is as follows:

try {

  mutex.acquire ();

  try {

    // do something

  } finally {

    mutex.release ();

  }

} catch (InterruptedException ie) {

  // ...

}

Another feature of concurrency is asynchronous. Various languages ​​have their own asynchronous mechanisms. Callback-based ones include:

  1. Ruby's EventMachine
  2. Python Twisted
  3. NodeJS

But it can't coexist well with parallel, rely on various library packages, code is difficult to debug, and easily fall into callback nesting hell.

Go's concurrency is based on two concepts:

  • Coroutine goroutine: is a kind of lightweight thread, it is not an operating system thread, but an operating system thread is used in stages, and cooperative scheduling is achieved through a scheduler. Is a kind of green thread, micro thread.
  • Channel: Unix-like Pipe, used for communication and synchronization between coroutines. Although coroutines are decoupled, they are coupled with Channel.

For example, the code for sleep and taalk is as follows:

func sleepAndTalk (t time.Duration, msg string) {

    time.Sleep (t)

    fmt.Printf ("% v", msg)

}

One message per second:

func main () {

    sleepAndTalk (0 * time.Second, "Hello")

    sleepAndTalk (1 * time.Second, "Gophers!")

    sleepAndTalk (2 * time.Second, "What's")

    sleepAndTalk (3 * time.Second, "up?")

}

What if we need to send messages at the same time instead of every second? Just add go:

func main () {

    go sleepAndTalk (0 * time.Second, "Hello")

    go sleepAndTalk (1 * time.Second, "Gophers!")

    go sleepAndTalk (2 * time.Second, "What's")

    go sleepAndTalk (3 * time.Second, "up?")

}

This is when main opens a main coroutine, and when it ends, the entire program ends.

Let's take a look at the communication through the Channel. In this case, sleepAndTalk does not print out the information, but sends the string to the channel.

func sleepAndTalk (secs time.Duration, msg string, c chan string) {

    time.Sleep (secs * time.Second)

    c <-msg

}

We create a channel and pass it to sleepAndTalk, and then we can wait for the data value to be sent to the channel:

func main () {

    c: = make (chan string)

    go sleepAndTalk (0, "Hello", c)

    go sleepAndTalk (1, "Gophers!", c)

    go sleepAndTalk (2, "What's", c)

    go sleepAndTalk (3, "up?", c)

    for i: = 0; i <4; i ++ {

        fmt.Printf ("% v", <-c)

    }

}

Let's see how to implement it in the web environment: First we receive the nextId from the Channel:

var nextID = make (chan int)

func handler (w http.ResponseWriter, q * http.Request) {

    fmt.Fprintf (w, "<h1> You got% v <h1>", <-nextID)

}

Need a coroutine to send nextID to the channel.

func main () {

    http.HandleFunc ("/ next", handler)

    go func () {

        for i: = 0;; i ++ {

            nextID <-i

        }

    } ()

    http.ListenAndServe ("localhost: 8080", nil)

}

Visit localhost: 8080 / next through your browser to get the nextID value.

If there are multiple channels, the code is as follows:

var battle = make (chan string)

 

func handler (w http.ResponseWriter, q * http.Request) {

    select {

    case battle <-q.FormValue ("usr"):

        fmt.Fprintf (w, "You won!")

    case won: = <-battle:

        fmt.Fprintf (w, "You lost,% v is better than you", won)

    }

}

The URL parameters accessed in this way are different:
Go-localhost: 8080 / fight? Usr = go
Java-localhost: 8080 / fight? Usr = java

Multiple Channels can be connected in series to form a stream:

gophers chain:

func f (left, right chan int) {

    left <-1 + <-right

}

func main () {

    start: = time.Now ()

    const n = 1000

    leftmost: = make (chan int)

    right: = leftmost

    left: = leftmost

    for i: = 0; i <n; i ++ {

        right = make (chan int)

        go f (left, right)

        left = right

    }

    go func (c chan int) {c <-0} (right)

    fmt.Println (<-leftmost, time.Since (start))

}

Go (Golang) to Python

Go (Golang) to Python

Using Go, CGO, and Cython to build Extension Modules. Go is a useful language to extend Python. This talk explains to you how to implement extension modules in Go. The talk shows how to use CGO to make Go code available as a C library and then to use Cython to make this library available as a Python extension module.

Python and Go are a great combination. Like Python, Go is easy to learn, powerful to use and has many useful libraries. Go and Python work great together: Go has better performance and parallelism, while Python is more expressive. Wouldn't it be nice if you could combine the benefits of Go and Python in one program? This talk shows you how.

Why you may want to attend
Extension modules written in C/C++ or other languages are one of the major strength Python. Go is a useful language to extend Python. This talk explains to you how to implement extension modules in Go.

Content of the Talk
The talk shows how to use CGO to make Go code available as a C library and then to use Cython to make this library available as a Python extension module.

We start by building a wrapper for simple Go code that adds some numbers and returns the results. This program is our end-to-end example to demonstrate the steps necessary to create a Python extension module in Go.
Next, we move to more complex use cases. We look at different ways to share complex data and to use Python callbacks from Go.
Then, we see how to how to handle Go's Garbage Collector when exposing with Go Objects.
Finally, the talk goes into the advantages and disadvantages of Go as an extension language for Python. We also look at some of the alternative ways to make Go code available in Python.

Recommended Prerequisites
To get the most out of the talk, you should know about the difference between native Python modules and extension modules written in other languages. Some background on concepts like garbage collection, stack and heap, and dynamic/shared libraries are beneficial. Knowledge of the Python C API is not required.
You do not need to know how to write Go code to follow the talk - the talk explains all the required Go.

Go Programming and Why should you learn Go Language?

Go Programming and Why should you learn Go Language?

Go provides you high performance like C/C++, super efficient concurrency handling like Java and fun to code like Python/Perl. Go with Golang and why go is the best programming language in the world and Why should you learn Go Language?

Why Learn Go Lang - Should I go with 'Go' | Brief Intro to Go Language

Go with Golang and why go is the best programming language in the world.

We will talk about:

  1. Power of GoLang
  2. Is Go for everyone
  3. Who said Go is better than Nodejs
  4. Who are the creators of GoLang
  5. Why GoLang was created by Google
  6. Why Learn of GoLang
  7. Companies using GoLang
  8. What GoLang have and what not
  9. GoLang Garbage Collection
  10. GoLang Concurrency
  11. Recommended Books for Learning GoLang

Go Programming Tutorial - Real World Advice for Building Go Projects

Go Programming Tutorial - Real World Advice for Building Go Projects

Practical Go: Real World Advice For Writing Maintainable Go Programs. Go is a language designed for engineering teams. his workshop will provide best practice real world advice for teams building projects in Go covering five areas: Idiomatic code, Package and API design, Error handling, Concurrency, Testing

Go is a language designed for engineering teams. Its central themes are simplicity, readability, and maintainability.

This workshop will provide best practice real world advice for teams building projects in Go covering five areas:

  • Idiomatic code
  • Package and API design
  • Error handling
  • Concurrency
  • Testing