SlideShare ist ein Scribd-Unternehmen logo
1 von 55
Go is a statically typed, compiled programming language designed at Google in 2007 by Robert Griesemer(JVM, V8 JavaScript
engine),
Rob Pike(Unix, UTF-8), and Ken Thompson(B, C, Unix) to improve programming productivity in an era
of multicore, networked machines and large codebases.
The designers wanted to address criticism of other languages in use at Google, but keep their useful characteristics:
- Static typing and run-time efficiency (like C)
- Readability and usability (like Python or JavaScript)
- High-performance networking and multiprocessing
It is syntactically like C, but with memory safety, garbage collection, structural typing, and CSP-style concurrency.
There are two major implementations:
1. Google's self-hosting "gc" compiler toolchain, targeting multiple operating systems and WebAssembly.
2. gofrontend, a frontend to other compilers, with the libgo library. With GCC the combination is gccgo; with LLVM the combination is
gollvm.
A third-party source-to-source compiler, GopherJS,[20] compiles Go to JavaScript for
front-end web development.
The guarantee: code written for Go 1.0 will build and run with Go 1.X.
Hello, Go!
package main
import "fmt"
func main() {
fmt.Println("Hello, Go!")
}
Variables
func main() {
var i, j int = 1, 2
k := 3
c, python, java := true, false, "no!”
const LENGTH int = 10
fmt.Println(i, j, k, c, python, java, LENGTH)
}
Functions
func multipleResults(x, y string) (string, string) {
return y, x
}
func sum(x int, y int) int {
return y + x
}
Zero Values
var i int // my zero value is 0
var f float64 // my zero value is 0
var b bool // my zero value is false
var s string // my zero value is ""
Exported(Public) & Unexported(Private)
var ExportedVar = ""
var unexportedVar = ""
func unexportedFunc() {
fmt.Println("unexported func!")
}
func ExportedFunc() {
fmt.Println("exported func")
}
Switch
switch os := runtime.GOOS; os {
case "darwin":
fmt.Println("OS X.")
case "linux":
fmt.Println("Linux.")
default:
fmt.Printf("%s.n", os)
}
// Switch with no condition
t := time.Now()
switch {
case t.Hour() < 12:
fmt.Println("Good morning!")
case t.Hour() < 17:
fmt.Println("Good afternoon.")
default:
fmt.Println("Good evening.")
}
Pointers
func main() {
i, j := 42, 2701
p := &i // point to i
fmt.Println(*p) // read i through the pointer
*p = 21 // set i through the pointer
fmt.Println(i) // see the new value of i
p = &j // point to j
*p = *p / 37 // divide j through the pointer
fmt.Println(j) // see the new value of j
}
A pointer holds the memory address of a value.
Struct (“class”)
type Vertex struct {
X int
Y int
}
func NewVertex(x, y int) *Vertex{
return &Vertex{
X: x,
Y: y,
}
}
A struct is a collection of fields
Arrays
func main() {
var a [2]string
a[0] = "Hello"
a[1] = "World"
fmt.Println(a[0], a[1])
fmt.Println(a)
primes := [6]int{2, 3, 5, 7, 11, 13}
fmt.Println(primes)
}
Slices(“Lists”)
Slices are pointers to arrays, with the length of the
segment, and its capacity.
The length of a slice is the number of elements it contains.
The capacity of a slice is the number of elements in the
underlying array, counting from the first element in the
slice.
a := make([]int, 5) // len(a)=5
var s []int
// append works on nil slices.
s = append(s, 0)
What is the zero value of a slice?
Slices(“Lists”)
var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}
func main() {
for i, v := range pow {
fmt.Printf("2**%d = %dn", i, v)
}
for i := range pow {
pow[i] = 1 << uint(i) // == 2**i
}
for _, value := range pow {
fmt.Printf("%dn", value)
}
}
Maps
type Vertex struct {
Lat, Long float64
}
var m map[string]Vertex
func main() {
m = make(map[string]Vertex)
m["Bell Labs"] = Vertex{
40.68433, -74.39967,
}
fmt.Println(m["Bell Labs"])
}
What is the zero value of a map?
Methods
Go does not have classes. However, you can define methods on types.
type Vertex struct {
X, Y float64
}
func (v Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
func (v *Vertex) Scale(f float64) {
v.X = v.X * f
v.Y = v.Y * f
}
Methods
Choosing a value or pointer receiver
There are two reasons to use a pointer receiver.
The first is so that the method can modify the value that its receiver points to.
The second is to avoid copying the value on each method call.
This can be more efficient if the receiver is a large struct, for example.
In general, all methods on a given type should have either value or pointer
receivers, but not a mixture of both.
Enums
type AccountStatus int
const (
CreateInProgress AccountStatus = iota
CreateDone
CreateFailed
DeleteInProgress
DeleteFailed
)
func (a AccountStatus) String() string {
return [...]string{
"CreateInProgress",
"CreateDone",
"CreateFailed",
"DeleteInProgress",
"DeleteFailed",
}[a]
}
iota is an identifier that is used with constant, and which can
simplify constant definitions that use auto-increment
numbers. The iota keyword represents integer constant
starting from zero.
Interfaces
type Abser interface {
Abs() float64
}
type MyFloat float64
func (f MyFloat) Abs() float64 {
if f < 0 {
return float64(-f)
}
return float64(f)
}
type Vertex struct {
X, Y float64
}
func (v *Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
* Interface are pointers in GO!
Interfaces are named collections of method signatures.
Interfaces “trick”!
Let's say we are using a third-party library that defines this struct:
type Vertex struct {}
func (v *Vertex) DoSmt() float64 {
return 1.1
}
We can create an interface in our code and make Vertex struct implicity implement our interace!
It might be very usfull for unit testing.
type Bla interface {
DoSmt() float64
}
Composition(Embedding) over inheritance
type Request struct {
Resource string
}
type AuthenticatedRequest struct {
Request
Username, Password string
}
func main() {
ar := new(AuthenticatedRequest)
ar.Resource = "example.com/request"
ar.Username = "bob"
ar.Password = "P@ssw0rd"
fmt.Printf("%#v", ar)
}
Go supports embedding of structs and interfaces to
express a more seamless composition of types.
The empty interface (Any/Object)
The interface type that specifies zero methods is known as the
empty interface: interface{}
An empty interface may hold values of any type. (Every type implements at least zero
methods.)
Imports
1. Default import
2. Using alias
3. Access package content without typing the package name
4. Import a package solely for its side-effact (initialization)
import "fmt"
import format "fmt"
import . "fmt"
import _ "fmt"
Go Tools
Panic
A panic typically means something went unexpectedly wrong. Mostly we use it to fail
fast on errors that shouldn’t occur during normal operation, or that we aren’t
prepared to handle gracefully.
Running this program will cause it to panic, print an error message and goroutine
traces, and exit with a non-zero status.
func main() {
panic("a problem")
}
Defer
A defer statement defers the execution of a function until the
surrounding function returns.
When to use?
func main() {
defer fmt.Println("world")
fmt.Println("hello")
}
Recover
Go makes it possible to recover from a panic, by using
the recover built-in function. A recover can stop a panic from aborting
the program and let it continue with execution instead.
func main() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered. Error:n", r)
}
}()
mayPanic()
fmt.Println("After mayPanic()")
}
Error handling
Error handling in Golang is done through the built-in interface type, error.
It’s zero value is nil; so, if it returns nil, that means that there were no error.
By convention, errors are the last return value
func divide(x int, y int) (int, error) {
if y == 0 {
return -1, errors.New("Cannot divide by 0!")
}
return x/y, nil
}
func main() {
answer, err := divide(5,0)
if err != nil {
// Handle the error!
fmt.Println(err) // will print “Cannot divide by 0!”
} else {
// No errors!
fmt.Println(answer)
}
}
type error interface {
Error() string
}
Error handling – where is my stacktrace?
func FindUser(username string) (*db.User, error) {
u, err := db.Find(username)
if err != nil {
return nil, fmt.Errorf("FindUser: failed executing db query: %w", err)
}
return u, nil
}
func SetUserAge(u *db.User, age int) error {
if err := db.SetAge(u, age); err != nil {
return fmt.Errorf("SetUserAge: failed executing db update: %w", err)
}
}
func FindAndSetUserAge(username string, age int) error {
var user *User
var err error
user, err = FindUser(username)
if err != nil {
return fmt.Errorf("FindAndSetUserAge: %w", err)
}
if err = SetUserAge(user, age); err != nil {
return fmt.Errorf("FindAndSetUserAge: %w", err)
}
return nil
}
Calling FindAndSetUserAge result:
FindAndSetUserAge: SetUserAge: failed executing db update: malformed request
Golang authors thought that the stack trace should be printed
only on Panic to reduce the overhead of unwinding the call stack.
It goes hand in hand with the error handling approach -
since errors must be handled, the developer should take care also
for the stack trace.
However, if you still want a stack trace you can get it using go runtime/debug package.
There are some third-party libraries that can be used for that:
https://pkg.go.dev/golang.org/x/xerrors
https://github.com/pkg/errors
https://github.com/rotisserie/eris
Go 2.0 - Error Handling draft
Check & handle keywords - inspired by Rust & Swift (abandoned)
func main() {
err := doSmt()
handle err {
log.Fatal(err)
}
hex := check ioutil.ReadAll(os.Stdin)
data := check parseHexdump(string(hex))
os.Stdout.Write(data)
}
- Adding stack trace
- Adding formatting
Dependecies (Go Modules)
The go.mod file is the root of dependency management in GoLang.
All the modules which are needed or to be used in the project are
maintained in go.mod file.
After running any package building command like go build, go test for
the first time, it will install all the packages with specific versions i.e. which
are the latest at that moment.
It will also create a go.sum file which maintains the checksum so when you
run the project again it will not install all packages again. But use the cache
which is stored inside $GOPATH/pkg/mod directory
(module cache directory).
go.sum is a generated file you don’t have to edit or modify this file.
“require” will include all dependency modules and the related version we
are going to use in our project
“replace” points to the local version of a dependency in Go rather than the
git-web. It will create a local copy of a vendor with versions available so no
need to install every time when we want to refer the vendor.
“//indirect” implies that we are not using these dependencies inside our
project but there is some module which imports these.
all the transitive dependencies are indirect, these include dependencies
which our project needs to work properly.
Dependecies (Go Modules)
go mod tidy -
It will bind the current imports in the project and packages listed in go.mod.
It ensures that the go.mod file matches the source code in the module. It adds any missing
module requirements necessary to build the current module’s packages and dependencies, if
there are some not used dependencies go mod tidy will remove those from go.mod accordingly.
It also adds any missing entries to go.sum and removes unnecessary entries.
go mod vendor -
It generates a vendor directory with the versions available. It copies all third-party dependencies
to a vendor folder in your project root.
This will add all the transitive dependencies required in order to run the vendor package.
When vendoring is enabled, the go command will load packages from the vendor directory
instead of downloading modules from their sources into the module cache and using packages
those downloaded.
Generics
Starting with version 1.18, Go has added support for generics, also known
as type parameters.
func MapKeys[K comparable, V any](m map[K]V) []K {
r := make([]K, 0, len(m))
for k := range m {
r = append(r, k)
}
return r
}
func main() {
var m = map[int]string{1: "2", 2: "4", 4: "8"}
fmt.Println("keys:", MapKeys(m))
}
Context
A Context carries deadlines, cancellation signals, and other request-scoped values across API boundaries and
goroutines.
Incoming requests to a server should create a Context, and outgoing calls to servers should accept a Context.
The chain of function calls between them must propagate the Context, optionally replacing it with a derived
Context created using WithCancel, WithDeadline, WithTimeout, or WithValue.
When a Context is canceled, all Contexts derived from it are also canceled.
The WithCancel, WithDeadline, and WithTimeout functions take a Context (the parent) and return a derived
Context (the child) and a CancelFunc. Calling the CancelFunc cancels the child and its children, removes the
parent's reference to the child, and stops any associated timers. Failing to call the CancelFunc leaks the child
and its children until the parent is canceled or the timer fires.
The go vet tool checks that CancelFuncs are used on all control-flow paths.
- Do not pass a nil Context, even if a function permits it.
Pass context.TODO if you are unsure about which Context to use.
- Use context Values only for request-scoped data that transits processes and APIs,
not for passing optional parameters to functions.
- The same Context may be passed to functions running in different goroutines;
Contexts are safe for simultaneous use by multiple goroutines (context is immutable)
Unit Testing
func TestSplit(t *testing.T) {
tests := map[string]struct {
input string
sep string
want []string
}{
"simple": {input: "a/b/c", sep: "/", want: []string{"a", "b", "c"}},
"wrong sep": {input: "a/b/c", sep: ",", want: []string{"a/b/c"}},
"no sep": {input: "abc", sep: "/", want: []string{"abc"}},
"trailing sep": {input: "a/b/c/", sep: "/", want: []string{"a", "b", "c"}},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
got := Split(tc.input, tc.sep)
if !reflect.DeepEqual(tc.want, got) {
t.Fatalf("expected: %v, got: %v", tc.want, got)
}
})
}
}
Unit Testing - Mocking
type MyRepo interface {
Get(ctx context.Context, id string) (interface{}, error)
Update(ctx context.Context, model interface{}) (interface{}, error)
}
type MyRepoImpl struct {
pg interface{}
}
func (m *MyRepoImpl) Get(ctx context.Context, id string) (interface{}, error) {
panic("implement me")
}
func (m *MyRepoImpl) Update(ctx context.Context, model interface{}) (interface{}, error) {
panic("implement me")
}
type MyRepoMock struct {
MockGet func(ctx context.Context, id string) (interface{}, error)
MockUpdate func(ctx context.Context, model interface{}) (interface{}, error)
}
func (a *MyRepoMock) Get(ctx context.Context, id string) (interface{}, error) {
return a.MockGet(ctx, id)
}
func (a *MyRepoMock) Update(ctx context.Context, model interface{}) (interface{}, error) {
return a.MockUpdate(ctx, model)
}
type MyService struct {
myRepo MyRepo
}
func (s *MyService) DoSmt(ctx context.Context) error {
// some logic...
model, err := s.myRepo.Get(ctx, "123")
if err != nil {
return err
}
// some logic...
}
Context - WithValue
func doSomething(ctx context.Context) {
fmt.Printf("doSomething: myKey's value is %sn", ctx.Value("myKey"))
}
func main() {
ctx := context.Background()
ctx = context.WithValue(ctx, "myKey", "myValue")
doSomething(ctx)
}
Output
doSomething: myKey's value is myValue
Context - WithCancel
func doSomething(ctx context.Context) {
ctx, cancelCtx := context.WithCancel(ctx)
printCh := make(chan int)
go doAnother(ctx, printCh)
for num := 1; num <= 3; num++ {
printCh <- num
}
cancelCtx()
time.Sleep(100 * time.Millisecond)
fmt.Printf("doSomething: finishedn")
}
func doAnother(ctx context.Context, printCh <-chan int) {
for {
select {
case <-ctx.Done():
if err := ctx.Err(); err != nil {
fmt.Printf("doAnother err: %sn", err)
}
fmt.Printf("doAnother: finishedn")
return
case num := <-printCh:
fmt.Printf("doAnother: %dn", num)
}
}
}
Output
doAnother: 1
doAnother: 2
doAnother: 3
doAnother err: context canceled
doAnother: finished
doSomething: finished
Context – WithDeadline / WithTimeout
const shortDuration = 1 * time.Millisecond
func main() {
d := time.Now().Add(shortDuration)
ctx, cancel := context.WithDeadline(context.Background(), d)
// Even though ctx will be expired, it is good practice to call its
// cancellation function in any case. Failure to do so may keep the
// context and its parent alive longer than necessary.
defer cancel()
select {
case <-time.After(1 * time.Second):
fmt.Println("overslept")
case <-ctx.Done():
fmt.Println(ctx.Err())
}
}
Output:
context deadline exceeded
Context – OpenTelemetry
OpenTelemetry also relies heavily on context for what is
called Context Propagation. That is a way to tied up
requests happening in different systems. The way to
implement that is to Inject span information into the
context you are going to send as part of the protocol you
are using (HTTP or gRPC, for instance). On the other
service you need to Extract the span information out of the
context.
Concurrency model
According to Rob Pike, concurrency is the composition of independently
executing computations, and concurrency is not parallelism: concurrency
is about dealing with lots of things at once, but parallelism is about doing
lots of things at once. Concurrency is about structure, parallelism is
about execution, concurrency provides a way to structure a solution to
solve a problem that may (but not necessarily) be parallelizable.
If you have only one processor, your program can still be concurrent, but it
cannot be parallel.
On the other hand, a well-written concurrent program might run efficiently in
parallel on a multiprocessor.
Goroutine
A goroutine is a lightweight thread(faster context switching & smaller size(2kB) compared with OS thread(1MB))
managed by the Go runtime.
It has its own call stack, which grows and shrinks as required.
It's very cheap. It's practical to have thousands, even hundreds of thousands of goroutines.
It's not a thread!
There might be only one thread in a program with thousands of goroutines.
Instead, goroutines are multiplexed dynamically onto threads as needed to keep all the goroutines running.
But if you think of it as a very cheap thread, you won't be far off.
The GOMAXPROCS variable limits the number of operating system threads
that can execute user-level Go code simultaneously.
There is no limit to the number of threads that can be blocked in system calls on behalf of Go code;
those do not count against the GOMAXPROCS limit. This package's GOMAXPROCS function
queries and changes the limit.
func say(s string) {
for i := 0; i < 5; i++ {
time.Sleep(100 * time.Millisecond)
fmt.Println(s)
}
}
func main() {
go say("world")
say("hello")
}
Channels
Don't communicate by sharing memory, share memory by communicating!
A channel in Go provides a connection between two goroutines, allowing them to communicate.
// Declaring and initializing.
var c chan int
c = make(chan int)
// or
c := make(chan int)
// Sending on a channel.
c <- 1
// Receiving from a channel.
// The "arrow" indicates the direction of data flow.
value = <-c
Channels
Buffered Channels - Sends to a buffered channel block only when the buffer is full.
Receives block when the buffer is empty.
ch := make(chan int, 100)
A sender can close a channel to indicate that no more values will be sent.
Only the sender should close a channel, never the receiver!
Closing is only necessary when the receiver must be told there are no more
values coming!
v, ok := <-ch
func fibonacci(n int, c chan int) {
x, y := 0, 1
for i := 0; i < n; i++ {
c <- x
x, y = y, x+y
}
close(c)
}
func main() {
c := make(chan int, 10)
go fibonacci(cap(c), c)
for i := range c {
fmt.Println(i)
}
}
Channels
Channel Directions- When using channels as function parameters, you can specify if a channel is
meant to only send or receive values. This specificity increases the type-safety of the program.
This ping function only accepts a channel for sending values. It would be a compile-time error to try
to receive on this channel.
The pong function accepts one channel for receives (pings)
and a second for sends (pongs).
func ping(pings chan<- string, msg string) {
pings <- msg
}
func pong(pings <-chan string, pongs chan<- string) {
msg := <-pings
pongs <- msg
}
func main() {
pings := make(chan string, 1)
pongs := make(chan string, 1)
ping(pings, "passed message")
pong(pings, pongs)
fmt.Println(<-pongs)
}
Channels - Select
The select statement lets a goroutine wait on multiple
communication operations.
A select blocks until one of its cases can run, then it
executes that case. It chooses one at random if multiple
are ready.
A default clause, if present, executes immediately if no
channel is ready.
select {
case v1 := <-c1:
fmt.Printf("received %v from c1n", v1)
case v2 := <-c2:
fmt.Printf("received %v from c2n", v1)
case c3 <- 23:
fmt.Printf("sent %v to c3n", 23)
default:
fmt.Printf("no one was ready to communicaten")
}
Channels - Timeout using select
The time.After function returns a channel that blocks for the
specified duration.
After the interval, the channel delivers the current time, once.
func main() {
c := boring("Joe")
for {
select {
case s := <-c:
fmt.Println(s)
case <-time.After(1 * time.Second):
fmt.Println("You're too slow.")
return
}
}
}
WaitGroups
To wait for multiple goroutines to finish, we can use a wait group.
func worker(id int) {
fmt.Printf("Worker %d startingn", id)
time.Sleep(time.Second)
fmt.Printf("Worker %d donen", id)
}
func main() {
var wg sync.WaitGroup
for i := 1; i <= 5; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
worker(i)
}(i)
}
wg.Wait()
}
sync.Mutex
We've seen how channels are great for communication
among goroutines.
But what if we don't need communication? What if we just
want to make sure only one goroutine can access a
variable at a time to avoid conflicts?
This concept is called mutual exclusion, and the
conventional name for the data structure that provides it
is mutex.
// SafeCounter is safe to use concurrently.
type SafeCounter struct {
mu sync.Mutex
v map[string]int
}
// Inc increments the counter for the given key.
func (c *SafeCounter) Inc(key string) {
c.mu.Lock()
// Lock so only one goroutine at a time can access the map c.v.
c.v[key]++
c.mu.Unlock()
}
// Value returns the current value of the counter for the given key.
func (c *SafeCounter) Value(key string) int {
c.mu.Lock()
// Lock so only one goroutine at a time can access the map c.v.
defer c.mu.Unlock()
return c.v[key]
}
func main() {
c := SafeCounter{v: make(map[string]int)}
for i := 0; i < 1000; i++ {
go c.Inc("somekey")
}
time.Sleep(time.Second)
fmt.Println(c.Value("somekey"))
}
Atomic Counters
Here we’ll look at using the sync/atomic package for atomic
counters accessed by multiple goroutines.
func main() {
var ops uint64
var wg sync.WaitGroup
for i := 0; i < 50; i++ {
wg.Add(1)
go func() {
for c := 0; c < 1000; c++ {
atomic.AddUint64(&ops, 1)
}
wg.Done()
}()
}
wg.Wait()
fmt.Println("ops:", ops)
}
Go Fuzzing
Go supports fuzzing in its standard toolchain beginning in Go 1.18.
Fuzzing is a type of automated testing which continuously manipulates inputs to a
program to find bugs. Go fuzzing uses coverage guidance to intelligently walk
through the code being fuzzed to find and report failures to the user. Since it can
reach edge cases which humans often miss, fuzz testing can be particularly valuable
for finding security exploits and vulnerabilities.
Best practices
- Do not ignore errors.
- Handle error only once.
- Use Channels for goroutines comunication.
- Return an error instead of using Panic (especially in libs).
- Return an Error interface instead of a custom error struct.
- Do not be lazy; Use interfaces!
- Do not pass function arguments on context.Context.
- Pass context.Context as the first argument to a function.
- Do not use package level vars & func init(magic is bad; global state is magic).
- Handle errors in deferred functions.
- When choosing a third-party lib make sure it is following the GO
Standard lib(context.Context, net/http…).
- Avoid Reflection.
What is the output of this program?
var WhatIsThe = AnswerToLife()
func AnswerToLife() int {
println("Hello from AnswerToLife")
return 42
}
func init() {
println("Hello from init")
WhatIsThe = 0
}
func main() {
println("Hello from main")
if WhatIsThe == 0 {
println("It's all a lie.")
}
}
Hello from AnswerToLife
Hello from init
Hello from main
It's all a lie.
Do not use package level vars & func init!
magic is bad; global state is magic!
What would we like Go to be better at?
• Error handling (& stack trace).
• Function Overloading and Default Values for Arguments.
• Extension funcs.
• Get Goroutine “result” – like Kotlin Coroutines:
• Null safety
• Define Enum type
• Functional programming
• Macros / inline function
fun String.removeFirstLastChar(): String = this.substring(1, this.length - 1)
val result = "Hello Everyone".removeFirstLastChar()
val x string?
x?.toLowercase()
val deferred: Deferred<String> = async {
"Hello World"
}
val result = deferred.await()
Usefull Resources
• https://go.dev/learn/
• https://go.dev/doc/effective_go
• https://gobyexample.com/
• https://go.dev/ref/spec
• https://peter.bourgon.org/blog/2017/06/09/theory-of-modern-go.html
• https://dave.cheney.net/
• https://github.com/avelino/awesome-go
• https://pkg.go.dev/cmd/go
• Google I/O 2012 - Go Concurrency Patterns
Until the next time…
Guy Komari

