~hedy/goplay

4434d0f2e1b13683d1d24658f1b600fb17abdd9a — Hedy Li 3 years ago
add everything
A  => go.mod +5 -0
@@ 1,5 @@
module go-play

go 1.16

require golang.org/x/tour v0.1.0

A  => go.sum +2 -0
@@ 1,2 @@
golang.org/x/tour v0.1.0 h1:OWzbINRoGf1wwBhKdFDpYwM88NM0d1SL/Nj6PagS6YE=
golang.org/x/tour v0.1.0/go.mod h1:DUZC6G8mR1AXgXy73r8qt/G5RsefKIlSj6jBMc8b9Wc=

A  => misc/factorial.go +24 -0
@@ 1,24 @@
/* factorial recursion and loop */

package misc

import "fmt"

func factorial(n int) int {
	// recursion
	if n == 0 || n == 1 { return 1  }; return n * factorial(n-1)
}

func factorialLoop(n int) int {
	// loop
	result := 1
	for n>=1 {
		result *= n; n--
	}
	return result
}

func main() {
	fmt.Println(factorial(5))
	fmt.Println(factorialLoop(5))
}

A  => tour/concurrency/10_webCrawler.go +102 -0
@@ 1,102 @@
// Crawl through fetcher map asynchronosly (?) and avoiding fetching duplicates

package concurrency

import (
	"fmt"
	"time"
)


// Crawl uses fetcher to recursively crawl
// pages starting with url, to a maximum of depth.
func Crawl(url string, depth int, fetcher Fetcher) {
	for _, v := range stored {
		if v == url { return  }
	}
	stored = append(stored, url)
	if depth <= 0 {
		return
	}
	body, urls, err := fetcher.Fetch(url)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Printf("found: %s %q\n", url, body)
	//done <- true
	for _, u := range urls {
		go Crawl(u, depth-1, fetcher)
	}
	return
}

func main() {
	Crawl("https://golang.org/", 4, fetcher)
	//<-done
	time.Sleep(time.Second)
}


// ----------------- storage stuff -----------------

var stored []string // fetched urls
//var done chan bool


// ----------------- fetcher stuff -----------------

// fakeFetcher is Fetcher that returns canned results.
type fakeFetcher map[string]*fakeResult

type fakeResult struct {
	body string
	urls []string
}

type Fetcher interface {
	// Fetch returns the body of URL and
	// a slice of URLs found on that page.
	Fetch(url string) (body string, urls []string, err error)
}

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{
	"https://golang.org/": &fakeResult{
	"The Go Programming Language",
	[]string{
		"https://golang.org/pkg/",
		"https://golang.org/cmd/",
	},
},
"https://golang.org/pkg/": &fakeResult{
"Packages",
[]string{
	"https://golang.org/",
	"https://golang.org/cmd/",
	"https://golang.org/pkg/fmt/",
	"https://golang.org/pkg/os/",
},
																																},
																																"https://golang.org/pkg/fmt/": &fakeResult{
																																"Package fmt",
																																[]string{
																																	"https://golang.org/",
																																	"https://golang.org/pkg/",
																																},
																															},
																															"https://golang.org/pkg/os/": &fakeResult{
																															"Package os",
																															[]string{
																																"https://golang.org/",
																																"https://golang.org/pkg/",
																															},
																														},
																													}

A  => tour/methods/09_interfaces.go +41 -0
@@ 1,41 @@
/*
# Interfaces

https://tour.golang.org/methods/9
*/

package methods

import (
	"fmt"
	"strings"
)

type Speaker interface {
	speak() string
}

// *********************************

func main() {
	var s Speaker
	r := Dog{"Roddy", "Brown", []string{"im created!", "im a doggy!"}}

	s = &r

	fmt.Println(r.name, "says", s.speak())
	fmt.Println("So far", r.name, "had said:\n -", strings.Join(r.speech, "\n - "))
	fmt.Println(r.name, "speaks again!", r.speak())
}

// *********************************

type Dog struct {
	name, color string
	speech      []string
}

func (d *Dog) speak() string {
	d.speech = append(d.speech, "woof")
	return "woof"
}

A  => tour/methods/14_emptyInterface.go +22 -0
@@ 1,22 @@
/*
# Empty interface

https://tour.golang.org/methods/14
*/

package methods

import (
	"fmt"
)

func main() {
	typePrint("hi")
}

// Prints argument type to stderr
// then prints the argument to stdout with newline
func typePrint(i interface{}) {
	print(fmt.Sprintf("%T", i) + "\n")
	fmt.Println(i)
}

A  => tour/methods/16_typeSwitches.go +33 -0
@@ 1,33 @@
/* type switches https://tour.golang.org/methods/16 */

