add: io reader composition
This commit is contained in:
		
							
								
								
									
										21
									
								
								interfaces/15-io-reader-composition/book.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								interfaces/15-io-reader-composition/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) | ||||||
|  | } | ||||||
							
								
								
									
										35
									
								
								interfaces/15-io-reader-composition/counter.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								interfaces/15-io-reader-composition/counter.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | |||||||
|  | // 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 "io" | ||||||
|  |  | ||||||
|  | // counter counts the total number of bytes read. | ||||||
|  | type counter struct { | ||||||
|  | 	r io.Reader | ||||||
|  | 	n int | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // newCounter wraps `r` and returns a *counter. | ||||||
|  | func newCounter(r io.Reader) *counter { | ||||||
|  | 	return &counter{r: r} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Total bytes read. | ||||||
|  | func (c *counter) total() int { | ||||||
|  | 	return c.n | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Read counts the number of bytes read from the underlying reader. | ||||||
|  | func (c *counter) Read(p []byte) (n int, err error) { | ||||||
|  | 	n, err = c.r.Read(p) // read from the underlying reader | ||||||
|  | 	if n > 0 { | ||||||
|  | 		c.n += n // sum the number of bytes read with the total bytes counted | ||||||
|  | 	} | ||||||
|  | 	return n, err // return the number of bytes read and an error | ||||||
|  | } | ||||||
							
								
								
									
										112
									
								
								interfaces/15-io-reader-composition/database.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								interfaces/15-io-reader-composition/database.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,112 @@ | |||||||
|  | // 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" | ||||||
|  | 	"reflect" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type database struct { | ||||||
|  | 	list  *list | ||||||
|  | 	types map[string]item | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // load the list by decoding the data from any kind of data source. | ||||||
|  | func (db *database) load(r io.Reader) error { | ||||||
|  | 	return json.NewDecoder(r).Decode(db) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (db *database) MarshalJSON() ([]byte, error) { | ||||||
|  | 	type encodable struct { | ||||||
|  | 		Type string | ||||||
|  | 		Item item | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var e []encodable | ||||||
|  |  | ||||||
|  | 	for _, it := range *db.list { | ||||||
|  | 		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) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	t := reflect.TypeOf(it) | ||||||
|  | 	e := t.Elem() | ||||||
|  | 	v := reflect.New(e) | ||||||
|  | 	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 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // I put it here as a reference implementation of manually reading from a reader. | ||||||
|  | // func (db *database) loadX(r io.Reader) error { | ||||||
|  | // 	buf := make([]byte, 64) | ||||||
|  | // | ||||||
|  | // 	var ( | ||||||
|  | // 		data []byte | ||||||
|  | // 		n    int | ||||||
|  | // 		err  error | ||||||
|  | // 	) | ||||||
|  | // | ||||||
|  | // 	for { | ||||||
|  | // 		n, err = r.Read(buf) | ||||||
|  | // | ||||||
|  | // 		if n > 0 { | ||||||
|  | // 			data = append(data, buf[:n]...) | ||||||
|  | //		} | ||||||
|  | // | ||||||
|  | // 		if err != nil { | ||||||
|  | // 			break | ||||||
|  | // 		} | ||||||
|  | // 	} | ||||||
|  | // | ||||||
|  | // 	if err != io.EOF { | ||||||
|  | // 		return err | ||||||
|  | // 	} | ||||||
|  | // 	return json.Unmarshal(data, db) | ||||||
|  | // } | ||||||
							
								
								
									
										54
									
								
								interfaces/15-io-reader-composition/database.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								interfaces/15-io-reader-composition/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 | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | ] | ||||||
							
								
								
									
										
											BIN
										
									
								
								interfaces/15-io-reader-composition/database.json.gz
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								interfaces/15-io-reader-composition/database.json.gz
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										12
									
								
								interfaces/15-io-reader-composition/game.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								interfaces/15-io-reader-composition/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/15-io-reader-composition/list.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								interfaces/15-io-reader-composition/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) | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										97
									
								
								interfaces/15-io-reader-composition/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								interfaces/15-io-reader-composition/main.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | |||||||
|  | // 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 ( | ||||||
|  | 	"compress/gzip" | ||||||
|  | 	"fmt" | ||||||
|  | 	"net/http" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func main() { | ||||||
|  | 	/* | ||||||
|  | 		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) | ||||||
|  | 	*/ | ||||||
|  |  | ||||||
|  | 	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)) | ||||||
|  |  | ||||||
|  | 	// load from a file | ||||||
|  | 	// f, _ := os.Open("database.json") | ||||||
|  | 	// db.load(f) | ||||||
|  | 	// f.Close() | ||||||
|  |  | ||||||
|  | 	// load from a string | ||||||
|  | 	// const data = `[ | ||||||
|  | 	// { "Type": "book", "Item": { "Title": "1984", "Price": 8, "Published": -649641600 } }, | ||||||
|  | 	// { "Type": "game", "Item": { "Title": "paperboy", "Price": 20 } }]` | ||||||
|  | 	// r := strings.NewReader(data) | ||||||
|  | 	// db.load(r) | ||||||
|  |  | ||||||
|  | 	// load from a web server | ||||||
|  | 	// res, _ := http.Get("https://inancgumus.github.io/x/database.json") | ||||||
|  | 	// db.load(res.Body) | ||||||
|  | 	// res.Body.Close() | ||||||
|  |  | ||||||
|  | 	// decompress the reader while reading from it | ||||||
|  | 	// res, _ := http.Get("https://inancgumus.github.io/x/database.json.gz") | ||||||
|  | 	// gr, _ := gzip.NewReader(res.Body) | ||||||
|  | 	// db.load(gr) | ||||||
|  | 	// gr.Close() | ||||||
|  | 	// res.Body.Close() | ||||||
|  |  | ||||||
|  | 	// decompress and count the number of compressed bytes read | ||||||
|  | 	// res, _ := http.Get("https://inancgumus.github.io/x/database.json.gz") | ||||||
|  | 	// c := newCounter(res.Body) // count the bytes read | ||||||
|  | 	// gr, _ := gzip.NewReader(c) | ||||||
|  |  | ||||||
|  | 	// db.load(gr) | ||||||
|  | 	// fmt.Printf("%d bytes read.\n\n", c.total()) | ||||||
|  |  | ||||||
|  | 	// gr.Close() | ||||||
|  | 	// res.Body.Close() | ||||||
|  |  | ||||||
|  | 	// count the number of compressed bytes read from the web server then decompress | ||||||
|  | 	res, _ := http.Get("https://inancgumus.github.io/x/database.json.gz") | ||||||
|  | 	gr, _ := gzip.NewReader(res.Body) | ||||||
|  | 	c := newCounter(gr) | ||||||
|  |  | ||||||
|  | 	db.load(c) | ||||||
|  | 	fmt.Printf("%d bytes read.\n\n", c.total()) | ||||||
|  |  | ||||||
|  | 	gr.Close() | ||||||
|  | 	res.Body.Close() | ||||||
|  |  | ||||||
|  | 	fmt.Print(store) | ||||||
|  | } | ||||||
							
								
								
									
										16
									
								
								interfaces/15-io-reader-composition/money.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								interfaces/15-io-reader-composition/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/15-io-reader-composition/product.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								interfaces/15-io-reader-composition/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/15-io-reader-composition/puzzle.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								interfaces/15-io-reader-composition/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/15-io-reader-composition/timestamp.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								interfaces/15-io-reader-composition/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/15-io-reader-composition/toy.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								interfaces/15-io-reader-composition/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