Weitere ähnliche Inhalte

Was ist angesagt?

Introduction to go lang
Introduction to go langIntroduction to go lang
Introduction to go langAmal Mohan N
 
Golang (Go Programming Language)
Golang (Go Programming Language)Golang (Go Programming Language)
Golang (Go Programming Language)ShubhamMishra485
 
Concurrency in Golang
Concurrency in GolangConcurrency in Golang
Concurrency in GolangOliver N
 
Introduction to GoLang
Introduction to GoLangIntroduction to GoLang
Introduction to GoLangNVISIA
 
Swift Programming Language
Swift Programming LanguageSwift Programming Language
Swift Programming LanguageGiuseppe Arici
 
Goroutines and Channels in practice
Goroutines and Channels in practiceGoroutines and Channels in practice
Goroutines and Channels in practiceGuilherme Garnier
 
Modern c++ (C++ 11/14)
Modern c++ (C++ 11/14)Modern c++ (C++ 11/14)
Modern c++ (C++ 11/14)Geeks Anonymes
 
Go Concurrency
Go ConcurrencyGo Concurrency
Go Concurrencyjgrahamc
 
Inline function
Inline functionInline function
Inline functionTech_MX
 
Reinventing the Y combinator
Reinventing the Y combinatorReinventing the Y combinator
Reinventing the Y combinatorIan Wang
 
