Skip to content

Instantly share code, notes, and snippets.

@danielemoraschi
Last active September 22, 2016 00:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danielemoraschi/742dffb417944288c9d17170b3985d9a to your computer and use it in GitHub Desktop.
Save danielemoraschi/742dffb417944288c9d17170b3985d9a to your computer and use it in GitHub Desktop.
A Tour of Go - Exercises

Excercise files in GO

package main
import (
"fmt"
"sync"
"net/url"
)
var mu = &sync.Mutex{}
func main() {
var wg sync.WaitGroup
urlToVisit := "http://golang.org/"
uniqueVisitPolicy := UniqueUrlPolicyFactory()
sameDomainPolicy := SameDomainPolicyFactory(urlToVisit)
policies := make([]PolicyInterface, 0)
policies = append(policies, uniqueVisitPolicy)
policies = append(policies, sameDomainPolicy)
var urlList []string
urlList = append(urlList, urlToVisit)
wg.Add(1)
Crawl(&urlList, &wg, urlToVisit, 2, fetcher, policies)
wg.Wait()
urlList = removeDuplicatesUnordered(urlList)
fmt.Println("ALL: %s", urlList)
}
func removeDuplicatesUnordered(elements []string) []string {
encountered := map[string]bool{}
// Create a map of all unique elements.
for v := range elements {
encountered[elements[v]] = true
}
// Place all keys from the map into a slice.
result := []string{}
for key := range encountered {
result = append(result, key)
}
return result
}
// CRAWLER ---------------------------------------------------------------------
// Crawl uses fetcher to recursively crawl
// pages starting with url, to a maximum of depth.
func Crawl(urlsList *[]string, wg *sync.WaitGroup, url string, depth int,
fetcher FetcherInterface, policies []PolicyInterface) {
defer wg.Done()
UrlAllowedByPolicies(policies, url)
//fmt.Printf("Visiting: %s\n", url)
_, urls, err := fetcher.Fetch(url)
if err != nil {
fmt.Println(err)
return
}
//fmt.Printf("Found: %s %q\n", urls, body)
mu.Lock()
*urlsList = append(*urlsList, urls...)
mu.Unlock()
if depth <= 0 {
return
}
for _, u := range urls {
if UrlAllowedByPolicies(policies, u) {
wg.Add(1)
go Crawl(urlsList, wg, u, depth-1, fetcher, policies)
}
}
return
}
// POLICIES --------------------------------------------------------------------
type PolicyInterface interface {
// Fetch returns the body of URL and
// a slice of URLs found on that page.
ShouldVisit(url string) bool
}
func UrlAllowedByPolicies(policies []PolicyInterface, url string) bool {
for i := 0; i < len(policies); i++ {
if ! policies[i].ShouldVisit(url) {
return false
}
}
return true
}
type UniqueUrlPolicy struct {
sync.Mutex
urlMap map[string]bool
PolicyInterface
}
func (p UniqueUrlPolicy) ShouldVisit(url string) bool {
p.Lock()
_, ok := p.urlMap[url]
p.urlMap[url] = true
p.Unlock()
return !ok
}
func UniqueUrlPolicyFactory() PolicyInterface {
p := UniqueUrlPolicy{urlMap: make(map[string]bool)}
return p
}
type SameDomainPolicy struct {
baseURL *url.URL
PolicyInterface
}
func (p SameDomainPolicy) ShouldVisit(u string) bool {
urlToCheck, err := url.ParseRequestURI(u)
if err != nil {
panic(err)
}
ret := p.baseURL.Host == urlToCheck.Host
//fmt.Printf("Checking: %s vs %s\n", p.baseURL.Host, urlToCheck.Host)
return ret
}
func SameDomainPolicyFactory(baseUrl string) PolicyInterface {
URL, err := url.ParseRequestURI(baseUrl)
if err != nil {
panic(err)
}
p := SameDomainPolicy{baseURL: URL}
return p
}
// FETCHERS --------------------------------------------------------------------
type FetcherInterface interface {
// Fetch returns the body of URL and
// a slice of URLs found on that page.
Fetch(url string) (string, []string, error)
}
// fakeFetcher is Fetcher that returns canned results.
type fakeFetcher map[string]*fakeResult
type fakeResult struct {
body string
urls []string
}
func (f fakeFetcher) Fetch(url string) (string, []string, error) {
if res, ok := f[url]; ok {
return res.body, res.urls, nil
}
return "", nil, fmt.Errorf("Not found: %s", url)
}
// fetcher is a populated fakeFetcher.
var fetcher = fakeFetcher{
"http://golang.org/": &fakeResult{
"The Go Programming Language",
[]string{
"http://golang.org/pkg/",
"http://golang.org/cmd/",
},
},
"http://golang.org/pkg/": &fakeResult{
"Packages",
[]string{
"http://golang.org/",
"http://golang.org/cmd/",
"http://golang.org/pkg/fmt/",
"http://golang.org/pkg/os/",
},
},
"http://golang.org/pkg/fmt/": &fakeResult{
"Package fmt",
[]string{
"http://golang.org/",
"http://golang.org/pkg/",
},
},
"http://golang.org/pkg/os/": &fakeResult{
"Package os",
[]string{
"http://go.com/",
"http://golang.org/",
"http://golang.org/pkg/",
},
},
"http://go.com/": &fakeResult{
"Go Base",
[]string{
"http://go.com/re1",
"http://go.com/re2",
},
},
"http://go.com/re1": &fakeResult{
"Go R1",
[]string{
"http://golang.org/",
},
},
}
package main
import (
"fmt"
"math"
)
func Sqrt(x float64) (float64, error) {
if x < 0 {
return x, ErrNegativeSqrt(x)
}
return math.Sqrt(x), nil
}
type ErrNegativeSqrt float64
func (e ErrNegativeSqrt) Error() string {
return fmt.Sprintf("Cannot Sqrt negative number: %f", e)
}
func main() {
fmt.Println(Sqrt(2))
fmt.Println(Sqrt(-2))
}
package main
import "fmt"
// 0, 1, 1, 2, 3, 5, 8, 13, 21, 34
func fibonacci() func() int {
current, next := 0, 1
return func() int {
ret := current
current, next = next, current + next
return ret
}
}
func main() {
f := fibonacci()
for i := 0; i < 10; i++ {
fmt.Println(f())
}
}
package main
import (
"fmt"
"math"
)
func Round(f float64, places int) (float64) {
shift := math.Pow(10, float64(places))
return math.Floor(f * shift + .5) / shift;
}
func Sqrt(x float64) float64 {
z := 1.0
for i := 0.; i < 500; i++ {
z = z - (z * z - x) / (2 * z)
}
return z
}
func main() {
for i := 0.; i < 100; i++ {
fmt.Println("Fake for", i, ":", Round(Sqrt(i), 5))
fmt.Println("Real for", i, ":", Round(math.Sqrt(i), 5))
}
}
package main
import (
"golang.org/x/tour/wc"
"strings"
)
func WordCount(s string) map[string]int {
ret := make(map[string]int)
words := strings.Fields(s)
for _, word := range words {
ret[word] = ret[word] + 1
}
return ret
}
func main() {
wc.Test(WordCount)
}
package main
import (
"golang.org/x/tour/pic"
)
func Pic(dx, dy int) [][]uint8 {
vs := make([][]uint8, dy)
for y := 0; y < dy; y++ {
vs[y] = make([]uint8, dx)
for x := 0; x < dx; x++ {
vs[y][x] = uint8( y^x )
}
}
return vs
}
func main() {
pic.Show(Pic)
}
package main
import "golang.org/x/tour/pic"
import (
"image/color"
"image"
)
type Image struct{}
func (i Image) ColorModel() color.Model {
return color.RGBA64Model
}
func (i Image) Bounds() image.Rectangle {
return image.Rect(0, 0, 50, 50)
}
func (i Image) At(x, y int) color.Color {
return color.RGBA{20, 60, 30, 0}
}
func main() {
m := Image{}
pic.ShowImage(m)
}
package main
import "fmt"
type SimCardInterface interface {
GetNumber() string
}
type SimCard struct {
number string
}
func (d SimCard) GetNumber() string {
return d.number
}
type PhoneInterface interface {
Call() string
}
type Phone struct { }
func (p Phone) Call() string {
return "Ring Ring"
}
type CameraInterface interface {
TakePicture() string
}
type Camera struct { }
func (c Camera) TakePicture() string {
return "Click"
}
type SmartPhoneInterface interface {
SimCardInterface
PhoneInterface
CameraInterface
}
// multiple inheritance
type SmartPhone struct {
SimCard //has anonymous sim card
Camera //has anonymous camera
Phone //has anonymous phone
}
func main() {
var phone SmartPhoneInterface = SmartPhone{
SimCard: SimCard{number: "+44770000000"},
}
fmt.Println("Our new SmartPhone exhibits multiple behaviors ...")
fmt.Println("It has a telephone number: ", phone.GetNumber())
fmt.Println("It can take a picture: ", phone.TakePicture())
fmt.Println("It can also make calls: ", phone.Call())
}
package main
import "fmt"
type Store interface {
GetLocation() string
String() string
}
type Tesco struct {
location string
}
func (t *Tesco) GetLocation() string {
return t.location
}
func (t *Tesco) String() string {
return fmt.Sprintf("Location \"%v\"", t.GetLocation())
}
func main() {
var store Store = &Tesco{"London"}
fmt.Println(store)
}
package main
import (
"fmt"
)
func MaxProfit(list []int) int {
max, length := -1, len(list)
for i:=0; i<length; i++ {
for j:=i+1; j<length; j++ {
r := list[j] - list[i]
if r > 0 && r > max {
max = r
}
}
}
return max
}
func main() {
list := []int{45, 24, 35, 31, 40, 38, 11, }
fmt.Printf("MAx profit %v", MaxProfit(list))
}
package main
import "fmt"
func factorial(x int) (result int) {
if x == 0 {
result = 1
} else {
result = x * factorial(x-1)
}
return
}
func permute(pos int, len int, set *[]int) {
if pos == len {
fmt.Printf("Perm: %v\n", set)
return
}
for i := pos; i < len; i++ {
(*set)[pos], (*set)[i] = (*set)[i], (*set)[pos]
permute(pos+1, len, set)
(*set)[pos], (*set)[i] = (*set)[i], (*set)[pos]
}
}
func main() {
set := []int{1, 2, 3, }
repeat := factorial(len(set))
fmt.Printf("Tot permutations: %v\n", repeat)
permute(0, len(set), &set)
fmt.Printf("Tot permutations: %v\n", repeat)
}
package main
import (
"fmt"
)
func fib(num int) int {
if (num == 0 || num == 1) {
return num
}
ret := fib(num-1) + fib(num-2)
return ret
}
func fib2() func() int {
x, p1, p2 := 0, 1, 1
return func() int {
if (x == 0 || x == 1) {
x++
}
x++
}
}
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() {
f := fib2()
for i := 0; i < 10; i++ {
fmt.Println(f())
}
fmt.Println("----------")
for i := 0; i < 10; i++ {
fmt.Println(fib(i))
}
fmt.Println("----------")
c := make(chan int, 10)
go fibonacci(cap(c), c)
for i := range c {
fmt.Println(i)
}
}
package main
import (
"io"
"os"
"strings"
)
func rot13(p []byte) []byte {
for i := 0; i < len(p); i++ {
if (p[i] >= 'A' && p[i] < 'N') || (p[i] >='a' && p[i] < 'n') {
p[i] += 13
} else if (p[i] > 'M' && p[i] <= 'Z') || (p[i] > 'm' && p[i] <= 'z'){
p[i] -= 13
}
}
return p
}
type rot13Reader struct {
r io.Reader
}
func (rot rot13Reader) Read(b []byte) (n int, err error) {
n, e := rot.r.Read(b)
rot13(b)
return len(b), e
}
func main() {
s := strings.NewReader("Lbh penpxrq gur pbqr!")
r := rot13Reader{s}
io.Copy(os.Stdout, &r)
}
package main
import "fmt"
type IPAddr [4]byte
func (t IPAddr) String() string {
return fmt.Sprintf("%d.%d.%d.%d", t[0], t[1], t[2], t[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)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment