add: io reader writer begins
This commit is contained in:
		
							
								
								
									
										21
									
								
								interfaces/14-io-reader/book.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								interfaces/14-io-reader/book.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | // For more tutorials: https://blog.learngoprogramming.com | ||||||
|  | // | ||||||
|  | // Copyright © 2018 Inanc Gumus | ||||||
|  | // Learn Go Programming Course | ||||||
|  | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ | ||||||
|  | // | ||||||
|  |  | ||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type book struct { | ||||||
|  | 	product | ||||||
|  | 	Published timestamp | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (b *book) String() string { | ||||||
|  | 	return fmt.Sprintf("%s - (%s)", &b.product, b.Published) | ||||||
|  | } | ||||||
							
								
								
									
										131
									
								
								interfaces/14-io-reader/database.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								interfaces/14-io-reader/database.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,131 @@ | |||||||
|  | // For more tutorials: https://blog.learngoprogramming.com | ||||||
|  | // | ||||||
|  | // Copyright © 2018 Inanc Gumus | ||||||
|  | // Learn Go Programming Course | ||||||
|  | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ | ||||||
|  | // | ||||||
|  |  | ||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"encoding/json" | ||||||
|  | 	"fmt" | ||||||
|  | 	"reflect" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type database struct { | ||||||
|  | 	list  *list | ||||||
|  | 	types map[string]item // the registry of the types | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // #v1 | ||||||
|  | // func (db *database) load(path string) error { | ||||||
|  | // 	data, err := ioutil.ReadFile(path) | ||||||
|  | // 	if err != nil { | ||||||
|  | // 		return err | ||||||
|  | // 	} | ||||||
|  | // 	return json.Unmarshal(data, db) | ||||||
|  | // } | ||||||
|  |  | ||||||
|  | // #v2 | ||||||
|  | // func (db *database) load(r io.Reader) error { | ||||||
|  | //  data, err := ioutil.ReadAll(r) | ||||||
|  | // 	if err != nil { | ||||||
|  | // 		return err | ||||||
|  | // 	} | ||||||
|  | // 	return json.Unmarshal(data, db) | ||||||
|  | // } | ||||||
|  |  | ||||||
|  | // #v3 | ||||||
|  | // TODO: use decoder | ||||||
|  |  | ||||||
|  | // #v1 | ||||||
|  | // func (db *database) save(path string) error { | ||||||
|  | // 	data, err := json.MarshalIndent(db, "", "\t") | ||||||
|  | // 	if err != nil { | ||||||
|  | // 		return err | ||||||
|  | // 	} | ||||||
|  | // 	return ioutil.WriteFile(path, data, 0644) | ||||||
|  | // } | ||||||
|  |  | ||||||
|  | // #v2 | ||||||
|  | // func (db *database) save(w io.Writer) error { | ||||||
|  | // 	data, err := json.MarshalIndent(db, "", "\t") | ||||||
|  | // 	if err != nil { | ||||||
|  | // 		return err | ||||||
|  | // 	} | ||||||
|  | // | ||||||
|  | //  return io.Copy(w, bytes.NewReader(data)) | ||||||
|  | // } | ||||||
|  |  | ||||||
|  | // #v3 | ||||||
|  | // TODO: use encoder | ||||||
|  |  | ||||||
|  | func (db *database) MarshalJSON() ([]byte, error) { | ||||||
|  | 	type encodable struct { | ||||||
|  | 		Type string | ||||||
|  | 		Item item | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var e []encodable | ||||||
|  |  | ||||||
|  | 	for _, it := range *db.list { | ||||||
|  | 		// TypeOf -> finds the dynamic type of "it" | ||||||
|  | 		// Elem   -> returns the element type of the pointer | ||||||
|  | 		// Name   -> returns the type name as string | ||||||
|  | 		t := reflect.TypeOf(it).Elem().Name() | ||||||
|  | 		e = append(e, encodable{t, it}) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return json.Marshal(e) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (db *database) UnmarshalJSON(data []byte) error { | ||||||
|  | 	var decodables []struct { | ||||||
|  | 		Type string | ||||||
|  | 		Item json.RawMessage | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if err := json.Unmarshal(data, &decodables); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, d := range decodables { | ||||||
|  | 		it, err := db.newItem(d.Item, d.Type) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		*db.list = append(*db.list, it) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (db *database) newItem(data []byte, typ string) (item, error) { | ||||||
|  | 	it, ok := db.types[typ] | ||||||
|  | 	if !ok { | ||||||
|  | 		return nil, fmt.Errorf("newItem: type (%q) does not exist", typ) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// get the dynamic type inside "it" like *book, *game, etc.. | ||||||
|  | 	t := reflect.TypeOf(it) | ||||||
|  |  | ||||||
|  | 	// get the pointer type's element type like book, game, etc... | ||||||
|  | 	e := t.Elem() | ||||||
|  |  | ||||||
|  | 	// create a new pointer value of the type like new(book), new(game), etc... | ||||||
|  | 	v := reflect.New(e) | ||||||
|  |  | ||||||
|  | 	// get the interface value and cast it to the item type | ||||||
|  | 	it = v.Interface().(item) | ||||||
|  |  | ||||||
|  | 	return it, json.Unmarshal(data, &it) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (db *database) register(typ string, it item) { | ||||||
|  | 	if db.types == nil { | ||||||
|  | 		db.types = make(map[string]item) | ||||||
|  | 	} | ||||||
|  | 	db.types[typ] = it | ||||||
|  | } | ||||||
							
								
								
									
										54
									
								
								interfaces/14-io-reader/database.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								interfaces/14-io-reader/database.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | |||||||
|  | [ | ||||||
|  | 	{ | ||||||
|  | 		"Type": "book", | ||||||
|  | 		"Item": { | ||||||
|  | 			"Title": "moby dick", | ||||||
|  | 			"Price": 10, | ||||||
|  | 			"Published": 118281600 | ||||||
|  | 		} | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"Type": "book", | ||||||
|  | 		"Item": { | ||||||
|  | 			"Title": "odyssey", | ||||||
|  | 			"Price": 15, | ||||||
|  | 			"Published": 733622400 | ||||||
|  | 		} | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"Type": "book", | ||||||
|  | 		"Item": { | ||||||
|  | 			"Title": "hobbit", | ||||||
|  | 			"Price": 25, | ||||||
|  | 			"Published": -62135596800 | ||||||
|  | 		} | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"Type": "puzzle", | ||||||
|  | 		"Item": { | ||||||
|  | 			"Title": "rubik's cube", | ||||||
|  | 			"Price": 5 | ||||||
|  | 		} | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"Type": "game", | ||||||
|  | 		"Item": { | ||||||
|  | 			"Title": "minecraft", | ||||||
|  | 			"Price": 20 | ||||||
|  | 		} | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"Type": "game", | ||||||
|  | 		"Item": { | ||||||
|  | 			"Title": "tetris", | ||||||
|  | 			"Price": 5 | ||||||
|  | 		} | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"Type": "toy", | ||||||
|  | 		"Item": { | ||||||
|  | 			"Title": "yoda", | ||||||
|  | 			"Price": 150 | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | ] | ||||||
							
								
								
									
										12
									
								
								interfaces/14-io-reader/game.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								interfaces/14-io-reader/game.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | // For more tutorials: https://blog.learngoprogramming.com | ||||||
|  | // | ||||||
|  | // Copyright © 2018 Inanc Gumus | ||||||
|  | // Learn Go Programming Course | ||||||
|  | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ | ||||||
|  | // | ||||||
|  |  | ||||||
|  | package main | ||||||
|  |  | ||||||
|  | type game struct { | ||||||
|  | 	product | ||||||
|  | } | ||||||
							
								
								
									
										40
									
								
								interfaces/14-io-reader/list.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								interfaces/14-io-reader/list.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | |||||||
|  | // For more tutorials: https://blog.learngoprogramming.com | ||||||
|  | // | ||||||
|  | // Copyright © 2018 Inanc Gumus | ||||||
|  | // Learn Go Programming Course | ||||||
|  | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ | ||||||
|  | // | ||||||
|  |  | ||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"strings" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type item interface { | ||||||
|  | 	discount(float64) | ||||||
|  | 	fmt.Stringer | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type list []item | ||||||
|  |  | ||||||
|  | func (l list) String() string { | ||||||
|  | 	if len(l) == 0 { | ||||||
|  | 		return "Sorry. We're waiting for delivery 🚚." | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var str strings.Builder | ||||||
|  | 	for _, it := range l { | ||||||
|  | 		str.WriteString(it.String()) | ||||||
|  | 		str.WriteRune('\n') | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return str.String() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (l list) discount(ratio float64) { | ||||||
|  | 	for _, it := range l { | ||||||
|  | 		it.discount(ratio) | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										61
									
								
								interfaces/14-io-reader/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								interfaces/14-io-reader/main.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | |||||||
|  | // For more tutorials: https://blog.learngoprogramming.com | ||||||
|  | // | ||||||
|  | // Copyright © 2018 Inanc Gumus | ||||||
|  | // Learn Go Programming Course | ||||||
|  | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ | ||||||
|  | // | ||||||
|  |  | ||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"encoding/json" | ||||||
|  | 	"fmt" | ||||||
|  | 	"io/ioutil" | ||||||
|  | 	"log" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func main() { | ||||||
|  | 	data, err := ioutil.ReadFile("database.json") | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatalln(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var store list | ||||||
|  |  | ||||||
|  | 	db := database{list: &store} | ||||||
|  | 	db.register("book", new(book)) | ||||||
|  | 	db.register("book", new(book)) | ||||||
|  | 	db.register("game", new(game)) | ||||||
|  | 	db.register("puzzle", new(puzzle)) | ||||||
|  | 	db.register("toy", new(toy)) | ||||||
|  |  | ||||||
|  | 	if err := json.Unmarshal(data, &db); err != nil { | ||||||
|  | 		log.Fatalln(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	fmt.Print(store) | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 		store := list{ | ||||||
|  | 			&book{product{"moby dick", 10}, toTimestamp(118281600)}, | ||||||
|  | 			&book{product{"odyssey", 15}, toTimestamp("733622400")}, | ||||||
|  | 			&book{product{"hobbit", 25}, unknown}, | ||||||
|  | 			&puzzle{product{"rubik's cube", 5}}, | ||||||
|  | 			&game{product{"minecraft", 20}}, | ||||||
|  | 			&game{product{"tetris", 5}}, | ||||||
|  | 			&toy{product{"yoda", 150}}, | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		db := database{list: &store} | ||||||
|  |  | ||||||
|  | 		out, err := json.MarshalIndent(&db, "", "\t") | ||||||
|  | 		if err != nil { | ||||||
|  | 			log.Fatalln(err) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		fmt.Println(string(out)) | ||||||
|  |  | ||||||
|  | 		// store.discount(.5) | ||||||
|  | 		// fmt.Print(store) | ||||||
|  | 	*/ | ||||||
|  | } | ||||||
							
								
								
									
										16
									
								
								interfaces/14-io-reader/money.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								interfaces/14-io-reader/money.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | // For more tutorials: https://blog.learngoprogramming.com | ||||||
|  | // | ||||||
|  | // Copyright © 2018 Inanc Gumus | ||||||
|  | // Learn Go Programming Course | ||||||
|  | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ | ||||||
|  | // | ||||||
|  |  | ||||||
|  | package main | ||||||
|  |  | ||||||
|  | import "fmt" | ||||||
|  |  | ||||||
|  | type money float64 | ||||||
|  |  | ||||||
|  | func (m money) String() string { | ||||||
|  | 	return fmt.Sprintf("$%.2f", m) | ||||||
|  | } | ||||||
							
								
								
									
										23
									
								
								interfaces/14-io-reader/product.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								interfaces/14-io-reader/product.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | // For more tutorials: https://blog.learngoprogramming.com | ||||||
|  | // | ||||||
|  | // Copyright © 2018 Inanc Gumus | ||||||
|  | // Learn Go Programming Course | ||||||
|  | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ | ||||||
|  | // | ||||||
|  |  | ||||||
|  | package main | ||||||
|  |  | ||||||
|  | import "fmt" | ||||||
|  |  | ||||||
|  | type product struct { | ||||||
|  | 	Title string | ||||||
|  | 	Price money | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (p *product) String() string { | ||||||
|  | 	return fmt.Sprintf("%-15s: %s", p.Title, p.Price) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (p *product) discount(ratio float64) { | ||||||
|  | 	p.Price *= money(1 - ratio) | ||||||
|  | } | ||||||
							
								
								
									
										12
									
								
								interfaces/14-io-reader/puzzle.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								interfaces/14-io-reader/puzzle.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | // For more tutorials: https://blog.learngoprogramming.com | ||||||
|  | // | ||||||
|  | // Copyright © 2018 Inanc Gumus | ||||||
|  | // Learn Go Programming Course | ||||||
|  | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ | ||||||
|  | // | ||||||
|  |  | ||||||
|  | package main | ||||||
|  |  | ||||||
|  | type puzzle struct { | ||||||
|  | 	product | ||||||
|  | } | ||||||
							
								
								
									
										77
									
								
								interfaces/14-io-reader/timestamp.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								interfaces/14-io-reader/timestamp.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | |||||||
|  | // For more tutorials: https://blog.learngoprogramming.com | ||||||
|  | // | ||||||
|  | // Copyright © 2018 Inanc Gumus | ||||||
|  | // Learn Go Programming Course | ||||||
|  | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ | ||||||
|  | // | ||||||
|  |  | ||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"strconv" | ||||||
|  | 	"time" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // Mon Jan 2 15:04:05 -0700 MST 2006 | ||||||
|  | const layout = "2006/01" | ||||||
|  |  | ||||||
|  | // unknown is the zero value of a timestamp. | ||||||
|  | var unknown = timestamp(time.Time{}) | ||||||
|  |  | ||||||
|  | // timestamp prints timestamps, it's a stringer. | ||||||
|  | // It is useful even if it's zero. | ||||||
|  | type timestamp time.Time | ||||||
|  |  | ||||||
|  | // MarshalJSON from timestamp. | ||||||
|  | func (ts timestamp) MarshalJSON() (out []byte, err error) { | ||||||
|  | 	u := time.Time(ts).Unix() | ||||||
|  | 	return strconv.AppendInt(out, u, 10), nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // UnmarshalJSON data to timestamp. | ||||||
|  | func (ts *timestamp) UnmarshalJSON(data []byte) error { | ||||||
|  | 	s := string(data) | ||||||
|  |  | ||||||
|  | 	// Let the ParseInt parse quoted strings. | ||||||
|  | 	us, err := strconv.Unquote(s) | ||||||
|  | 	if err == nil { | ||||||
|  | 		s = us | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Always overwrite the timestamp when decoding. | ||||||
|  | 	*ts = unknown | ||||||
|  |  | ||||||
|  | 	// Handle the numeric case. | ||||||
|  | 	if n, err := strconv.ParseInt(s, 10, 64); err == nil { | ||||||
|  | 		*ts = timestamp(time.Unix(n, 0)) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // String representation of the timestamp. | ||||||
|  | func (ts timestamp) String() string { | ||||||
|  | 	t := time.Time(ts) | ||||||
|  |  | ||||||
|  | 	if t.IsZero() { | ||||||
|  | 		return "unknown" | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return t.Format(layout) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // toTimestamp from an unknown value. | ||||||
|  | func toTimestamp(v interface{}) timestamp { | ||||||
|  | 	var t int | ||||||
|  |  | ||||||
|  | 	switch v := v.(type) { | ||||||
|  | 	case int: | ||||||
|  | 		t = v | ||||||
|  | 	case string: | ||||||
|  | 		t, _ = strconv.Atoi(v) | ||||||
|  | 	default: | ||||||
|  | 		return unknown | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return timestamp(time.Unix(int64(t), 0)) | ||||||
|  | } | ||||||
							
								
								
									
										12
									
								
								interfaces/14-io-reader/toy.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								interfaces/14-io-reader/toy.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | // For more tutorials: https://blog.learngoprogramming.com | ||||||
|  | // | ||||||
|  | // Copyright © 2018 Inanc Gumus | ||||||
|  | // Learn Go Programming Course | ||||||
|  | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ | ||||||
|  | // | ||||||
|  |  | ||||||
|  | package main | ||||||
|  |  | ||||||
|  | type toy struct { | ||||||
|  | 	product | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user