Introduction to go language programming
Introduction to go language programmingIntroduction to go language programming
Introduction to go language programmingMahmoud Masih Tehrani
 
Exception Handling in C++
Exception Handling in C++Exception Handling in C++
Exception Handling in C++Deepak Tathe
 
Operators and expressions in C++
Operators and expressions in C++Operators and expressions in C++
Operators and expressions in C++Neeru Mittal
 
Operators in c programming
Operators in c programmingOperators in c programming
Operators in c programmingsavitamhaske
 
Introduction to C Programming
Introduction to C ProgrammingIntroduction to C Programming
Introduction to C ProgrammingAniket Patne
 

Was ist angesagt? (20)

Introduction to go lang
Introduction to go langIntroduction to go lang
Introduction to go lang
 
Golang (Go Programming Language)
Golang (Go Programming Language)Golang (Go Programming Language)
Golang (Go Programming Language)
 
GoLang Introduction
GoLang IntroductionGoLang Introduction
GoLang Introduction
 
Go. Why it goes
Go. Why it goesGo. Why it goes
Go. Why it goes
 
Concurrency in Golang
Concurrency in GolangConcurrency in Golang
Concurrency in Golang
 
Introduction to GoLang
Introduction to GoLangIntroduction to GoLang
Introduction to GoLang
 
