Go basics
Golang Basics#
- Golang Basics
- Introduction
- How Go is different than other languages
- Install
- Setup
- Run
- Memory Management
- Keywords
- Declaration
- Data Type
- Data Structure
- Types & interfaces
- Reflection
- Statements
- Functions
- Struct
- Interface
- Constructor
- goroutine
- Channels
- Modules
- Package
- Import
- json
- regexp
- Errors
- Testing
- Debug
- Profiling
- Deploy
- Misc
- Best Practices
- Documentation
- Best Practices
- Concepts
- Debugging
- Profiling
- Design Patterns
- References
- Surprises
Introduction#
- intially developed at Google - 2007
- by Robert Griesemer, Rob Pike, and Ken Thompson
- is a statically-typed language with syntax similar to that of C
- provides
- garbage collection
- type safety
- dynamic-typing capability
- many advanced built-in types such as
- variable length arrays
- key-value maps
- heap
- a rich standard library
- is expressive, concise, clean, and efficient
- its concurrency mechanisms make it easy to write programs that get the most out of multi core and networked machines
- compiles quickly to machine code yet has the convenience of garbage collection and the power of run-time reflection
How Go is different than other languages#
- native concurrency support - i.e. at language-level
- different GC design
- single executable - copy/paste & deploy
- no dynamic/linked libraries
- keep lang. simple & expressive
- directly compiles to
machine code
- no virtual runtime or interpreter concept interior pointer
concept
Install#
Setup#
Run#
Memory Management#
- https://deepu.tech/memory-management-in-golang/
- https://medium.com/eureka-engineering/understanding-allocations-in-go-stack-heap-memory-9a2631b5035d
Stack vs Heap#
- https://stackoverflow.com/questions/10866195/stack-vs-heap-allocation-of-structs-in-go-and-how-they-relate-to-garbage-collec
Garbage Collection#
- https://blog.golang.org/ismmkeynote
- https://golang.org/doc/faq#garbage_collection
Keywords#
package
#
import
#
type
#
const
#
var
#
func
#
struct
#
Declaration#
Data Type#
bool
#
int
#
string
#
- https://blog.golang.org/strings
- In Go, a string is in effect a read-only slice of bytes
- string holds arbitrary bytes
- It is not required to hold Unicode text, UTF-8 text, or any other predefined format
- string literal that uses \xNN notation to define a string constant holding some peculiar byte values
- Of course, bytes range from hexadecimal values 00 through FF, inclusive
1 2 3 |
|
- NOTE: indexing/iterating over string gives bytes and not characters in Go
- that also means, when we store a character in a string, we store its byte representation
UTF-8 and string literals#
- placeOfInterest =
⌘
- Unicode character value U+2318
1 2 3 4 5 6 7 8 9 |
|
- NOTE:
- Source code in Go is defined to be UTF-8 text; no other representation is allowed
byte
#
Code points, characters, and runes#
- https://blog.golang.org/strings
Given
- lower case Latin letter 'A': a
- A: unicode code point: U+0061
- lower case grave-accented letter 'A', à
- B: unicode code point: U+00E0
- grave accent code point (that sign above a):
- C: unicode code point: U+0300
Then
à == A + C
or à == B
- code point == rune
- code point is a bit of mouthful, hence go introduces shorter term
rune
- rune meaning: any of the characters of any of several alphabets
- code point is a bit of mouthful, hence go introduces shorter term
-
character
- when we store a character value in a string, we store its byte-at-a-time representation
- In general, a character may be represented by a number of different sequences of code points, and therefore different sequences of UTF-8 bytes
- The concept of character in computing is therefore ambiguous, or at least confusing, so we use it with care
-
NOTE:
- Go team have been very careful so far in how we use the words "byte" and "character"
- That's partly because strings hold bytes, and partly because the idea of "character" is a little hard/ambiguous to define
Data Structure#
Array#
1 2 3 4 5 |
|
Slice#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
Map#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Types & interfaces#
- Go is statically typed
- Every variable has a static type, that is, exactly one type known and fixed at compile time: int, float32, *MyType, []byte, and so on
interface
is one important category of type - which represent fixed/minimal sets of methods
If we declare
1 2 3 4 |
|
then
i
has typeint
andj
has typeMyInt
- variables
i
andj
have distinct static types and, although they have the same underlying type, they cannot be assigned to one another without a conversion
An interface variable can store any concrete (non-interface) value as long as that value implements the interface's methods.
1 2 3 4 5 |
|
Here r
can exhibit lot more methods than Read()
of io.Reader
. Its not limited to methods provided by interface io.Reader
.
An extremely important example of an interface type is the empty interface: interface{}
interface{}
#
A.K.A. Empty Interface
It represents the empty set of methods and is satisfied by any value at all, since any value has zero or more methods.
- interface{} (empty interface) type describes an interface with zero methods
- Every Go type implements at least zero methods
- therefore satisfies the empty interface
- so we can receive any go data type in an empty interface (similar to object/var in other langs.)
1 2 3 4 5 6 |
|
- https://github.com/toransahu/go-misc/blob/master/interfac/main.go
A variable of interface type always has the same static type, and even though at run time the value stored in the interface variable may change type, that value will always satisfy the interface.
The representation of an interface#
- A variable of type
interface
type stores a pair: a concrete value assigned to the variable, and that concrete values's type/type-descriptor.
e.g.
1 2 3 4 5 6 |
|
here r
contains pair (value, concrete type) == (tty, *os.File).
As a interface variable also stores the type details, we can do things like this:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
this is called type assertion
.
Reflection#
- Reflection in computing is the ability of a program to examine its own structure, particularly through types; it's a form of metaprogramming. It's also a great source of confusion.
- reflection builds on the type system
The first law of reflection - Reflection goes from interface value to reflection object#
- At the basic level, reflection is just a mechanism to examine the type and value pair stored inside an interface variable
- there are two types we need to know about in package reflect: Type and Value
- Those two types give access to the contents of an interface variable, and two simple functions, called
reflect.TypeOf()
andreflect.ValueOf()
- tbd
- Those two types give access to the contents of an interface variable, and two simple functions, called
The second law of reflection - Reflection goes from reflection object to interface value#
tbd
The third law of reflection - To modify a reflection object, the value must be settable#
tbd
Statements#
Control Flows#
if
, else
#
1 2 3 4 5 6 7 |
|
- NOTE: there is no ternary
?
if else condition
for
#
for
is the only looping construct in Gofor
have 3-4 pattern
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
switch
#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
|
goto
#
- why its still valid in a new-gen prog. lang. ??
range
#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|
Functions#
- src:
- https://golang.org/doc/codewalk/functions/
First Class#
User-defined#
Higher-order#
- a function which accepts another function as a arg
Closures#
- a concept of having access of outer scope
- in an Anonynous function,
function literals
are closures: they inherit the scope of the function in which they are declared - same as python, javascript
Multiple Return Values#
- similar to pl/sql procedures
1 |
|
Variadic#
- variable/arbitrary numbers of arguments
- similar to
*args
variable
[space]...
concateanted totype
vardiac
arg is always aslice
- builtin e.g.
fmt.Println
1 2 3 4 5 6 7 8 9 10 11 12 |
|
- can directly pass a
slice
like
1 2 |
|
Anonymous/Lambda#
1 2 3 |
|
Access Modifier#
- depends on CASE of the func
- if starts with Capital case --> Public
- should have comment/doc string
- else private
- if starts with Capital case --> Public
Struct#
- regular struct
- in go, struct are alternative to classes
1 2 3 4 5 6 7 8 9 10 11 |
|
Methods#
1 2 3 4 5 6 7 |
|
Interface#
- Interfaces are named collections of method signatures
- https://gobyexample.com/interfaces
Constructor#
goroutine#
- A goroutine is a lightweight thread of execution
go
#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
|
by going through above mentioned example:
- if we want to invoke the function
f
as a goroutine we call it usinggo
statement- func
f
will execute concurrently with the calling/main one
- func
- we can also start a goroutine for an anonymous func
- our two function calls are running asynchronously in separate goroutines now
- we see output of
- blocking/synchronous call first
- then the interleaved output of two goroutines (output order may vary system to system)
defer
#
tbd
- https://blog.golang.org/defer-panic-and-recover
panic
#
recover
#
goroutine vs threads#
- can run more number of goroutines on a typical system than can threads
- goroutine are managed by go runtime, and have been designed to be lightweight
- thus the startup time is low
- its lightweight because it gets assigned very minimal memory, and that could be increased on demand
- that called growable segmented stack
- goroutine comes with in-built primitives called
channels
to communicate safely between themselves - goroutines are multiplexed onto a small number of OS threads, rather than 1:1 mapping
Channels#
- https://gobyexample.com/channels
- Channels are the pipes that connect concurrent goroutines
- You can send values into channels from one goroutine and receive those values into another goroutine
1 2 3 4 5 |
|
- NOTE: By default sends and receives block until both the sender and receiver are ready. This property allowed us to wait at the end of our program for the "ping" message without having to use any other synchronization.
- meaning that, whenever there will be receiver (and is ready to receive the value) then only sender can send the value/msg to the channel
- see: https://github.com/toransahu/go-misc/blob/master/goroutines/channels/channels.go#L30
- hence we can say, by default go channels are unbufferred
Channel Buffering#
- we checked above NOTE about readiness of
senders
&receivers
- channel buffering is to alter that nature & keep the value/msg in the buffer
- Buffered channels accept a limited number of values without a corresponding receiver for those values
1 2 3 4 5 |
|
- https://github.com/toransahu/go-misc/blob/master/goroutines/channels/buffered/buffered_channels.go
Channel Synchromization#
tbd
- https://gobyexample.com/channel-synchronization
Channel Directions#
tbd
- https://gobyexample.com/channel-directions
select
#
tbd
- https://gobyexample.com/select
Timeouts#
tbd
- https://gobyexample.com/timeouts
Non-blocking Channel operations#
tbd
- https://gobyexample.com/non-blocking-channel-operations
Closing Channels#
tbd
- https://gobyexample.com/closing-channels
range
over channels#
tbd
- https://gobyexample.com/range-over-channels
Modules#
A module is a collection of related Go packages that are versioned together as a single unit.
Ref:
- https://github.com/golang/go/wiki/Modules#modules
- https://github.com/golang/go/wiki/Modules
go mod
#
- to manage [versioned] dependencies
- was out with go 1.11 with preliminary/provisionary support & target to finalizing the feature for 1.14 (considering all feedbacks since 1.11-1.13)
- don't need to live the code in GOPATH
- creates/uses go.mod file
- the initial prototype
vgo
was announced in February 2018 - other alternatives were: dep, gom etc.
- management of interdependencies:
- vgo's controversial algo uses the oldest common version to support stability
- this may while discard the acceptance of any security bug fixed in newer version
- e.g.
- package A uses B and B uses D's atleast 1.0 version
- package A also uses C and C uses D's either 1.0 or 1.1 version
- then, as per vgo
- vgo's controversial algo uses the oldest common version to support stability
- vgo
- versioned go
- manages all the algorithm of versioning the go projects/packages/modules
- cmd
vgo build
is capable of generating go.mod - creates/manages versioned cache packages inside GOPATH/src/v
- there are support for more than one module in repository, but general idea is one
- As of Go 1.11, the go command enables the use of modules when the current directory or any parent directory has a go.mod, provided the directory is outside GOPATH/src. (Inside GOPATH/src, for compatibility, the go command still runs in the old GOPATH mode, even if a go.mod is found. See the go command documentation for details.)
- Starting in Go 1.13, module mode will be the default for all development.
- In addition to go.mod, the go command maintains a file named go.sum containing the expected cryptographic hashes of the content of specific module versions
- to maintain the intigrity of the go.mod
Semantic Import Versioning (SEMVER)#
- way to handle major dependency changes like:
- v1 to v2, v3,...
- API/interface changes
- how
- /github.com/toransahu/log (contains all v1.x.x) & /github.com/toransahu/log/v2 (contains all v2.x.x)
Ref:
- https://research.swtch.com/vgo-import
Package#
main#
package
Vs directory
#
Built-in Packages#
timer
& ticker
#
tbd
- https://gobyexample.com/timers
- https://gobyexample.com/tickers
continue exploring other packages from here
Import#
Inbuilt Package#
Intra Package#
Inter Package#
Remote Package#
Cyclic#
json
#
Encoding#
func Marshal(v interface{}) ([]byte, error)
-
Only data structures that can be represented as valid JSON will be encoded:
- JSON objects only support strings as keys; to encode a Go map type it must be of the form map[string]T (where T is any Go type supported by the json package).
- TODO: Channel, complex, and function types cannot be encoded.
- TODO: Cyclic data structures are not supported; they will cause Marshal to go into an infinite loop.
- Pointers will be encoded as the values they point to (or 'null' if the pointer is nil)
-
The json package only accesses the exported fields of struct types (those that begin with an uppercase letter). Therefore only the the exported fields of a struct will be present in the JSON output.
- TODO: what if alias is also provided?
- we can also provide
json:"alias"
for each field in the struct- so that those fields will be encoded as per
aliases
- shortcut to generate those:
- vim-go:
- visual select ->
<leader> GoAddTags
- visual select ->
- GoLand:
- vim-go:
- so that those fields will be encoded as per
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
- https://github.com/toransahu/go-misc/blob/master/json/encoding.go
Decoding#
- https://github.com/toransahu/go-misc/blob/master/json/decoding.go
Generic JSON with interface{}#
- The json package uses map[string]interface{} and []interface{} values
- to store arbitrary JSON objects and arrays
- it will happily unmarshal any valid JSON blob into a plain interface{} value
- default concrete Go types are:
bool
for JSON booleansfloat64
for JSON numbersstring
for JSON stringsnil
for JSON null
Creating arbitrary data#
1 2 3 |
|
Encoding arbitrary data#
1 |
|
Decoding arbitrary data#
- https://github.com/toransahu/go-misc/blob/master/json/json_test.go#L33
1 2 |
|
Json & Reference Type (pointers, slices, maps)#
- https://blog.golang.org/json-and-go
- https://github.com/toransahu/go-misc/blob/master/jsons/reference_type.go#L53
Streaming Encoders and Decoders#
- https://blog.golang.org/json-and-go
Misc#
- https://vsupalov.com/go-json-omitempty/
- https://www.reddit.com/r/golang/comments/k0hitv/compiler_written_in_go/
- Lexical Scanning in Go - Rob Pike
regexp
#
Ref:
- https://golang.org/pkg/regexp/
- https://github.com/google/re2/wiki/Syntax
- https://shapeshed.com/golang-regexp/
Errors#
- https://gobyexample.com/errors
Error Handling#
- https://blog.golang.org/error-handling-and-go
Testing#
- test module should named as
*_test.go
under packages - FIXME: better to organize test modules in a separate package - similar to Java??
Testcase
#
Benchmarks
#
Examples
#
Skipping
#
Subtests
and Sub-benchmarks
#
Main
#
Run#
- a test file
~/go/src/github.com/toransahu/go-misc/json on
master! ⌚ 14:18:45
$ go test json_test.go config.go encoding.go ok command-line-arguments 0.003s
- all test files under a package
~/go/src/github.com/toransahu/go-misc/json on
master! ⌚ 14:18:56
$ go test
PASS
ok github.com/toransahu/go-misc/json 0.002s
- all test files in all packages
tbd
- specific test function of a test file
tbd
- specific test function/file with pattern/regex
tbd
Coverage#
-
https://blog.alexellis.io/golang-writing-unit-tests/
-
src:
- https://golang.org/pkg/testing/#hdr-Subtests_and_Sub_benchmarks
- https://stackoverflow.com/questions/16935965/how-to-run-test-cases-in-a-specified-file
Debug#
gdb#
- https://golang.org/doc/gdb
Delve#
Profiling#
pprof
#
- https://blog.golang.org/pprof
CPU Profiling - stack sampling (vs instrumentation)#
Heap Profiling - allocation profiling#
Block#
Trace#
Deploy#
CircleCI#
Run Test#
Misc#
generate
#
- automatically generate golang code for a particular purpose
- like print name of memebers in a struct
stringr
- like print name of memebers in a struct
- https://blog.golang.org/generate
- can set header/preprocessor (with commands) in the go file to do the job on each build
Advance Testing#
assert
#
- 3rd party packages for assert.*
- https://github.com/stretchr/testify
Extra#
- https://talks.golang.org/2012/10things.slide#3
Best Practices#
Naming Convetions#
- https://golang.org/doc/effective_go.html#names
- https://blog.golang.org/package-names
Code Organization#
- Package
- main
- test
- https://blog.golang.org/organizing-go-code
- inside a directory
- all modules with only single package name
- can only execute/run
main
package module- hence
main
package
- hence
func main
should be declared to run themain
package module
Documentation#
- to document a type, variable, constant, function, or even a package, write a regular comment directly preceding its declaration, with no intervening blank line
- a complete sentence
- begins with the name of the element
- similar to
python
'sDocstring
&java
'sJavadoc
but simpler than them - src:
- https://blog.golang.org/godoc-documenting-go-code
1 2 3 4 5 6 7 8 9 10 |
|
Godoc
#
Best Practices#
Concepts#
Compilation#
Static Typing#
Pointer#
Garbage Collection#
- Go language features, goals, and use cases have forced to rethink the entire garbage collection stack and have led to a surprising place
- Go programs have hundreds of thousands of stacks
- They are managed by the Go scheduler and are always preempted at GC safepoints
- The Go scheduler multiplexes Go routines onto OS threads which hopefully run with one OS thread per HW thread
- We manage the stacks and their size by copying them and updating pointers in the stack. It's a local operation so it scales fairly well.
Ref:
- https://blog.golang.org/ismmkeynote
- https://www.ardanlabs.com/blog/2018/12/garbage-collection-in-go-part1-semantics.html
Debugging#
gdb
#
- https://golang.org/doc/gdb
- https://astaxie.gitbooks.io/build-web-application-with-golang/content/en/11.2.html
Delve#
Profiling#
- https://blog.golang.org/pprof
Design Patterns#
References#
- https://golang.org/doc/code.html
- https://github.com/golang/go/wiki/Learn
- https://go.dev/about/#best-practices-h2
Surprises#
- https://medium.com/@karel_3d/things-that-surprised-me-in-go-47bccce94558
- https://utcc.utoronto.ca/~cks/space/blog/programming/GoInteriorPointerGC
- https://dave.cheney.net/2017/04/29/there-is-no-pass-by-reference-in-go