Home>

This article mainly introduces go, starting from the perspective of comparative analysis of languages.The reason why I chose to compare with python and erlang is because as a high-level language,They have a large similarity in language characteristics,But the main reason is that I am familiar with these.

Many language features of go draw on its three ancestors:c, pascal, and csp. Go's syntax, data types, and control flow are inherited from c. Go's package and object-oriented ideas are derived from pascal branch.Coroutine concurrency model based on pipeline communication,Borrowed from the csp branch.

Go/python/erlang language features comparison

As the article "Programming Languages ​​and Paradigms" states,No matter how many languages ​​emerge,The design of all languages ​​is inseparable from 2 fundamentals:control flow and data types.To improve language description,Languages ​​generally provide control abstraction and data abstraction.The comparison of language features in this section also starts from these 4 dimensions.See the following figure for details (click to enlarge).

In the figure we can see thatCompared to Python's 40 features, go has only 31, and it can be said that go is quite restrained in language design.For example, it has no implicit numeric conversion,No constructors and destructors,No operator overloading,No default parameters,And no inheritance,Without generics,No exception,No macros, no function modifications,No thread-local storage.

But go is also very distinctive,For example, it has coroutines, automatic garbage collection, a package management system, first-class citizen functions, stack space management, and so on.

go as a statically typed language,It guarantees that go is more efficient than python and erlang in terms of operating efficiency, memory usage, and type safety.

The data types of go are also more abundant,In addition to supporting complex data structures such as tables and dictionaries,Pointer and interface types are also supported,This is not available in python or erlang.Especially the interface type is particularly powerful,It provides the means to manage the type system.The pointer type provides a means of managing memory,This gives go strong support for getting into the underlying software development.

Go made a lot of reflections and choices on object-oriented feature support.It has no features such as classes, virtual functions, inheritance, and generics.The core of object-oriented programming in Go is composition and function. The combination is very similar to the combination of the struct structure of the C language.Methods are similar to java's interfaces, but are more decoupled from objects using methods.Reduced intrusion into the subject.Erlang does not support the object-oriented programming paradigm,in comparison,Python has the most comprehensive support for the object-oriented paradigm.

On the support of functional programming,erlang as a functional language,The most comprehensive support.But basic functional language features,Such as lambda, higher-order functions, curry, etc., all three languages ​​are supported.

Control flow feature support,All three languages ​​are similar.Erlang supports tail recursive optimization,This brings convenience to functional programming.Go supports deep recursive calls by dynamically expanding the coroutine stack.Python is often popped on deep recursive calls.

Both go and erlang's concurrency models are derived from csp, but erlang is a concurrent implementation based on actors and messaging.Go is a concurrent implementation based on goroutine and channels.Both erlang actors and go goroutines meet the characteristics of coroutines:they are implemented and scheduled by programming languages,Switching is done in user mode,The creation and destruction overhead is small.As for Python, its multi-threaded switching and scheduling is implemented based on the operating system.And because gil's big pit exists,There is no real parallelism.

And from the author's concurrent programming experience,Erlang's functional programming syntax style and the obscure use of callbacks provided by its otp behavior framework,For most programmers,For programmers from c/c++ and java,There are certain barriers to entry and challenges.Go, which is called "c in the Internet age," has a class c syntax and control flow.And object-oriented programming paradigms,The programming experience is much better.

Go/python/erlang language syntax comparison

All language features need a formal representation,A detailed comparison of the syntax of the three languages ​​of go, python and erlang is as followsthe second part,the third part). Here (link) there is a detailed syntax comparison between go and c,This is one reason why I did not compare go vs. c.

As Rob Pike, one of the designers of the Go language, said, "The complexity of software is multiplicative." This is fully reflected in the control of the number of language keywords.The keywords of go are minimal,There are only 25, while Erlang has 27 and Python has 31. Fundamentally guarantees the simplicity of the Go language.

The Go language divides data types into four categories:basic types, composite types, reference types, and interface types.The basic types include:integer, floating-point, complex, string, and Boolean.Compound data types are arrays and structures.Reference types include pointers, slices, dictionaries, functions, and channels. Other data types,Such as atom, binary, tuple, set, record, go does not support it.

Go has improved many syntax features of the C language.As Rob Pike mentioned in "less is exponentially more", Go's "starting point:C language, solve some obvious flaws, remove impurities, add some missing features."For example, the case subroutine of switch/case breaks out by default, and the case statement supports numerical ranges and conditional judgment statements;All types are initialized to 0 by default and there are no uninitialized variables;Put the type behind the declaration syntax (link) of the variable to make complex declarations clearer and easier to understand;No header file,The compilation of files is organized in packages,Improve packaging capabilities;Replace void * with an empty interface (interface {}), improve type system capabilities, and more.