Swift Programming Language
Swift Programming LanguageSwift Programming Language
Swift Programming Language
 
Goroutines and Channels in practice
Goroutines and Channels in practiceGoroutines and Channels in practice
Goroutines and Channels in practice
 
C program
C programC program
C program
 
Modern c++ (C++ 11/14)
Modern c++ (C++ 11/14)Modern c++ (C++ 11/14)
Modern c++ (C++ 11/14)
 
Go Concurrency
Go ConcurrencyGo Concurrency
Go Concurrency
 
Inline function
Inline functionInline function
Inline function
 
Reinventing the Y combinator
Reinventing the Y combinatorReinventing the Y combinator
Reinventing the Y combinator
 
Introduction to go language programming
Introduction to go language programmingIntroduction to go language programming
Introduction to go language programming
 
Functions in c++
Functions in c++Functions in c++
Functions in c++
 
Exception Handling in C++
Exception Handling in C++Exception Handling in C++
Exception Handling in C++
 
Operators and expressions in C++
Operators and expressions in C++Operators and expressions in C++
Operators and expressions in C++
 
Operators in c programming
Operators in c programmingOperators in c programming
Operators in c programming
 
Introduction to C Programming
Introduction to C ProgrammingIntroduction to C Programming
Introduction to C Programming
 
An introduction to programming in Go
An introduction to programming in GoAn introduction to programming in Go
An introduction to programming in Go
 

Ähnlich wie golang_getting_started.pptx

Go Programming Language (Golang)
Go Programming Language (Golang)Go Programming Language (Golang)
Go Programming Language (Golang)Ishin Vin
 
