massive: move a lot of things
This commit is contained in:
		| @@ -0,0 +1,6 @@ | ||||
| learngoprogramming.com 10 | ||||
| learngoprogramming.com 10 | ||||
| golang.org 4 | ||||
| golang.org 6 | ||||
| blog.golang.org 20 | ||||
| blog.golang.org 10 | ||||
| @@ -0,0 +1,6 @@ | ||||
| learngoprogramming.com 10 | ||||
| learngoprogramming.com 10 | ||||
| golang.org | ||||
| golang.org 6 | ||||
| blog.golang.org 20 | ||||
| blog.golang.org 10 | ||||
| @@ -0,0 +1,6 @@ | ||||
| learngoprogramming.com 10 | ||||
| learngoprogramming.com 10 | ||||
| golang.org -100 | ||||
| golang.org 6 | ||||
| blog.golang.org 20 | ||||
| blog.golang.org 10 | ||||
| @@ -0,0 +1,6 @@ | ||||
| learngoprogramming.com 10 | ||||
| learngoprogramming.com 10 | ||||
| golang.org FOUR | ||||
| golang.org 6 | ||||
| blog.golang.org 20 | ||||
| blog.golang.org 10 | ||||
							
								
								
									
										57
									
								
								25-functions-and-pointers/08x-log-parser-pointers/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								25-functions-and-pointers/08x-log-parser-pointers/main.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| // 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 ( | ||||
| 	"bufio" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
| 	in := bufio.NewScanner(os.Stdin) | ||||
|  | ||||
| 	p := newParser() | ||||
| 	for in.Scan() { | ||||
| 		// dom, err := parse(p, in.Text()) | ||||
| 		// if err != nil { | ||||
| 		// 	fmt.Println(err) | ||||
| 		// 	return | ||||
| 		// } | ||||
|  | ||||
| 		// p = push(p, dom) | ||||
|  | ||||
| 		add(p, in.Text()) | ||||
| 	} | ||||
|  | ||||
| 	summarize(p) | ||||
| 	dumpErrs(in.Err(), err(p)) | ||||
| } | ||||
|  | ||||
| // funcs not always need to be reused. | ||||
| // here, it tells about what it does: it summarizes the parsing result. | ||||
| func summarize(p *parser) { | ||||
| 	// multiple iterators can be created. each one remembers the last | ||||
| 	// read domain record. | ||||
|  | ||||
| 	next, cur := iterator(p) | ||||
| 	for next() { | ||||
| 		dom := cur() | ||||
| 		fmt.Printf("%-25s -> %d\n", dom.name, dom.visits) | ||||
| 	} | ||||
| 	fmt.Printf("\n%-25s -> %d\n", "TOTAL", p.total) | ||||
| } | ||||
|  | ||||
| // this variadic func simplifies the multiple error handling | ||||
| func dumpErrs(errs ...error) { | ||||
| 	for _, err := range errs { | ||||
| 		if err != nil { | ||||
| 			fmt.Printf("> Err: %s\n", err) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										110
									
								
								25-functions-and-pointers/08x-log-parser-pointers/parser.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								25-functions-and-pointers/08x-log-parser-pointers/parser.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,110 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| // domain represents a domain log record | ||||
| type domain struct { | ||||
| 	name   string | ||||
| 	visits int | ||||
| } | ||||
|  | ||||
| // parser parses a log file and provides an iterator to iterate upon the domains | ||||
| // | ||||
| // the parser struct is carefully crafted to be usable using its zero values except the map field | ||||
| type parser struct { | ||||
| 	sum     map[string]domain // visits per unique domain | ||||
| 	domains []string          // unique domain names | ||||
| 	total   int               // total visits to all domains | ||||
| 	lines   int               // number of parsed lines (for the error messages) | ||||
| 	lerr    error             // saves the last error occurred | ||||
| } | ||||
|  | ||||
| // newParser creates and returns a new parser. | ||||
| func newParser() *parser { | ||||
| 	return &parser{sum: make(map[string]domain)} | ||||
| } | ||||
|  | ||||
| // add parses the given line and saves the result to the internal list of | ||||
| // domains. it doesn't add the record when the parsing fails. | ||||
| func add(p *parser, line string) { | ||||
| 	// if there was a previous error do not add | ||||
| 	if p.lerr != nil { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	dom, err := parse(p, line) | ||||
|  | ||||
| 	// store only the last error | ||||
| 	if err != nil { | ||||
| 		p.lerr = err | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	push(p, dom) | ||||
| } | ||||
|  | ||||
| // iterator returns two functions for iterating over domains. | ||||
| // next = returns true when there are more domains to iterate on. | ||||
| // cur  = returns the current domain | ||||
| func iterator(p *parser) (next func() bool, cur func() domain) { | ||||
| 	// remember the last received line | ||||
| 	var last int | ||||
|  | ||||
| 	next = func() bool { | ||||
| 		defer func() { last++ }() | ||||
| 		return len(p.domains) > last | ||||
| 	} | ||||
|  | ||||
| 	cur = func() domain { | ||||
| 		// return a copy so the caller cannot change it | ||||
| 		name := p.domains[last-1] | ||||
| 		return p.sum[name] | ||||
| 	} | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // error returns the last error occurred | ||||
| func err(p *parser) error { | ||||
| 	return p.lerr | ||||
| } | ||||
|  | ||||
| // parse parses the given text and returns a domain struct | ||||
| func parse(p *parser, line string) (dom domain, err error) { | ||||
| 	p.lines++ // increase the parsed line counter (only write is here) | ||||
|  | ||||
| 	fields := strings.Fields(line) | ||||
| 	if len(fields) != 2 { | ||||
| 		err = fmt.Errorf("wrong input: %v (line #%d)", fields, p.lines) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	name, visits := fields[0], fields[1] | ||||
|  | ||||
| 	n, err := strconv.Atoi(visits) | ||||
| 	if n < 0 || err != nil { | ||||
| 		err = fmt.Errorf("wrong input: %q (line #%d)", visits, p.lines) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	return domain{name: name, visits: n}, nil | ||||
| } | ||||
|  | ||||
| // push pushes the given domain to the internal list of domains. | ||||
| // it also increases the total visits for all the domains. | ||||
| func push(p *parser, d domain) { | ||||
| 	name := d.name | ||||
|  | ||||
| 	// collect the unique domains | ||||
| 	if _, ok := p.sum[name]; !ok { | ||||
| 		p.domains = append(p.domains, name) | ||||
| 	} | ||||
|  | ||||
| 	p.total += d.visits | ||||
| 	d.visits += p.sum[name].visits | ||||
| 	p.sum[name] = d | ||||
| } | ||||
		Reference in New Issue
	
	Block a user