github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/talks/2012/goforc.slide (about)

     1  Go for C programmers
     2  ACCU, Silicon Valley Chapter, Nov. 14, 2012
     3  
     4  # Go is a general-purpose programming language developed at Google.
     5  # Go's design is influenced by the C and Pascal lineage, but instead of providing
     6  # a conglomerate of features, Go takes a fresh look at the essential mechanisms
     7  # required for modern programming tasks. As a result, Go has evolved to a compact
     8  # language of surprising power. In this presentation we give a brief introduction
     9  # to Go, slightly slanted towards programmers with a C/C++ background, and then
    10  # talk about particularly interesting aspects of Go.
    11  
    12  Robert Griesemer
    13  Google Inc.
    14  gri@golang.org
    15  
    16  * Organization of this talk
    17  
    18  Part 1: Introduction to Go
    19  
    20  Break
    21  
    22  Part 2: Object-oriented and concurrent programming in Go
    23  
    24  # if time permits and desire exists
    25  
    26  * Motivation
    27  
    28  * Have
    29  
    30  Incomprehensible and unsafe code.
    31  
    32  Extremely slow builds.
    33  
    34  Missing concurrency support.
    35  
    36  Outdated tools.
    37  
    38  # C, C++ are > 30 years old!
    39  # Java is 15 years old, but not really a systems-programming language.
    40  # (No control over data layout, no unsigned, verbose, etc.)
    41  
    42  * Want
    43  
    44  Readable, safe, and efficient code.
    45  
    46  A build system that scales.
    47  
    48  Good concurrency support.
    49  
    50  Tools that can operate at Google-scale.
    51  
    52  # A language for the 21. century!
    53  
    54  * Meet Go
    55  
    56  Compact, yet expressive
    57  # spec is ~50 pages
    58  
    59  Statically typed and garbage collected
    60  
    61  Object- but not type-oriented
    62  
    63  Strong concurrency support
    64  
    65  Efficient implementation
    66  
    67  Rich standard library
    68  
    69  Fast compilers
    70  
    71  Scalable tools
    72  
    73  * Hello, World
    74  
    75  .play goforc/hello.go
    76  
    77  # the canonical first program
    78  # note: immediately readable for a C programmer even without prior knowledge of Go
    79  # (not the case with C++'s Hello, World, which is using the << operator)
    80  # which bring us to the first item on the "Want" list: readable code.
    81  
    82  * Syntax
    83  
    84  * Syntax
    85  
    86  _Syntax_is_not_important..._-_unless_you_are_a_programmer._
    87  Rob Pike.
    88  
    89  _The_readability_of_programs_is_immeasurably_more_important_than_their_writeability._
    90  Hints on Programming Language Design
    91  C. A. R. Hoare 1973
    92  
    93  # A lot of effort has gone into honing Go's syntax over more than 3 years.
    94  # The result is a clutter- and stutter-free, compact, yet readable notation.
    95  # Consider some alternatives...
    96  
    97  * Too verbose
    98  
    99  	scoped_ptr<logStats::LogStats>
   100  		logStats(logStats::LogStats::NewLogStats(FLAGS_logStats, logStats::LogStats::kFIFO));
   101  
   102  # real example from C++ (2012) (names changed)
   103  # logStats mentioned 9 times!
   104  # too much clutter
   105  
   106  * Too dense
   107  
   108  	(n: Int) => (2 to n) |> (r => r.foldLeft(r.toSet)((ps, x) =>
   109  		if (ps(x)) ps -- (x * x to n by x) else ps))
   110  
   111  # prime sieve in Scala
   112  # pretty and short but incomprehensible
   113  
   114  * Just right
   115  
   116  	t := time.Now()
   117  	switch {
   118  	case t.Hour() < 12:
   119  	    return "morning"
   120  	case t.Hour() < 18:
   121  	    return "afternoon"
   122  	default:
   123  	    return "evening"
   124  	}
   125  
   126  # looks like pseudo code
   127  # readable even w/o knowing Go
   128  # lots of things are going on but not relevant for understanding
   129  # no clutter
   130  
   131  * Reading Go code
   132  
   133  * Packages
   134  
   135  A Go program consists of _packages_.
   136  
   137  A _package_ consists of one or more _source_files_ (`.go` files).
   138  
   139  Each _source_file_ starts with a _package_clause_ followed by declarations.
   140  
   141  .code goforc/hello.go
   142  
   143  By convention, all files belonging to a single package are located in a single directory.
   144  
   145  * Declarations, "Pascal-style" (left to right)
   146  
   147  Pattern: keyword names [type] [initializer]
   148  
   149  .code goforc/decls.go /START/,/STOP/
   150  
   151  * Why?
   152  
   153  	p, q *Point
   154  
   155  	func adder(delta int) func(x int) int
   156  
   157  # try this in C
   158  # composition of types straight-forward
   159  
   160  * Constants
   161  
   162  In Go, constants are _mathematically_precise_.
   163  
   164  There is no need for qualifiers (`-42LL`, `7UL`, etc.)
   165  
   166  .code goforc/consts.go /START1/,/STOP1/
   167  
   168  Only when used, constants are truncated to size:
   169  
   170  .play goforc/consts.go /START2/,/STOP2/
   171  
   172  Huge win in readability and ease of use.
   173  
   174  * Types
   175  
   176  Familiar:
   177  - Basic types, arrays, structs, pointers, functions.
   178  
   179  But:
   180  - `string` is a basic type.
   181  - No automatic conversion of basic types in expressions.
   182  - No pointer arithmetic; pointers and arrays are different.
   183  - A function type represents a function; context and all.
   184  
   185  New:
   186  - _Slices_ instead of array pointers + separate length: `[]int`
   187  - _Maps_ because everybody needs them: `map[string]int`
   188  - _Interfaces_ for polymorphism: `interface{}`
   189  - _Channels_ for communication between goroutines: `chan` `int`
   190  
   191  * Variables
   192  
   193  Familiar:
   194  
   195  .code goforc/vars.go /START1/,/STOP1/
   196  
   197  New: Type can be inferred from type of initializing expression.
   198  
   199  .code goforc/vars.go /START2/,/STOP2/
   200  
   201  Shortcut (inside functions):
   202  
   203  .code goforc/vars.go /i :=/
   204  
   205  It is _safe_ to take the address of _any_ variable:
   206  
   207  .code goforc/vars.go /return/
   208  
   209  * Functions
   210  
   211  Functions may have multiple return values:
   212  
   213  	func atoi(s string) (i int, err error)
   214  
   215  Functions are first-class citizens (_closures_):
   216  
   217  .code goforc/adder.go /START1/,/STOP1/
   218  .play goforc/adder.go /START2/,/STOP2/
   219  
   220  * Statements
   221  
   222  .code goforc/stmts.go /START/,/STOP/
   223  
   224  * Go statements for C programmers
   225  
   226  Cleanups:
   227  
   228  - No semicolons
   229  - Multiple assignments
   230  - `++` and `--` are statements
   231  - No parentheses around conditions; curly braces mandatory
   232  - Implicit `break` in `switch`; explicit `fallthrough`
   233  
   234  New:
   235  
   236  - `for` `range`
   237  - type `switch`
   238  - `go`, `select`
   239  - `defer`
   240  
   241  * Assignments
   242  
   243  Assignments may assign multiple values simultaneously:
   244  
   245  	a, b = x, y
   246  
   247  Equivalent to:
   248  
   249  	t1 := x
   250  	t2 := y
   251  	a = t1
   252  	b = t2
   253  
   254  For instance:
   255  
   256  	a, b = b, a       // swap a and b
   257  	i, err = atoi(s)  // assign results of atoi
   258  	i, _ = atoi(991)  // discard 2nd value
   259  
   260  * Switch statements
   261  
   262  Switch statements may have multiple case values, and `break` is implicit:
   263  
   264  	switch day {
   265  	case 1, 2, 3, 4, 5:
   266  		tag = "workday"
   267  	case 0, 6:
   268  		tag = "weekend"
   269  	default:
   270  		tag = "invalid"
   271  	}
   272  
   273  The case values don't have to be constants:
   274  
   275  	switch {
   276  	case day < 0 || day > 6:
   277  		tag = "invalid"
   278  	case day == 0 || day == 6:
   279  		tag = "weekend"
   280  	default:
   281  		tag = "workday"
   282  	}
   283  
   284  * For loops
   285  
   286  .code goforc/forloop.go /START1/,/STOP1/
   287  
   288  A `range` clause permits easy iteration over arrays and slices:
   289  
   290  .play goforc/forloop.go /START3/,/STOP3/
   291  
   292  Unused values are discarded by assigning to the blank (_) identifier:
   293  
   294  .code goforc/forloop.go /START2/,/STOP2/
   295  
   296  * Dependencies
   297  
   298  * Dependencies in Go
   299  
   300  An _import_declaration_ is used to express a _dependency_ on another package:
   301  
   302  	import "net/rpc"
   303  
   304  Here, the importing package depends on the Go package "rpc".
   305  
   306  The _import_path_ ("net/rpc") uniquely identifies a package; multiple packages may have the same name, but they all reside at different locations (directories).
   307  
   308  By convention, the package name matches the last element of the import path (here: "rpc").
   309  
   310  _Exported_ functionality of the `rpc` package is available via the _package_qualifier_ (`rpc`):
   311  
   312  	rpc.Call
   313  
   314  A Go import declaration takes the place of a C _include_.
   315  
   316  * Naming: An excursion
   317  
   318  How names work in a programming language is critical to readability.
   319  Scopes control how names work.
   320  Go has very simple scope hierarchy:
   321  
   322  - universe
   323  - package
   324  - file (for imports only)
   325  - function
   326  - block
   327  
   328  * Locality of names
   329  
   330  Upper case names are _exported_: `Name` _vs._ `name`.
   331  
   332  The package qualifier is always present for imported names.
   333  
   334  (First component of) every name is always declared in the current package.
   335  
   336  One of the best (and hardest!) decisions made in Go.
   337  
   338  * Locality scales
   339  
   340  No surprises when importing:
   341  
   342  - Adding an exported name to my package cannot break your package!
   343  
   344  Names do not leak across boundaries.
   345  
   346  In C, C++, Java the name `y` could refer to anything.
   347  In Go, `y` (or even `Y`) is always defined within the package.
   348  In Go, `x.Y` is clear: find `x` locally, `Y` belongs to it, and there is only one such `Y`.
   349  
   350  Immediate consequences for readability.
   351  
   352  * Back to imports
   353  
   354  Importing a package means reading a package's exported API.
   355  
   356  This export information is self-contained. For instance:
   357  
   358  - A imports B
   359  - B imports C
   360  - B exports contain references to C
   361  
   362  B's export data contains all necessary information about C. There is no need for a compiler to read the export data of C.
   363  
   364  This has huge consequences for build times!
   365  
   366  * Dependencies in C
   367  
   368  `.h` files are not self-contained.
   369  
   370  As a result, a compiler ends up reading core header files over and over again.
   371  
   372  `ifdef` still requires the preprocessor to read a lot of code.
   373  
   374  No wonder it takes a long time to compile...
   375  
   376  At Google scale: dependencies explode, are exponential, become almost non-computable.
   377  
   378  A large Google C++ build can read the same header file tens of thousands of times!
   379  
   380  # it is real work, too, teaching the compiler what a string is each time
   381  
   382  * Tools
   383  
   384  * A brief overview
   385  
   386  Two compilers: gc, gccgo
   387  
   388  Support for multiple platforms: x86 (32/64bit), ARM (32bit), Linux, BSD, OS X, ...
   389  
   390  Automatic formatting of source code: `gofmt`
   391  
   392  Automatic documentation extraction: `godoc`
   393  
   394  Automatic API adaption: `gofix`
   395  
   396  All (and more!) integrated into the `go` command.
   397  
   398  * Building a Go program
   399  
   400  A Go program can be compiled and linked without additional build information (`make` files, etc.).
   401  
   402  By convention, all files belonging to a package are found in the same directory.
   403  
   404  All depending packages are found by inspecting the import paths of the top-most (_main_) package.
   405  
   406  A single integrated tool takes care of compiling individual files or entire systems.
   407  
   408  * The go command
   409  
   410  Usage:
   411  
   412  	go command [arguments]
   413  
   414  Selected commands:
   415  
   416  	build       compile packages and dependencies
   417  	clean       remove object files
   418  	doc         run godoc on package sources
   419  	fix         run go tool fix on packages
   420  	fmt         run gofmt on package sources
   421  	get         download and install packages and dependencies
   422  	install     compile and install packages and dependencies
   423  	list        list packages
   424  	run         compile and run Go program
   425  	test        test packages
   426  	vet         run go tool vet on packages
   427  
   428  .link http://golang.org/cmd/go/
   429  
   430  * Break
   431  
   432  # After the break, we will discuss OOP and concurrency in Go.
   433  
   434  * Object-oriented programming
   435  
   436  * What is object-oriented programming?
   437  
   438  "Object-oriented programming (OOP) is a programming paradigm using _objects_ – usually instances of a class – consisting of data fields and methods together with their interactions – to design applications and computer programs. Programming techniques may include features such as data abstraction, encapsulation, messaging, modularity, polymorphism, and inheritance. Many modern programming languages now support forms of OOP, at least as an option."
   439  
   440  (Wikipedia)
   441  
   442  # Important:
   443  # Notion of _objects_
   444  # _Objects_ have _state_ (data fields), and _methods_ (for interactions)
   445  
   446  * OOP requires very little extra programming language support
   447  
   448  We only need
   449  
   450  - the notion of an _Object_,
   451  - a mechanism to interact with them (_Methods_),
   452  - and support for polymorphism (_Interfaces_).
   453  
   454  Claim: Data abstraction, encapsulation, and modularity are mechanisms
   455  in their own right, not OOP specific, and a modern language (OO or not)
   456  should have support for them independently.
   457  
   458  
   459  * Object-oriented programming in Go
   460  
   461  Methods without classes
   462  
   463  Interfaces without hierarchies
   464  
   465  Code reuse without inheritance
   466  
   467  Specifically:
   468  
   469  - Any _value_ can be an _object_
   470  - Any _type_ can play the role of a _class_
   471  - _Methods_ can be attached to any _type_
   472  - _Interfaces_ implement polymorphism.
   473  
   474  * Methods
   475  
   476  .play goforc/point.go
   477  
   478  * Methods can be attached to any type
   479  
   480  .play goforc/celsius.go
   481  
   482  * Interfaces
   483  
   484  	type Stringer interface {
   485  	     String() string
   486  	}
   487  
   488  	type Reader interface {
   489  	     Read(p []byte) (n int, err error)
   490  	}
   491  
   492  	type Writer interface {
   493  	     Write(p []byte) (n int, err error)
   494  	}
   495  
   496  	type Empty interface{}
   497  
   498  An interface defines a set of methods.
   499  A type that implements all methods of an interface is said to implement the interface.
   500  All types implement the empty interface interface{}.
   501  
   502  * Dynamic dispatch
   503  
   504  .play goforc/interface.go /START/,/STOP/
   505  
   506  A value (here: `corner`, `boiling`) of a type (`Point`, `Celsius`) that implements
   507  an interface (`Stringer`) can be assigned to a variable (`v`) of that interface type.
   508  
   509  * Composition and chaining
   510  
   511  Typically, interfaces are small (1-3 methods).
   512  
   513  Pervasive use of key interfaces in the standard library make it easy to chain APIs together.
   514  
   515  	package io
   516  	func Copy(dst Writer, src Reader) (int64, error)
   517  
   518  The io.Copy function copies by reading from any Reader and writing to any Writer.
   519  
   520  Interfaces are often introduced ad-hoc, and after the fact.
   521  
   522  There is no explicit hierarchy and thus no need to design one!
   523  
   524  * cat
   525  
   526  .code goforc/cat.go
   527  
   528  # An `os.File` implements the `Reader` interface;
   529  # `os.Stdout` implements the `Writer` interface.
   530  
   531  * Interfaces in practice
   532  
   533  Methods on any types and _ad_hoc_ interfaces make for a light-weight OO programming style.
   534  
   535  Go interfaces enable post-facto abstraction.
   536  # Existing code may not know about a new interface
   537  
   538  No explicit type hierarchies.
   539  # Coming up with the correct type hierarchy is hard
   540  # They are often wrong
   541  # They are difficult and time-consuming to change
   542  
   543  "Plug'n play" in a type-safe way.
   544  
   545  # There's much more but we won't have time for more detail.
   546  
   547  * Concurrency
   548  
   549  * What is concurrency?
   550  
   551  Concurrency is the composition of independently executing computations.
   552  
   553  Concurrency is a way to structure software, particularly as a way to write clean code that interacts well with the real world.
   554  
   555  It is not parallelism.
   556  
   557  * Concurrency is not parallelism
   558  
   559  Concurrency is not parallelism, although it enables parallelism.
   560  
   561  If you have only one processor, your program can still be concurrent  but it cannot be parallel.
   562  
   563  On the other hand, a well-written concurrent program might run efficiently in parallel on a multiprocessor. That property could be important...
   564  
   565  For more on that distinction, see the link below. Too much to discuss here.
   566  
   567  .link http://golang.org/s/concurrency-is-not-parallelism
   568  
   569  * A model for software construction
   570  
   571  Easy to understand.
   572  
   573  Easy to use.
   574  
   575  Easy to reason about.
   576  
   577  You don't need to be an expert!
   578  
   579  (Much nicer than dealing with the minutiae of parallelism (threads, semaphores, locks, barriers, etc.))
   580  
   581  There is a long history behind Go's concurrency features, going back to Hoare's CSP in 1978 and even Dijkstra's guarded commands (1975).
   582  
   583  * Basic Examples
   584  
   585  * A boring function
   586  
   587  We need an example to show the interesting properties of the concurrency primitives.
   588  
   589  To avoid distraction, we make it a boring example.
   590  
   591  .code goforc/example0.go /START1/,/STOP1/
   592  .play goforc/example0.go /START2/,/STOP2/
   593  
   594  * Ignoring it
   595  
   596  The `go` statement runs the function as usual, but doesn't make the caller wait.
   597  
   598  It launches a goroutine.
   599  
   600  The functionality is analogous to the & on the end of a shell command.
   601  
   602  .play goforc/example1.go /START/,/STOP/
   603  
   604  * Ignoring it a little less
   605  
   606  When main returns, the program exits and takes the function `f` down with it.
   607  
   608  We can hang around a little, and on the way show that both main and the launched goroutine are running.
   609  
   610  .play goforc/example2.go /START/,/STOP/
   611  
   612  * Goroutines
   613  
   614  What is a goroutine? It's an independently executing function, launched by a `go` statement.
   615  
   616  It has its own call stack, which grows and shrinks as required.
   617  
   618  It's very cheap. It's practical to have thousands, even hundreds of thousands of goroutines.
   619  
   620  It's not a thread.
   621  
   622  There might be only one thread in a program with thousands of goroutines.
   623  
   624  Instead, goroutines are multiplexed dynamically onto threads as needed to keep all the goroutines running.
   625  
   626  But if you think of it as a very cheap thread, you won't be far off.
   627  
   628  * Channels
   629  
   630  A channel in Go provides a connection between two goroutines, allowing them to communicate.
   631  
   632  .code goforc/channels.go /START1/,/STOP1/
   633  .code goforc/channels.go /START2/,/STOP2/
   634  .code goforc/channels.go /START3/,/STOP3/
   635  
   636  * Using channels
   637  
   638  A channel connects the `main` and `f` goroutines so they can communicate.
   639  
   640  .play goforc/communication1.go /START1/,/STOP1/
   641  .code goforc/communication1.go /START2/,/STOP2/
   642  
   643  * Synchronization
   644  
   645  When the main function executes `<–c`, it will wait for a value to be sent.
   646  
   647  Similarly, when the function `f` executes `c<–value`, it waits for a receiver to be ready.
   648  
   649  A sender and receiver must both be ready to play their part in the communication. Otherwise we wait until they are.
   650  
   651  Thus channels both communicate and synchronize.
   652  
   653  Channels can be unbuffered or buffered.
   654  
   655  * Using channels between many goroutines
   656  
   657  .play goforc/communication2.go /START1/,/STOP1/
   658  
   659  A single channel may be used to communicate between many (not just two) goroutines; many goroutines may communicate via one or multiple channels.
   660  
   661  This enables a rich variety of concurrency patterns.
   662  
   663  # There's enough material for several talks on this subject alone.
   664  
   665  * Elements of a work-stealing scheduler
   666  
   667  .code goforc/worker1.go /START2/,/STOP2/
   668  
   669  The `worker` uses two channels to communicate:
   670  - The `in` channel waits for some work order.
   671  - The `out` channel communicates the result.
   672  - As work load, a worker (very slowly) computes the list of prime factors for a given order.
   673  
   674  * A matching producer and consumer
   675  
   676  .code goforc/worker1.go /START3/,/STOP3/
   677  
   678  The `producer` produces and endless supply of work orders and sends them `out`.
   679  
   680  The `consumer` receives `n` results from the `in` channel and then terminates.
   681  
   682  * Putting it all together
   683  
   684  .play goforc/worker1.go /START1/,/STOP1/
   685  
   686  We use one worker to handle the entire work load.
   687  
   688  Because there is only one worker, we see the result coming back in order.
   689  
   690  This is running rather slow...
   691  
   692  * Using 10 workers
   693  
   694  .play goforc/worker2.go /START1/,/STOP1/
   695  
   696  A ready worker will read the next order from the `in` channel and start working on it. Another ready worker will proceed with the next order, and so forth.
   697  
   698  Because we have many workers and since different orders take different amounts of time to work on, we see the results coming back out-of-order.
   699  
   700  On a multi-core system, many workers may truly run in parallel.
   701  
   702  This is running much faster...
   703  
   704  * The Go approach
   705  
   706  Don't communicate by sharing memory, share memory by communicating.
   707  
   708  * There's much more...
   709  
   710  * Links
   711  
   712  Go Home Page:
   713  
   714  .link http://golang.org
   715  
   716  Go Tour (learn Go in your browser)
   717  
   718  .link http://tour.golang.org
   719  
   720  Package documentation:
   721  
   722  .link http://golang.org/pkg
   723  
   724  Articles galore:
   725  
   726  .link http://golang.org/doc