Beauty and Power of Go
Beauty and Power of GoBeauty and Power of Go
Beauty and Power of GoFrank Müller
 
Kamil witecki asynchronous, yet readable, code
Kamil witecki asynchronous, yet readable, codeKamil witecki asynchronous, yet readable, code
Kamil witecki asynchronous, yet readable, codeKamil Witecki
 
Go 1.10 Release Party - PDX Go
Go 1.10 Release Party - PDX GoGo 1.10 Release Party - PDX Go
Go 1.10 Release Party - PDX GoRodolfo Carvalho
 
Introduction to go
Introduction to goIntroduction to go
Introduction to goJaehue Jang
 
C programming language tutorial
C programming language tutorial C programming language tutorial
C programming language tutorial javaTpoint s
 
ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015Michiel Borkent
 
Go ahead, make my day
Go ahead, make my dayGo ahead, make my day
Go ahead, make my dayTor Ivry
 
What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)Pavlo Baron
 
Coding in GO - GDG SL - NSBM
Coding in GO - GDG SL - NSBMCoding in GO - GDG SL - NSBM
Coding in GO - GDG SL - NSBMRaveen Perera
 
Functions And Header Files In C++ | Bjarne stroustrup
Functions And Header Files In C++ | Bjarne stroustrupFunctions And Header Files In C++ | Bjarne stroustrup
Functions And Header Files In C++ | Bjarne stroustrupSyedHaroonShah4
 

Ähnlich wie golang_getting_started.pptx (20)

Go Programming Language (Golang)
Go Programming Language (Golang)Go Programming Language (Golang)
Go Programming Language (Golang)
 
Let's Go-lang
Let's Go-langLet's Go-lang
Let's Go-lang
 
Beauty and Power of Go
Beauty and Power of GoBeauty and Power of Go
Beauty and Power of Go
 
Kamil witecki asynchronous, yet readable, code
Kamil witecki asynchronous, yet readable, codeKamil witecki asynchronous, yet readable, code
Kamil witecki asynchronous, yet readable, code
 
Go 1.10 Release Party - PDX Go
Go 1.10 Release Party - PDX GoGo 1.10 Release Party - PDX Go
Go 1.10 Release Party - PDX Go
 
Introduction to go
Introduction to goIntroduction to go
Introduction to go
 
Go Lang Tutorial
Go Lang TutorialGo Lang Tutorial
Go Lang Tutorial
 
C programming language tutorial
C programming language tutorial C programming language tutorial
C programming language tutorial
 
ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015
 
7 functions
7  functions7  functions
7 functions
 
Go ahead, make my day
Go ahead, make my dayGo ahead, make my day
Go ahead, make my day
 
What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)
 
functions
functionsfunctions
functions
 
C Tutorials
C TutorialsC Tutorials
C Tutorials
 
Unit2 C
Unit2 C Unit2 C
Unit2 C
 
Unit2 C
Unit2 CUnit2 C
Unit2 C
 
Coding in GO - GDG SL - NSBM
Coding in GO - GDG SL - NSBMCoding in GO - GDG SL - NSBM
Coding in GO - GDG SL - NSBM
 
Functions And Header Files In C++ | Bjarne stroustrup
Functions And Header Files In C++ | Bjarne stroustrupFunctions And Header Files In C++ | Bjarne stroustrup
Functions And Header Files In C++ | Bjarne stroustrup
 
C tutorial
C tutorialC tutorial
C tutorial
 
C tutorial
C tutorialC tutorial
C tutorial
 

Kürzlich hochgeladen

Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...Rob Geurden
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024StefanoLambiase
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...Technogeeks
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Angel Borroy López
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...OnePlan Solutions
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...confluent
 
PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentationvaddepallysandeep122
 
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Hr365.us smith
 
Post Quantum Cryptography – The Impact on Identity
Post Quantum Cryptography – The Impact on IdentityPost Quantum Cryptography – The Impact on Identity
Post Quantum Cryptography – The Impact on Identityteam-WIBU
 
UI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptxUI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptxAndreas Kunz
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesŁukasz Chruściel
 
Precise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalPrecise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalLionel Briand
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Natan Silnitsky
 
VK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web DevelopmentVK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web Developmentvyaparkranti
 
Comparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfComparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfDrew Moseley
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesPhilip Schwarz
 
Machine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringMachine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringHironori Washizaki
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceBrainSell Technologies
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfStefano Stabellini
 

Kürzlich hochgeladen (20)

Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
 
PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentation
 
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)
 
Post Quantum Cryptography – The Impact on Identity
Post Quantum Cryptography – The Impact on IdentityPost Quantum Cryptography – The Impact on Identity
Post Quantum Cryptography – The Impact on Identity
 
UI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptxUI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptx
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New Features
 
Precise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalPrecise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive Goal
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
 
VK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web DevelopmentVK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web Development
 
Comparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfComparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdf
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a series
 
Machine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringMachine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their Engineering
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. Salesforce
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdf
 