package methods

import "fmt"

func tryType(i interface{}) {
	switch v := i.(type) {
	case int:
		fmt.Printf("Twice %v is %v\n", v, v*2)
	case float64:
		fmt.Printf("%v rounded to 2dp is: %.2f\n", v, v)
	case string:
		fmt.Printf("%q is %v bytes long\n", v, len(v)) // %q = quoted
	case bool:
		fmt.Printf("!%v is %v\n", v, !v)
	case []int:
		fmt.Printf("int slice has capacity %v and length %v\n", cap(v), len(v))
	case map[string]int:
		fmt.Printf("Map with key as string, value as int has %v items in it\n", len(v))
	default:
		fmt.Printf("Type %T with syntax %#v unknown!\n", v, v)
	}
}

func main() {
	tryType(21)
	tryType("hello")
	tryType(true)
	tryType(2.1313)
	tryType(make([]int, 2))
	tryType(make(map[string]int))
}

A  => tour/methods/18_stringers.go +29 -0
@@ 1,29 @@
/* Stringers (exercise) https://tour.golang.org/methods/18 */

package methods

import (
	"fmt"
	"strings"
)

type IPAddr [4]byte

func (ip IPAddr) String() string {
	var ipStr []string
	for _, v := range ip { // array byte to string
		// not sure if there's a better way for this than fmt.Sprintf
		ipStr = append(ipStr, fmt.Sprintf("%v", v))
	}
	return strings.Join(ipStr, ".")
}

func main() {
	hosts := map[string]IPAddr{
		"loopback":  {127, 0, 0, 1},
		"googleDNS": {8, 8, 8, 8},
	}
	for name, ip := range hosts { // print "name: ip"
		fmt.Printf("%v: %v\n", name, ip)
	}
}

A  => tour/methods/19_errors.go +32 -0
@@ 1,32 @@
/* Errors https://tour.golang.org/methods/19 */

package methods

import (
	"fmt"
)

type ZeroError struct {
	TryInstead int
	Reason     string
}

func (e *ZeroError) Error() string {
	return fmt.Sprintln(
		"Zero not allowed, because",
		e.Reason+".", "Maybe try",
		e.TryInstead, "instead.")
	}

	func minus1(n int) (int, error) {
		if n != 0 {
			return n - 1, nil
		}
		return 0, &ZeroError{5, "I said so"}
	}

	func main() {
		if _, err := minus1(0); err != nil {
			panic(err)
		}
	}

A  => tour/methods/22_AReader.go +23 -0
@@ 1,23 @@
// Readers Exercise - A reader type that emits an infinite stream of 'A'
// https://tour.golang.org/methods/22

package methods

import "golang.org/x/tour/reader"

type MyReader struct{}

// Read just fills b with 'A' and yeah, that's all it does
// honestly I didn't know changing the value of b would actually
// change it (I thought you'd have to use pointers?) but it did
// pass the test so ok!
func (MyReader) Read(b []byte) (int, error) {
	for i := range b {
		b[i] = 'A'
	}
	return len(b), nil
}

func main() {
	reader.Validate(MyReader{})
}

A  => tour/methods/23_rot13Reader.go +94 -0
@@ 1,94 @@
// rot13Reader Exercise
//
// A io.Reader that encrypts or unencrypts its io.Reader contents
// https://tour.golang.org/methods/23
//
// > Implement a rot13Reader that implements io.Reader and reads
// > from an io.Reader, modifying the stream by applying the
// > rot13 substitution cipher to all alphabetical characters.
//
// rot13 is literally caesar cipher but with key=13, this just makes
// it so that encryption and decryption is the same because:
// len(letters) / 2 = 13.
//
// Check out rot13 wikipedia for more info

package methods

import (
	"io"
	"os"
	"strings"
	"unicode"
)

var letters string = "abcdefghigklmnopqrstuvwxyz"

type rot13Reader struct {
	r io.Reader

	prevRune int // I have no idea how r.prevRune and r.i work together but
	// this strategy is present everywhere in standard libs and
	// the program gives no output if I don't do this.

	i int64  // read index
	o string // unencrypted text
}