Go makes a clear distinction between functions, methods, and interfaces.Similar to erlang, go functions as first citizens.Functions allow us to pack a sequence of statements into a unit,It can then be called multiple times from elsewhere in the program.The difference between a function and a method is the presence or absence of a receiver.It does not mean that there is no return value as in other languages.The interface type specifically describes a collection of methods,The empty interface interfac {} means that it can receive any type.The use of these 2 interfaces,Using the object-oriented programming paradigm,Can be analogized with subtype polymorphism (adtype polymorphism) and ad hoc polymorphism (non-parametric polymorphism).

As can be seen from the example in the figure,Go's goroutine is a function,And a stack allocated for it on the heap.So its system overhead is very small,Tens of thousands of goroutines can be easily created, and they are not scheduled for execution by the operating system.A goroutine can only use channels to send requests to the specified goroutine to query for update variables.This is the mantra of go "Don't use shared data to communicate,Use communication to share data. "Channels support capacity limits and range iterators.

Go/python/erlang lexical comparison

A detailed comparison of the lexical symbols in the three languages ​​of go, python and erlang is as follows (click to see the full picture). Go has the most lexical symbols in 3 languages.There are 41, and there are many cases of symbol multiplexing.Relatively speaking,Python is the least, only 31.

The Go language has adopted a very strong attitude towards lexical and code formatting.Go has only one way to control visibility:capitalized identifiers are derived from the package in which they are defined,Lowercase letters do not.This way of restricting members in a package is also applicable to struct or a type method.

In file naming,Go also has certain regulatory requirements,If the source file with the _test.go suffix is ​​a test file,They are part of the go test;The functions prefixed with test in the test file are test functions.Used to test whether some logical behavior of the program is correct;Functions prefixed with the benchmark function name are benchmark functions.They are used to measure the performance of some functions.

In addition to keywords,In addition, go has about 30 more predefined names,For example, int and true correspond to built-in constants, types, and functions.

tdd go programming example

This section uses the tdd method to reconstruct the Fibonacci algorithm 4 times.To briefly show the features, syntax, and usage of go,Such as go's unit testing technology,Concurrency programming, anonymous functions, closures, etc.

First, take a look at the unit test file that tdd finally formed:

package main
import (
  "testing"
)
func testfib (t * testing.t) {
  var testdatas=[] struct {
    n int
    want int64
  } {
    {0, 0},    {1, 1},    {twenty one},    {3, 2},    {4, 3},    {16, 987},    {32, 2178309},    {45, 1134903170},  }
  for _, test:= range testdatas {
    n:= test.n
    want:= test.want
    got:= fib (n)
    if got!=want {
      t.errorf ("fib (%d) =%d, want%d \ n", n, got, want)
    }
  }
}

Implementation scheme based on recursion:

func fib1 (n int) int64 {
  if n == 0 || n == 1 {
    return int64 (n)
  }
  return fib1 (n-1) + fib1 (n-2)
}

Test Results:

[email protected] $time go test
pass
ok _/home/crbsp/alex/go/fib 9.705s
real 0m10.045s
user 0m9.968s
sys 0m0.068s

Concurrency scheme based on goroutine:

func fib2 (n int) int64 {
  var got int64
  var channel=make (chan int64, 2)
  if n == 0 || n == 1 {
    return int64 (n)
  }
  runtime.gomaxprocs (2)
  go func () {channel <-fib1 (n-2)} ()
  go func () {channel <-fib1 (n-1)} ()
  got =<-channel
  got + =<-channel
  return got
}

Test Results:

pass

ok _/home/crbsp/alex/go/fib 6.118s

real 0m6.674s

user 0m10.268s

sys 0m0.148s

Implementation scheme based on iteration:

func fib3 (n int) int64 {
  var a, b int64
  a, b=0, 1
  for i:= 0;i<n;i ++ {
    a, b=b, a + b
  }
  return a
}

Test Results:

pass

ok _/home/crbsp/alex/go/fib 0.002s

real 0m0.547s

user 0m0.328s

sys 0m0.172s

Closure-based implementation:

func fibwrapper4 () func () int64 {
  var a, b int64
  a, b=0, 1
  return func () int64 {
    a, b=b, a + b
    return a
  }
}
func fib4 (n int) int64 {
  var got int64
  got=0
  f:= fibwrapper4 ()
  for i:= 0;i<n;i ++ {
    got=f ()
  }
  return got
}

Test Results:

paok _/home/crbsp/alex/go/fib 0.002s

real 0m0.411s

user 0m0.260s

sys 0m0.140s

to sum up

  • Previous Implementing a simple popup effect using Vue components
  • Next Talking about Angular4 dirty value detection (performance optimization)