Last active
October 2, 2018 21:30
-
-
Save marius92mc/c8009095d421492b71570ccb0e2fa11f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
IMPORTANT! | |
The rule about pointers vs. values for receivers is that | |
value methods can be invoked on pointers AND values, but | |
pointer methods can only be invoked on pointers. | |
`make([]int, 10, 100)` | |
// It allocates an array of 100 ints and then creates a slice structure with length 10 and a capacity of 100 | |
// pointing at the first 10 elements of the array. | |
// (When making a slice, the capacity can be omitted.) | |
// In contrast, `new([]int)` returns a pointer to a newly allocated, zeroed slice structure, that is, | |
// a pointer to a nil slice value. | |
// The expressions new(File) and &File{} are equivalent. | |
Remember that `make` applies only to maps, slices and channels and does not return a pointer. | |
To obtain an explicit pointer allocate with `new` or take the address of a variable explicitly. | |
Slices hold references to an underlying array, and if you assign one slice to another, both refer to the same array. | |
If a function takes a slice argument, changes it makes to the elements of the slice will be visible to the caller, | |
analogous to passing a pointer to the underlying array. | |
Maps | |
The key can be of any type for which the equality operator is defined, | |
such as integers, floating point and complex numbers, strings, pointers, | |
interfaces (as long as the dynamic type supports equality), structs and arrays. | |
Slices cannot be used as map keys, because equality is not defined on them. | |
Like slices, maps hold references to an underlying data structure. | |
If you pass a map to a function that changes the contents of the map, the changes will be visible in the caller. | |
*/ | |
package main | |
import ( | |
"golang.org/x/tour/wc" | |
"strings" | |
) | |
func WordCount(s string) map[string]int { | |
var hashTable map[string]int = make(map[string]int) | |
for _, word := range strings.Fields(s) { | |
if _, present := hashTable[word]; !present { | |
hashTable[word] = 1 | |
} else { | |
hashTable[word] += 1 | |
} | |
} | |
// delete(hashTable, key) | |
return hashTable | |
} | |
func main() { | |
wc.Test(WordCount) | |
} | |
// ----------------------------------------------- | |
package main | |
import ( | |
"fmt" | |
) | |
func main() { | |
var timeZone map[string]int = map[string]int{ | |
"UTC": 1*60*60, | |
"EST": -5*60*60, | |
"CST": -6*60*60, | |
"MST": -7*60*60, | |
"PST": -8*60*60, | |
} | |
var key string = "UTC" | |
if value, present := timeZone[key]; present { | |
fmt.Println(value) | |
} | |
if _, present := timeZone["GMT"]; !present { | |
fmt.Println("GMT not present\n") | |
} | |
delete(timeZone, "PDT") // delete "PDT" key. It's safe to do this even if the key is already absent from the map. | |
type MyType struct { | |
a int | |
b float64 | |
c string | |
} | |
t := &MyType{a: 7, b: -2.35, c: "abc\tdef" } | |
fmt.Printf("%v\n", t) | |
fmt.Printf("%+v\n", t) | |
fmt.Printf("%#v\n", t) | |
fmt.Printf("%#v\n", timeZone) | |
} | |
/* | |
Output: | |
3600 | |
GMT not present | |
&{7 -2.35 abc def} | |
&{a:7 b:-2.35 c:abc def} | |
&main.MyType{a:7, b:-2.35, c:"abc\tdef"} | |
map[string]int{"UTC":3600, "EST":-18000, "CST":-21600, "MST":-25200, "PST":-28800} | |
*/ | |
// ----------------------------------------------- | |
package main | |
import "fmt" | |
func main() { | |
var s []int | |
printSlice(s) | |
// append works on nil slices. | |
s = append(s, 0) | |
printSlice(s) | |
// The slice grows as needed. | |
s = append(s, 1) | |
printSlice(s) | |
// We can add more than one element at a time. | |
s = append(s, 2, 3, 4) | |
printSlice(s) | |
} | |
func printSlice(s []int) { | |
fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s) | |
} | |
// ----------------------------------------------- | |
package main | |
import "fmt" | |
type IPAddr [4]byte | |
func (ip IPAddr) String() string { | |
return fmt.Sprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]) | |
} | |
func main() { | |
hosts := map[string]IPAddr{ | |
"loopback": {127, 0, 0, 1}, | |
"googleDNS": {8, 8, 8, 8}, | |
} | |
for name, ip := range hosts { | |
fmt.Printf("%v: %v\n", name, ip) | |
} | |
} | |
// ----------------------------------------------- | |
// Exercise errors. | |
package main | |
import ( | |
"fmt" | |
"math" | |
) | |
type ErrNegativeSqrt float64 | |
func (e ErrNegativeSqrt) Error() string { | |
return fmt.Sprintf("Cannot Sqrt negative number: %f", e) | |
} | |
const e float64 = 1e-8 // small delta | |
func Sqrt(x float64) (float64, error) { | |
if x < 0 { | |
return 0, ErrNegativeSqrt(x) | |
} | |
var z float64 = x // starting point | |
for { | |
new_z := z - ((z*z - x) / (2*z)) | |
if math.Abs(new_z - z) < e { | |
return new_z, nil | |
} | |
z = new_z | |
} | |
return z, nil | |
} | |
func main() { | |
fmt.Println(Sqrt(2)) | |
fmt.Println(Sqrt(-2)) | |
} | |
// ----------------------------------------------- | |
// https://github.com/luciotato/golang-notes/blob/master/OOP.md | |
package main | |
import ( | |
"fmt" | |
) | |
/* | |
class Animal | |
virtual abstract Speak() string | |
*/ | |
type Animal interface { | |
Speak() string | |
} | |
/* | |
class Dog | |
method Speak() string //non-virtual | |
return "Woof!" | |
Dog implements Animal interface. | |
*/ | |
type Dog struct { | |
Animal | |
} | |
func (d Dog) Speak() string { | |
return "Woof!" | |
} | |
/* | |
class Cat | |
method Speak() string //non-virtual | |
return "Meow!" | |
*/ | |
type Cat struct { | |
Animal | |
} | |
func (c Cat) Speak() string { | |
return "Meow!" | |
} | |
/* | |
class Llama | |
method Speak() string //non-virtual | |
return "LaLLamaQueLLama!" | |
*/ | |
type Llama struct { | |
Animal | |
} | |
func (l Llama) Speak() string { | |
return "LaLLamaQueLLama!" | |
} | |
/* | |
func main | |
var animals = [ Dog{}, Cat{}, Llama{} ] | |
for animal in animals | |
print animal.Speak() // method dispatch via jmp-table | |
*/ | |
func main() { | |
animals := []Animal{Dog{}, Cat{}, Llama{}} | |
for _, animal := range animals { | |
fmt.Println(animal.Speak()) // method dispatch via jmp-table | |
} | |
} | |
// ----------------------------------------------- | |
//class NamedObj | |
type NamedObj struct { | |
Name string | |
} | |
//method show | |
func (n NamedObj) show() { | |
Println(n.Name) // "n" is "this" | |
} | |
//class Rectangle | |
type Rectangle struct { | |
NamedObj //inheritance | |
Width, Height float64 | |
} | |
//override method show | |
func (r Rectangle) show() { | |
Println("Rectangle ", r.Name) // "r" is "this" | |
} | |
// ----------------------------------------------- | |
package main | |
import ( | |
"fmt" | |
"io" | |
"strings" | |
) | |
func main() { | |
r := strings.NewReader("Hello, Reader!") | |
b := make([]byte, 8) // b is a slice over an array with byte elements and len 8 | |
for { | |
n, err := r.Read(b) | |
fmt.Printf("n = %v err = %v b = %v\n", n, err, b) | |
fmt.Printf("b[:n] = %q\n", b[:n]) | |
if err == io.EOF { | |
break | |
} | |
} | |
} | |
// ----------------------------------------------- | |
// exercise-reader.go | |
package main | |
import "golang.org/x/tour/reader" | |
type MyReader struct{} | |
func (reader MyReader) Read(b []byte) (n int, e error) { | |
for i, _ := range b { | |
b[i] = 65 | |
} | |
return len(b), nil | |
} | |
func main() { | |
reader.Validate(MyReader{}) | |
} | |
// ----------------------------------------------- | |
package main | |
import ( | |
"fmt" | |
"sync" | |
"time" | |
) | |
// SafeCounter is safe to use concurrently. | |
type SafeCounter struct { | |
v map[string]int | |
mux sync.Mutex | |
} | |
// Inc increments the counter for the given key. | |
func (c *SafeCounter) Inc(key string) { | |
c.mux.Lock() | |
// Lock so only one goroutine at a time can access the map c.v. | |
c.v[key]++ | |
c.mux.Unlock() | |
} | |
// Value returns the current value of the counter for the given key. | |
func (c *SafeCounter) Value(key string) int { | |
c.mux.Lock() | |
// Lock so only one goroutine at a time can access the map c.v. | |
defer c.mux.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")) | |
} | |
// ----------------------------------------------- | |
func NewFile(fd int, name string) *File { | |
return &File{fd: fd, name: name} // The expressions new(File) and &File{} are equivalent. | |
} | |
// ----------------------------------------------- | |
func append(slice []T, elements ...T) []T | |
// What append does is append the elements to the end of the slice and return the result. | |
// The result needs to be returned because the underlying array may change. | |
//This simple example | |
x := []int{1,2,3} | |
x = append(x, 4, 5, 6) | |
fmt.Println(x) | |
// prints [1 2 3 4 5 6]. | |
// So append works a little like `Printf`, collecting an arbitrary number of arguments. | |
// But what if we wanted to append a slice to a slice? | |
// Easy: use ... at the call site. This snippet produces identical output to the one above. | |
x := []int{1,2,3} | |
y := []int{4,5,6} | |
x = append(x, y...) | |
fmt.Println(x) | |
// Without that ..., it wouldn't compile because the types would be wrong; y is not of type int. | |
// ----------------------------------------------- | |
// Since we can define a method for any type except pointers and interfaces, | |
// we can write a method for a function. The http package contains this code: | |
// The HandlerFunc type is an adapter to allow the use of | |
// ordinary functions as HTTP handlers. If f is a function | |
// with the appropriate signature, HandlerFunc(f) is a | |
// Handler object that calls f. | |
type HandlerFunc func(ResponseWriter, *Request) | |
// ServeHTTP calls f(w, req). | |
func (f HandlerFunc) ServeHTTP(w ResponseWriter, req *Request) { | |
f(w, req) | |
} | |
// ----------------------------------------------- | |
// https://golang.org/doc/effective_go.html#goroutines | |
c := make(chan int) // Allocate a channel. | |
// Start the sort in a goroutine; when it completes, signal on the channel. | |
go func() { | |
list.Sort() | |
c <- 1 // Send a signal; value does not matter. | |
}() | |
doSomethingForAWhile() | |
<- c // Wait for sort to finish; discard sent value. | |
// ----------------------------------------------- |
Go interfaces:
- terminology: A type implements an interface.
- heavily used
- define the behaviour
- a
struct
can implement an interface - it's an abstraction. It is also a type
- usually methods/functions receive interfaces and return structs
- when you implement a function/method and know the signature, by knowing the methods from that parameter that is an interface, you know with which methods you can work with inside your function/method for that parameter object.
Go tooling in action
https://youtu.be/uBjoTxosSys
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
A tour of Go
Effective Go
The Go Book http://www.golang-book.com/books/intro