golang_getting_started.pptx

  • 1.
  • 2. Go is a statically typed, compiled programming language designed at Google in 2007 by Robert Griesemer(JVM, V8 JavaScript engine), Rob Pike(Unix, UTF-8), and Ken Thompson(B, C, Unix) to improve programming productivity in an era of multicore, networked machines and large codebases. The designers wanted to address criticism of other languages in use at Google, but keep their useful characteristics: - Static typing and run-time efficiency (like C) - Readability and usability (like Python or JavaScript) - High-performance networking and multiprocessing It is syntactically like C, but with memory safety, garbage collection, structural typing, and CSP-style concurrency. There are two major implementations: 1. Google's self-hosting "gc" compiler toolchain, targeting multiple operating systems and WebAssembly. 2. gofrontend, a frontend to other compilers, with the libgo library. With GCC the combination is gccgo; with LLVM the combination is gollvm. A third-party source-to-source compiler, GopherJS,[20] compiles Go to JavaScript for front-end web development. The guarantee: code written for Go 1.0 will build and run with Go 1.X.
  • 3. Hello, Go! package main import "fmt" func main() { fmt.Println("Hello, Go!") }
  • 4. Variables func main() { var i, j int = 1, 2 k := 3 c, python, java := true, false, "no!” const LENGTH int = 10 fmt.Println(i, j, k, c, python, java, LENGTH) }
  • 5. Functions func multipleResults(x, y string) (string, string) { return y, x } func sum(x int, y int) int { return y + x }
  • 6. Zero Values var i int // my zero value is 0 var f float64 // my zero value is 0 var b bool // my zero value is false var s string // my zero value is ""
  • 7. Exported(Public) & Unexported(Private) var ExportedVar = "" var unexportedVar = "" func unexportedFunc() { fmt.Println("unexported func!") } func ExportedFunc() { fmt.Println("exported func") }
  • 8. Switch switch os := runtime.GOOS; os { case "darwin": fmt.Println("OS X.") case "linux": fmt.Println("Linux.") default: fmt.Printf("%s.n", os) } // Switch with no condition t := time.Now() switch { case t.Hour() < 12: fmt.Println("Good morning!") case t.Hour() < 17: fmt.Println("Good afternoon.") default: fmt.Println("Good evening.") }
  • 9. Pointers func main() { i, j := 42, 2701 p := &i // point to i fmt.Println(*p) // read i through the pointer *p = 21 // set i through the pointer fmt.Println(i) // see the new value of i p = &j // point to j *p = *p / 37 // divide j through the pointer fmt.Println(j) // see the new value of j } A pointer holds the memory address of a value.
  • 10. Struct (“class”) type Vertex struct { X int Y int } func NewVertex(x, y int) *Vertex{ return &Vertex{ X: x, Y: y, } } A struct is a collection of fields
  • 11. Arrays func main() { var a [2]string a[0] = "Hello" a[1] = "World" fmt.Println(a[0], a[1]) fmt.Println(a) primes := [6]int{2, 3, 5, 7, 11, 13} fmt.Println(primes) }
  • 12. Slices(“Lists”) Slices are pointers to arrays, with the length of the segment, and its capacity. The length of a slice is the number of elements it contains. The capacity of a slice is the number of elements in the underlying array, counting from the first element in the slice. a := make([]int, 5) // len(a)=5 var s []int // append works on nil slices. s = append(s, 0) What is the zero value of a slice?
  • 13. Slices(“Lists”) var pow = []int{1, 2, 4, 8, 16, 32, 64, 128} func main() { for i, v := range pow { fmt.Printf("2**%d = %dn", i, v) } for i := range pow { pow[i] = 1 << uint(i) // == 2**i } for _, value := range pow { fmt.Printf("%dn", value) } }
  • 14. Maps type Vertex struct { Lat, Long float64 } var m map[string]Vertex func main() { m = make(map[string]Vertex) m["Bell Labs"] = Vertex{ 40.68433, -74.39967, } fmt.Println(m["Bell Labs"]) } What is the zero value of a map?
  • 15. Methods Go does not have classes. However, you can define methods on types. type Vertex struct { X, Y float64 } func (v Vertex) Abs() float64 { return math.Sqrt(v.X*v.X + v.Y*v.Y) } func (v *Vertex) Scale(f float64) { v.X = v.X * f v.Y = v.Y * f }
  • 16. Methods Choosing a value or pointer receiver There are two reasons to use a pointer receiver. The first is so that the method can modify the value that its receiver points to. The second is to avoid copying the value on each method call. This can be more efficient if the receiver is a large struct, for example. In general, all methods on a given type should have either value or pointer receivers, but not a mixture of both.
  • 17. Enums type AccountStatus int const ( CreateInProgress AccountStatus = iota CreateDone CreateFailed DeleteInProgress DeleteFailed ) func (a AccountStatus) String() string { return [...]string{ "CreateInProgress", "CreateDone", "CreateFailed", "DeleteInProgress", "DeleteFailed", }[a] } iota is an identifier that is used with constant, and which can simplify constant definitions that use auto-increment numbers. The iota keyword represents integer constant starting from zero.
  • 18. Interfaces type Abser interface { Abs() float64 } type MyFloat float64 func (f MyFloat) Abs() float64 { if f < 0 { return float64(-f) } return float64(f) } type Vertex struct { X, Y float64 } func (v *Vertex) Abs() float64 { return math.Sqrt(v.X*v.X + v.Y*v.Y) } * Interface are pointers in GO! Interfaces are named collections of method signatures.
  • 19. Interfaces “trick”! Let's say we are using a third-party library that defines this struct: type Vertex struct {} func (v *Vertex) DoSmt() float64 { return 1.1 } We can create an interface in our code and make Vertex struct implicity implement our interace! It might be very usfull for unit testing. type Bla interface { DoSmt() float64 }
  • 20. Composition(Embedding) over inheritance type Request struct { Resource string } type AuthenticatedRequest struct { Request Username, Password string } func main() { ar := new(AuthenticatedRequest) ar.Resource = "example.com/request" ar.Username = "bob" ar.Password = "P@ssw0rd" fmt.Printf("%#v", ar) } Go supports embedding of structs and interfaces to express a more seamless composition of types.
  • 21. The empty interface (Any/Object) The interface type that specifies zero methods is known as the empty interface: interface{} An empty interface may hold values of any type. (Every type implements at least zero methods.)
  • 22. Imports 1. Default import 2. Using alias 3. Access package content without typing the package name 4. Import a package solely for its side-effact (initialization) import "fmt" import format "fmt" import . "fmt" import _ "fmt"
  • 24. Panic A panic typically means something went unexpectedly wrong. Mostly we use it to fail fast on errors that shouldn’t occur during normal operation, or that we aren’t prepared to handle gracefully. Running this program will cause it to panic, print an error message and goroutine traces, and exit with a non-zero status. func main() { panic("a problem") }
  • 25. Defer A defer statement defers the execution of a function until the surrounding function returns. When to use? func main() { defer fmt.Println("world") fmt.Println("hello") }
  • 26. Recover Go makes it possible to recover from a panic, by using the recover built-in function. A recover can stop a panic from aborting the program and let it continue with execution instead. func main() { defer func() { if r := recover(); r != nil { fmt.Println("Recovered. Error:n", r) } }() mayPanic() fmt.Println("After mayPanic()") }
  • 27. Error handling Error handling in Golang is done through the built-in interface type, error. It’s zero value is nil; so, if it returns nil, that means that there were no error. By convention, errors are the last return value func divide(x int, y int) (int, error) { if y == 0 { return -1, errors.New("Cannot divide by 0!") } return x/y, nil } func main() { answer, err := divide(5,0) if err != nil { // Handle the error! fmt.Println(err) // will print “Cannot divide by 0!” } else { // No errors! fmt.Println(answer) } } type error interface { Error() string }
  • 28. Error handling – where is my stacktrace? func FindUser(username string) (*db.User, error) { u, err := db.Find(username) if err != nil { return nil, fmt.Errorf("FindUser: failed executing db query: %w", err) } return u, nil } func SetUserAge(u *db.User, age int) error { if err := db.SetAge(u, age); err != nil { return fmt.Errorf("SetUserAge: failed executing db update: %w", err) } } func FindAndSetUserAge(username string, age int) error { var user *User var err error user, err = FindUser(username) if err != nil { return fmt.Errorf("FindAndSetUserAge: %w", err) } if err = SetUserAge(user, age); err != nil { return fmt.Errorf("FindAndSetUserAge: %w", err) } return nil } Calling FindAndSetUserAge result: FindAndSetUserAge: SetUserAge: failed executing db update: malformed request Golang authors thought that the stack trace should be printed only on Panic to reduce the overhead of unwinding the call stack. It goes hand in hand with the error handling approach - since errors must be handled, the developer should take care also for the stack trace. However, if you still want a stack trace you can get it using go runtime/debug package. There are some third-party libraries that can be used for that: https://pkg.go.dev/golang.org/x/xerrors https://github.com/pkg/errors https://github.com/rotisserie/eris
  • 29. Go 2.0 - Error Handling draft Check & handle keywords - inspired by Rust & Swift (abandoned) func main() { err := doSmt() handle err { log.Fatal(err) } hex := check ioutil.ReadAll(os.Stdin) data := check parseHexdump(string(hex)) os.Stdout.Write(data) } - Adding stack trace - Adding formatting
  • 30. Dependecies (Go Modules) The go.mod file is the root of dependency management in GoLang. All the modules which are needed or to be used in the project are maintained in go.mod file. After running any package building command like go build, go test for the first time, it will install all the packages with specific versions i.e. which are the latest at that moment. It will also create a go.sum file which maintains the checksum so when you run the project again it will not install all packages again. But use the cache which is stored inside $GOPATH/pkg/mod directory (module cache directory). go.sum is a generated file you don’t have to edit or modify this file. “require” will include all dependency modules and the related version we are going to use in our project “replace” points to the local version of a dependency in Go rather than the git-web. It will create a local copy of a vendor with versions available so no need to install every time when we want to refer the vendor. “//indirect” implies that we are not using these dependencies inside our project but there is some module which imports these. all the transitive dependencies are indirect, these include dependencies which our project needs to work properly.
  • 31. Dependecies (Go Modules) go mod tidy - It will bind the current imports in the project and packages listed in go.mod. It ensures that the go.mod file matches the source code in the module. It adds any missing module requirements necessary to build the current module’s packages and dependencies, if there are some not used dependencies go mod tidy will remove those from go.mod accordingly. It also adds any missing entries to go.sum and removes unnecessary entries. go mod vendor - It generates a vendor directory with the versions available. It copies all third-party dependencies to a vendor folder in your project root. This will add all the transitive dependencies required in order to run the vendor package. When vendoring is enabled, the go command will load packages from the vendor directory instead of downloading modules from their sources into the module cache and using packages those downloaded.
  • 32. Generics Starting with version 1.18, Go has added support for generics, also known as type parameters. func MapKeys[K comparable, V any](m map[K]V) []K { r := make([]K, 0, len(m)) for k := range m { r = append(r, k) } return r } func main() { var m = map[int]string{1: "2", 2: "4", 4: "8"} fmt.Println("keys:", MapKeys(m)) }
  • 33. Context A Context carries deadlines, cancellation signals, and other request-scoped values across API boundaries and goroutines. Incoming requests to a server should create a Context, and outgoing calls to servers should accept a Context. The chain of function calls between them must propagate the Context, optionally replacing it with a derived Context created using WithCancel, WithDeadline, WithTimeout, or WithValue. When a Context is canceled, all Contexts derived from it are also canceled. The WithCancel, WithDeadline, and WithTimeout functions take a Context (the parent) and return a derived Context (the child) and a CancelFunc. Calling the CancelFunc cancels the child and its children, removes the parent's reference to the child, and stops any associated timers. Failing to call the CancelFunc leaks the child and its children until the parent is canceled or the timer fires. The go vet tool checks that CancelFuncs are used on all control-flow paths. - Do not pass a nil Context, even if a function permits it. Pass context.TODO if you are unsure about which Context to use. - Use context Values only for request-scoped data that transits processes and APIs, not for passing optional parameters to functions. - The same Context may be passed to functions running in different goroutines; Contexts are safe for simultaneous use by multiple goroutines (context is immutable)
  • 34. Unit Testing func TestSplit(t *testing.T) { tests := map[string]struct { input string sep string want []string }{ "simple": {input: "a/b/c", sep: "/", want: []string{"a", "b", "c"}}, "wrong sep": {input: "a/b/c", sep: ",", want: []string{"a/b/c"}}, "no sep": {input: "abc", sep: "/", want: []string{"abc"}}, "trailing sep": {input: "a/b/c/", sep: "/", want: []string{"a", "b", "c"}}, } for name, tc := range tests { t.Run(name, func(t *testing.T) { got := Split(tc.input, tc.sep) if !reflect.DeepEqual(tc.want, got) { t.Fatalf("expected: %v, got: %v", tc.want, got) } }) } }
  • 35. Unit Testing - Mocking type MyRepo interface { Get(ctx context.Context, id string) (interface{}, error) Update(ctx context.Context, model interface{}) (interface{}, error) } type MyRepoImpl struct { pg interface{} } func (m *MyRepoImpl) Get(ctx context.Context, id string) (interface{}, error) { panic("implement me") } func (m *MyRepoImpl) Update(ctx context.Context, model interface{}) (interface{}, error) { panic("implement me") } type MyRepoMock struct { MockGet func(ctx context.Context, id string) (interface{}, error) MockUpdate func(ctx context.Context, model interface{}) (interface{}, error) } func (a *MyRepoMock) Get(ctx context.Context, id string) (interface{}, error) { return a.MockGet(ctx, id) } func (a *MyRepoMock) Update(ctx context.Context, model interface{}) (interface{}, error) { return a.MockUpdate(ctx, model) } type MyService struct { myRepo MyRepo } func (s *MyService) DoSmt(ctx context.Context) error { // some logic... model, err := s.myRepo.Get(ctx, "123") if err != nil { return err } // some logic... }
  • 36. Context - WithValue func doSomething(ctx context.Context) { fmt.Printf("doSomething: myKey's value is %sn", ctx.Value("myKey")) } func main() { ctx := context.Background() ctx = context.WithValue(ctx, "myKey", "myValue") doSomething(ctx) } Output doSomething: myKey's value is myValue
  • 37. Context - WithCancel func doSomething(ctx context.Context) { ctx, cancelCtx := context.WithCancel(ctx) printCh := make(chan int) go doAnother(ctx, printCh) for num := 1; num <= 3; num++ { printCh <- num } cancelCtx() time.Sleep(100 * time.Millisecond) fmt.Printf("doSomething: finishedn") } func doAnother(ctx context.Context, printCh <-chan int) { for { select { case <-ctx.Done(): if err := ctx.Err(); err != nil { fmt.Printf("doAnother err: %sn", err) } fmt.Printf("doAnother: finishedn") return case num := <-printCh: fmt.Printf("doAnother: %dn", num) } } } Output doAnother: 1 doAnother: 2 doAnother: 3 doAnother err: context canceled doAnother: finished doSomething: finished
  • 38. Context – WithDeadline / WithTimeout const shortDuration = 1 * time.Millisecond func main() { d := time.Now().Add(shortDuration) ctx, cancel := context.WithDeadline(context.Background(), d) // Even though ctx will be expired, it is good practice to call its // cancellation function in any case. Failure to do so may keep the // context and its parent alive longer than necessary. defer cancel() select { case <-time.After(1 * time.Second): fmt.Println("overslept") case <-ctx.Done(): fmt.Println(ctx.Err()) } } Output: context deadline exceeded
  • 39. Context – OpenTelemetry OpenTelemetry also relies heavily on context for what is called Context Propagation. That is a way to tied up requests happening in different systems. The way to implement that is to Inject span information into the context you are going to send as part of the protocol you are using (HTTP or gRPC, for instance). On the other service you need to Extract the span information out of the context.
  • 40. Concurrency model According to Rob Pike, concurrency is the composition of independently executing computations, and concurrency is not parallelism: concurrency is about dealing with lots of things at once, but parallelism is about doing lots of things at once. Concurrency is about structure, parallelism is about execution, concurrency provides a way to structure a solution to solve a problem that may (but not necessarily) be parallelizable. If you have only one processor, your program can still be concurrent, but it cannot be parallel. On the other hand, a well-written concurrent program might run efficiently in parallel on a multiprocessor.
  • 41. Goroutine A goroutine is a lightweight thread(faster context switching & smaller size(2kB) compared with OS thread(1MB)) managed by the Go runtime. It has its own call stack, which grows and shrinks as required. It's very cheap. It's practical to have thousands, even hundreds of thousands of goroutines. It's not a thread! There might be only one thread in a program with thousands of goroutines. Instead, goroutines are multiplexed dynamically onto threads as needed to keep all the goroutines running. But if you think of it as a very cheap thread, you won't be far off. The GOMAXPROCS variable limits the number of operating system threads that can execute user-level Go code simultaneously. There is no limit to the number of threads that can be blocked in system calls on behalf of Go code; those do not count against the GOMAXPROCS limit. This package's GOMAXPROCS function queries and changes the limit. func say(s string) { for i := 0; i < 5; i++ { time.Sleep(100 * time.Millisecond) fmt.Println(s) } } func main() { go say("world") say("hello") }
  • 42. Channels Don't communicate by sharing memory, share memory by communicating! A channel in Go provides a connection between two goroutines, allowing them to communicate. // Declaring and initializing. var c chan int c = make(chan int) // or c := make(chan int) // Sending on a channel. c <- 1 // Receiving from a channel. // The "arrow" indicates the direction of data flow. value = <-c
  • 43. Channels Buffered Channels - Sends to a buffered channel block only when the buffer is full. Receives block when the buffer is empty. ch := make(chan int, 100) A sender can close a channel to indicate that no more values will be sent. Only the sender should close a channel, never the receiver! Closing is only necessary when the receiver must be told there are no more values coming! v, ok := <-ch func fibonacci(n int, c chan int) { x, y := 0, 1 for i := 0; i < n; i++ { c <- x x, y = y, x+y } close(c) } func main() { c := make(chan int, 10) go fibonacci(cap(c), c) for i := range c { fmt.Println(i) } }
  • 44. Channels Channel Directions- When using channels as function parameters, you can specify if a channel is meant to only send or receive values. This specificity increases the type-safety of the program. This ping function only accepts a channel for sending values. It would be a compile-time error to try to receive on this channel. The pong function accepts one channel for receives (pings) and a second for sends (pongs). func ping(pings chan<- string, msg string) { pings <- msg } func pong(pings <-chan string, pongs chan<- string) { msg := <-pings pongs <- msg } func main() { pings := make(chan string, 1) pongs := make(chan string, 1) ping(pings, "passed message") pong(pings, pongs) fmt.Println(<-pongs) }
  • 45. Channels - Select The select statement lets a goroutine wait on multiple communication operations. A select blocks until one of its cases can run, then it executes that case. It chooses one at random if multiple are ready. A default clause, if present, executes immediately if no channel is ready. select { case v1 := <-c1: fmt.Printf("received %v from c1n", v1) case v2 := <-c2: fmt.Printf("received %v from c2n", v1) case c3 <- 23: fmt.Printf("sent %v to c3n", 23) default: fmt.Printf("no one was ready to communicaten") }
  • 46. Channels - Timeout using select The time.After function returns a channel that blocks for the specified duration. After the interval, the channel delivers the current time, once. func main() { c := boring("Joe") for { select { case s := <-c: fmt.Println(s) case <-time.After(1 * time.Second): fmt.Println("You're too slow.") return } } }
  • 47. WaitGroups To wait for multiple goroutines to finish, we can use a wait group. func worker(id int) { fmt.Printf("Worker %d startingn", id) time.Sleep(time.Second) fmt.Printf("Worker %d donen", id) } func main() { var wg sync.WaitGroup for i := 1; i <= 5; i++ { wg.Add(1) go func(i int) { defer wg.Done() worker(i) }(i) } wg.Wait() }
  • 48. sync.Mutex We've seen how channels are great for communication among goroutines. But what if we don't need communication? What if we just want to make sure only one goroutine can access a variable at a time to avoid conflicts? This concept is called mutual exclusion, and the conventional name for the data structure that provides it is mutex. // SafeCounter is safe to use concurrently. type SafeCounter struct { mu sync.Mutex v map[string]int } // Inc increments the counter for the given key. func (c *SafeCounter) Inc(key string) { c.mu.Lock() // Lock so only one goroutine at a time can access the map c.v. c.v[key]++ c.mu.Unlock() } // Value returns the current value of the counter for the given key. func (c *SafeCounter) Value(key string) int { c.mu.Lock() // Lock so only one goroutine at a time can access the map c.v. defer c.mu.Unlock() return c.v[key] } func main() { c := SafeCounter{v: make(map[string]int)} for i := 0; i < 1000; i++ { go c.Inc("somekey") } time.Sleep(time.Second) fmt.Println(c.Value("somekey")) }
  • 49. Atomic Counters Here we’ll look at using the sync/atomic package for atomic counters accessed by multiple goroutines. func main() { var ops uint64 var wg sync.WaitGroup for i := 0; i < 50; i++ { wg.Add(1) go func() { for c := 0; c < 1000; c++ { atomic.AddUint64(&ops, 1) } wg.Done() }() } wg.Wait() fmt.Println("ops:", ops) }
  • 50. Go Fuzzing Go supports fuzzing in its standard toolchain beginning in Go 1.18. Fuzzing is a type of automated testing which continuously manipulates inputs to a program to find bugs. Go fuzzing uses coverage guidance to intelligently walk through the code being fuzzed to find and report failures to the user. Since it can reach edge cases which humans often miss, fuzz testing can be particularly valuable for finding security exploits and vulnerabilities.
  • 51. Best practices - Do not ignore errors. - Handle error only once. - Use Channels for goroutines comunication. - Return an error instead of using Panic (especially in libs). - Return an Error interface instead of a custom error struct. - Do not be lazy; Use interfaces! - Do not pass function arguments on context.Context. - Pass context.Context as the first argument to a function. - Do not use package level vars & func init(magic is bad; global state is magic). - Handle errors in deferred functions. - When choosing a third-party lib make sure it is following the GO Standard lib(context.Context, net/http…). - Avoid Reflection.
  • 52. What is the output of this program? var WhatIsThe = AnswerToLife() func AnswerToLife() int { println("Hello from AnswerToLife") return 42 } func init() { println("Hello from init") WhatIsThe = 0 } func main() { println("Hello from main") if WhatIsThe == 0 { println("It's all a lie.") } } Hello from AnswerToLife Hello from init Hello from main It's all a lie. Do not use package level vars & func init! magic is bad; global state is magic!
  • 53. What would we like Go to be better at? • Error handling (& stack trace). • Function Overloading and Default Values for Arguments. • Extension funcs. • Get Goroutine “result” – like Kotlin Coroutines: • Null safety • Define Enum type • Functional programming • Macros / inline function fun String.removeFirstLastChar(): String = this.substring(1, this.length - 1) val result = "Hello Everyone".removeFirstLastChar() val x string? x?.toLowercase() val deferred: Deferred<String> = async { "Hello World" } val result = deferred.await()
  • 54. Usefull Resources • https://go.dev/learn/ • https://go.dev/doc/effective_go • https://gobyexample.com/ • https://go.dev/ref/spec • https://peter.bourgon.org/blog/2017/06/09/theory-of-modern-go.html • https://dave.cheney.net/ • https://github.com/avelino/awesome-go • https://pkg.go.dev/cmd/go • Google I/O 2012 - Go Concurrency Patterns
  • 55. Until the next time… Guy Komari