Skip to content

Instantly share code, notes, and snippets.

@marius92mc
Last active October 2, 2018 21:30
Show Gist options
  • Save marius92mc/c8009095d421492b71570ccb0e2fa11f to your computer and use it in GitHub Desktop.
Save marius92mc/c8009095d421492b71570ccb0e2fa11f to your computer and use it in GitHub Desktop.
/*
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.
// -----------------------------------------------
@marius92mc
Copy link
Author

marius92mc commented Jul 15, 2018

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.

@marius92mc
Copy link
Author

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