func (r rot13Reader) Read(b []byte) (n int, err error) {
	// Read the crypt text
	readByte := make([]byte, 1)
	n, err = r.r.Read(readByte)
	// Exit immediately if there's no more to read
	if err == io.EOF {
		return
	}

	// Prepare for decryption
	oneByte := readByte[0]
	up := false

	// Only do the rot13 if the thing is an actual letter
	if unicode.IsLetter(rune(oneByte)) {
		// Easier to do string manipulation with strings pkg
		oneStr := string(oneByte)

		// Lower the string for string indexing, but keep the case later
		if strings.ToUpper(oneStr) == oneStr {
			up = true
			oneStr = strings.ToLower(oneStr)
		}

		index := strings.Index(letters, oneStr) + 13
		if index > 25 {
			index = index % 26
		} // Wrap around
		letter := []rune(letters)[index] // Rotated/result letter
		if up {                          // Preserve original case
			letter = []rune(strings.ToUpper(string(letter)))[0]
		}

		oneByte = byte(letter)
	}

	// This is such an ugly hack as I think of it, but this is just to replace the
	// r.s thingy in strings.Reader implementation (as well as in bytes pkg)
	r.o += string(oneByte)

	// ---- Begin some random copied shit ----
	if r.i >= int64(len(r.o)) { // As I said above I have no idea how this works
		return 0, io.EOF
	}
	r.prevRune = -1
	n = copy(b, r.o[r.i:])
	r.i += int64(n)
	// ----  End some random copied shit  ----
	return
}

func main() {
	s := strings.NewReader("Lbh penpxrq gur pbqr!") // => You cracked the code!
	// TBH I don't even know if these default values I gave are ok, it works, so yeah.
	r := rot13Reader{s, 0, 0, ""}
	io.Copy(os.Stdout, &r)
}

A  => tour/methods/25_imageInterface.go +37 -0
@@ 1,37 @@
// implementing Image interface like the Bluescale Pic generator for slices exercise
// https://tour.golang.org/methods/25 (the other pic generator ^ was /moretypes/18)
//
// Output: https://hedy.smol.pub/imageInterface.png

package methods

import (
	"golang.org/x/tour/pic"
	"image/color"
	"image"
)

type Image struct{}

func (i Image) ColorModel() color.Model {
	return color.RGBAModel
}

func (i Image) Bounds() image.Rectangle {
	return image.Rect(0, 0, 150, 150)
}

func (i Image) At(x, y int) color.Color {
	var r, g, b, a int
	// nothing fancy like 2^((x-y)/(x+3)^x)^x or something lol
	r = 2^x+y // but this still produces a somewhat weird image 0_0
	g = 70
	b = 200
	a = 200
	return color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)}
}

func main() {
	m := Image{}
	pic.ShowImage(m)
}

A  => tour/moretypes/18_slicesBluescalePic.go +21 -0
@@ 1,21 @@
/* https://tour.golang.org/moretypes/18 */

package moretypes

import "golang.org/x/tour/pic"

func Pic(dx, dy int) [][]uint8 {
	var a [][]uint8
	var b []uint8
	for i := range make([]uint8, 256) {
		for j := range make([]uint8, 256) {
			b = append(b, uint8(2^(i-j)))
		}
		a = append(a, b)
	}
	return a[:dy][:dx]
}

func main() {
	pic.Show(Pic)
}

A  => tour/moretypes/23_wordCount.go +33 -0
@@ 1,33 @@
/* https://tour.golang.org/moretypes/23 */

package moretypes

import (
	"golang.org/x/tour/wc"
	"strings"
	//"fmt"
)

func itemCount(a []string, sub string) int {
	var count int
	for _, v := range a {
		if v == sub {
			count++
		}
	}
	return count
}

func WordCount(s string) map[string]int {
	m := make(map[string]int)
	strs := strings.Fields(s)
	for _, v := range strs {
		m[v] = itemCount(strs, v)
	}
	return m
}

func main() {
	wc.Test(WordCount)
	//fmt.Println(WordCount("a a b"))
}

A  => tour/moretypes/25_highOrderFunc.go +22 -0
@@ 1,22 @@
// func that returns a func
// https://tour.golang.org/moretypes/25
// Classic example when learning high order funcs

package moretypes

import (
	"fmt"
)

func makeAdder(addWhat int) func(a int) int {
	return func(a int) int {
		return a + addWhat
	}
}

func main() {
	add2 := makeAdder(2)
	fmt.Println(add2(2)) // 2+2
	add1 := makeAdder(1)
	fmt.Println(add1(3)) // 3+1
}

A  => tour/moretypes/26_fibonacciClosure.go +23 -0
@@ 1,23 @@
/* https://tour.golang.org/moretypes/26 */

package moretypes

import "fmt"

// fibonacci is a function that returns a function that returns an int.
// It's closure, duh
func fibonacci() func() int {
	a, b := 0, 0
	return func() int {
		a, b = b, a+b
		if b == 0 { a++  }
		return b
	}
}

func main() {
	f := fibonacci()
	for i := 0; i < 7; i++ {
		fmt.Println(f())
	}
}