The Go Programming Language Ex(5)

Ex 4.8

Modify charcount to count letters, digits, and so on in their Unicode categories, using functions like unicode.IsLetter.

package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"unicode"
)

func main() {
	counts := make(map[string]int)                       // counts of Unicode characters
	invalid, letter, digit, mark, other := 0, 0, 0, 0, 0 // count of invalid UTF-8 characters

	in := bufio.NewReader(os.Stdin)
	for {
		r, n, err := in.ReadRune() // returns rune, nbytes, error
		if err == io.EOF {
			break
		}
		if err != nil {
			fmt.Fprintf(os.Stderr, "charcount: %v\n", err)
			os.Exit(1)
		}
		if r == unicode.ReplacementChar && n == 1 {
			invalid++
			continue
		} else if unicode.IsLetter(r) {
			letter++
		} else if unicode.IsDigit(r) {
			digit++
		} else if unicode.IsMark(r) {
			mark++
		} else {
			other++
			fmt.Println(r)
		}
	}
	counts["invalid"] = invalid
	counts["letter"] = letter
	counts["digit"] = digit
	counts["mark"] = mark
	counts["other"] = other

	for c, n := range counts {
		fmt.Printf("%s\t:%d\n", c, n)
	}
}
./ex4.8
sdfwwer 1434jipi三是奇偶i问
32
10
invalid	:0
letter	:17
digit	:4
mark	:0
other	:2
  • 显然汉字也被认为是letter
  • 终端模拟EOF 为 ctrl + d

Ex 4.9

Write a program wordfreq to report the frequency of each word in an input text file. Call input.Split(bufio.ScanWords) before the first call to Scan to break the input into words instead of lines.

package main

import (
	"bufio"
	"fmt"
	"strings"
)

func main() {
	words := make(map[string]int)
	input := "foo  bar   baz foo 我们 foo 我们"
	scanner := bufio.NewScanner(strings.NewReader(input))
	scanner.Split(bufio.ScanWords)
	for scanner.Scan() {
		//fmt.Println(scanner.Text())
		words[scanner.Text()]++
	}
	for k, v := range words {
		fmt.Printf("%s : %d\n", k, v)
	}
}
$ go run wordfreq.go
baz : 1
我们 : 2
foo : 3
bar : 1

Ex4.13

The JSON-based web service of the Open Movie Database lets you s https://omdbapi.com/ for a movie by name and download its poster image. Write a tool poster that downloads the poster image for the movie named on the command line.

package main

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
)

const OmdbAPI = "http://www.omdbapi.com/?i=tt3896198&apikey=7b94e6bd&t="

type Movie struct {
	Title    string
	Year     string
	Poster   string
	Response string
	Errormsg string `json:"Error,omitempty"`
}

func main() {
	for i := 1; i < len(os.Args); i++ {
		url := OmdbAPI + os.Args[i]
		resp, err := http.Get(url)
		if err != nil {
			fmt.Println("http get error ", err)
			return
		}
		defer resp.Body.Close()
		var result Movie
		err = json.NewDecoder(resp.Body).Decode(&result)
		if err != nil {
			fmt.Println("decode failed")
			return
		}
		fmt.Printf("%#v\n", result)
		fmt.Printf("%v\n", result)
		if result.Response == "false" {
			fmt.Println(result.Errormsg)
		} else {
			fmt.Println("starting download poster")
			result.Poster = "https://gss1.bdstatic.com/9vo3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike92%2C5%2C5%2C92%2C30/sign=5a60b1a4cf8065386fe7ac41f6b4ca21/fd039245d688d43f4ee7a518781ed21b0ff43b89.jpg"
			posterres, err := http.Get(result.Poster)
			if err != nil {
				fmt.Println("get poster url error, download failed", err)
				return
			} else {
				filename := result.Title + ".jpg"
				f, err := os.Create(filename)
				if err != nil {
					fmt.Println("create file error")
					return
				}
				io.Copy(f, posterres.Body)
			}
		}
	}
}
$ ./ex4.13 triangle triangleeeee
main.Movie{Title:"Triangle", Year:"2009", Poster:"https://images-na.ssl-images-amazon.com/images/M/MV5BY2VlODI5ZmMtZDExYS00OWI4LWJiMWItZWZkZWRkNzlmZWI2XkEyXkFqcGdeQXVyMTQxNzMzNDI@._V1_SX300.jpg", Response:"True", Errormsg:""}
{Triangle 2009 https://images-na.ssl-images-amazon.com/images/M/MV5BY2VlODI5ZmMtZDExYS00OWI4LWJiMWItZWZkZWRkNzlmZWI2XkEyXkFqcGdeQXVyMTQxNzMzNDI@._V1_SX300.jpg True }
starting download poster
download finished
main.Movie{Title:"", Year:"", Poster:"", Response:"False", Errormsg:"Movie not found!"}
{   False Movie not found!}
Movie not found!

Triangle.jpg

Ex 4.14

Create a web server that queries GitHub once and then allows navigation of the list of bug reports, milestones, and users.

package main

import (
	"encoding/json"
	"fmt"
	temp2 "html/template"
	"log"
	"net/http"
	"net/url"
	"os"
	"strings"
	temp1 "text/template"
	"time"
)

const IssuesURL = "https://api.github.com/search/issues"

//!+template
const templ1 = `{{.TotalCount}} issues:
{{range .Items}}----------------------------------------
Number: {{.Number}}
User:   {{.User.Login}}
Title:  {{.Title | printf "%.64s"}}
Age:    {{.CreatedAt | daysAgo}} days
Milestone: {{.Milestone.Title}}
{{end}}`
const templ2 = `

{{.TotalCount}} issues

{{range .Items}} {{end}}
# State User Title Milestone
{{.Number}} {{.State}} {{.User.Login}} {{.Title}} {{.Milestone.Title}}
` //!-template type IssuesSearchResult struct { TotalCount int `json:"total_count"` Items []*Issue } type Issue struct { Number int HTMLURL string `json:"html_url"` Title string State string User *User CreatedAt time.Time `json:"created_at"` Body string // in Markdown format Milestone *Milestone } type User struct { Login string HTMLURL string `json:"html_url"` } type Milestone struct { Title string HTMLURL string `json:"html_url"` } var report1 = temp1.Must(temp1.New("issuelist1"). Funcs(temp1.FuncMap{"daysAgo": daysAgo}). Parse(templ1)) var report2 = temp2.Must(temp2.New("issuelist2"). Funcs(temp2.FuncMap{"daysAgo": daysAgo}). Parse(templ2)) func main() { result, err := SearchIssues(os.Args[1:]) if err != nil { log.Fatal(err) } f1, err := os.Create("report.txt") if err := report1.Execute(f1, result); err != nil { log.Fatal(err) } f2, err := os.Create("report.html") if err := report2.Execute(f2, result); err != nil { log.Fatal(err) } } func daysAgo(t time.Time) int { return int(time.Since(t).Hours() / 24) } // SearchIssues queries the GitHub issue tracker. func SearchIssues(terms []string) (*IssuesSearchResult, error) { q := url.QueryEscape(strings.Join(terms, " ")) resp, err := http.Get(IssuesURL + "?q=" + q) if err != nil { return nil, err } // We must close resp.Body on all execution paths. // (Chapter 5 presents 'defer', which makes this simpler.) if resp.StatusCode != http.StatusOK { resp.Body.Close() return nil, fmt.Errorf("search query failed: %s", resp.Status) } var result IssuesSearchResult if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { resp.Body.Close() return nil, err } resp.Body.Close() return &result, nil }
//report.txt
41 issues:
----------------------------------------
Number: 23188
User:   ianlancetaylor
Title:  cmd/compile: incorrect order of evaluation according to spec
Age:    7 days
Milestone: Go1.11
----------------------------------------
Number: 23183
User:   terinjokes
Title:  net/http: muxer no longer redirects host patterns in go1.10
Age:    7 days
Milestone: Go1.10
----------------------------------------
Number: 23181
User:   hirochachacha
Title:  cmd/buildid: rewrite algorithm is broken
Age:    7 days
Milestone: Go1.10
----------------------------------------
Number: 23180
User:   aarzilli
Title:  cmd/go: go test -c does not apply specified gcflags to all packa
Age:    7 days
Milestone: Go1.10
----------------------------------------
Number: 23166
User:   mvdan
Title:  x/tools/go/ssa/interp: tests consistently failing on darwin
Age:    8 days
Milestone: Go1.10
----------------------------------------
Number: 23146
User:   bradfitz
Title:  cmd/vet: stderr spam during testing
Age:    12 days
Milestone: Go1.10
----------------------------------------
Number: 23122
User:   rsc
Title:  all: remove support for OS X 10.8 and 10.9
Age:    13 days
Milestone: Go1.11
----------------------------------------
Number: 23098
User:   mikioh
Title:  runtime: loop over allp causes a nil pointer dereference crash
Age:    15 days
Milestone: Go1.10
----------------------------------------
Number: 23037
User:   zolotov
Title:  cmd/go: add JSON output for building package failures while runn
Age:    19 days
Milestone: Go1.10
----------------------------------------
Number: 23036
User:   zolotov
Title:  cmd/test2json: filtering out testing service messages or mark th
Age:    19 days
Milestone: Go1.10
----------------------------------------
Number: 23011
User:   bradfitz
Title:  build: announce end of support for old macOS releases
Age:    21 days
Milestone: Go1.11
----------------------------------------
Number: 23010
User:   rsc
Title:  net/http: ResponseWriter panics in WriteHeaders that were former
Age:    21 days
Milestone: Go1.10
----------------------------------------
Number: 23009
User:   rsc
Title:  net/http/httputil: ReverseProxy change conflicts with future Rev
Age:    21 days
Milestone: Go1.10
----------------------------------------
Number: 22984
User:   rsc
Title:  cmd/go: test -json not cached
Age:    22 days
Milestone: Go1.10
----------------------------------------
Number: 22924
User:   chipaca
Title:  syscall: on linux 386 doesn't support syscalls that don't fail
Age:    27 days
Milestone: Go1.11
----------------------------------------
Number: 22781
User:   pciet
Title:  runtime: fatal error: sweep increased allocation count, go1.9.x
Age:    39 days
Milestone: Go1.9.3
----------------------------------------
Number: 22637
User:   ianlancetaylor
Title:  crypto: examine and probably remove OpenSSL derived code
Age:    48 days
Milestone: Go1.10
----------------------------------------
Number: 22487
User:   tklauser
Title:  lib/time: update tzdata before 1.10 release
Age:    58 days
Milestone: Go1.10
----------------------------------------
Number: 22475
User:   rsc
Title:  cmd/go: include GOROOT in linkActionID hash
Age:    59 days
Milestone: Go1.10
----------------------------------------
Number: 22472
User:   rsc
Title:  cmd/go: implement gccgo support for content-based staleness
Age:    60 days
Milestone: Go1.10
----------------------------------------
Number: 22444
User:   griesemer
Title:  cmd/compile: missing wrapper function for call of literal method
Age:    62 days
Milestone: Go1.11
----------------------------------------
Number: 22429
User:   TheTincho
Title:  cmd/compile: invalid instruction error for FMOVD when compiling 
Age:    63 days
Milestone: Go1.9.3
----------------------------------------
Number: 22349
User:   alexbrainman
Title:  net: ipStackCapabilities.probe creates sockets that can escape i
Age:    68 days
Milestone: Go1.10
----------------------------------------
Number: 22224
User:   siebenmann
Title:  cmd/go: build failure on amd64 Linux with an error in TestTwoGop
Age:    76 days
Milestone: Go1.10
----------------------------------------
Number: 22204
User:   tmm1
Title:  runtime: sigpanic during GC on android/arm64
Age:    77 days
Milestone: Go1.10
----------------------------------------
Number: 22155
User:   rsc
Title:  cmd/go: GOROOT override using linker -X flag is probably not rig
Age:    82 days
Milestone: Go1.10
----------------------------------------
Number: 21431
User:   josharian
Title:  runtime: stack split at a bad time on mipsle
Age:    135 days
Milestone: Go1.10
----------------------------------------
Number: 21282
User:   dsnet
Title:  cmd/compile: incorrect type assertions on conflicting package na
Age:    146 days
Milestone: Go1.11
----------------------------------------
Number: 21221
User:   vibhavp
Title:  cmd/compile: internal compiler error: constant type mismatch whe
Age:    150 days
Milestone: Go1.11
----------------------------------------
Number: 20790
User:   mikioh
Title:  net: DefaultResolver.Lookup{Host,IPAddr} and LookupHost fail to 
Age:    185 days
Milestone: Go1.11
//report.html

41 issues

# State User Title Milestone
23188 open ianlancetaylor cmd/compile: incorrect order of evaluation according to spec Go1.11
23183 open terinjokes net/http: muxer no longer redirects host patterns in go1.10 Go1.10
23181 open hirochachacha cmd/buildid: rewrite algorithm is broken Go1.10
23180 open aarzilli cmd/go: go test -c does not apply specified gcflags to all packages Go1.10
23166 open mvdan x/tools/go/ssa/interp: tests consistently failing on darwin Go1.10
23146 open bradfitz cmd/vet: stderr spam during testing Go1.10
23122 open rsc all: remove support for OS X 10.8 and 10.9 Go1.11
23098 open mikioh runtime: loop over allp causes a nil pointer dereference crash Go1.10
23037 open zolotov cmd/go: add JSON output for building package failures while running go test on directory with several packages Go1.10
23036 open zolotov cmd/test2json: filtering out testing service messages or mark them in a special way Go1.10
23011 open bradfitz build: announce end of support for old macOS releases Go1.11
23010 open rsc net/http: ResponseWriter panics in WriteHeaders that were formerly ignored Go1.10
23009 open rsc net/http/httputil: ReverseProxy change conflicts with future ReverseProxy plans Go1.10
22984 open rsc cmd/go: test -json not cached Go1.10
22924 open chipaca syscall: on linux 386 doesn't support syscalls that don't fail Go1.11
22781 open pciet runtime: fatal error: sweep increased allocation count, go1.9.x Go1.9.3
22637 open ianlancetaylor crypto: examine and probably remove OpenSSL derived code Go1.10
22487 open tklauser lib/time: update tzdata before 1.10 release Go1.10
22475 open rsc cmd/go: include GOROOT in linkActionID hash Go1.10
22472 open rsc cmd/go: implement gccgo support for content-based staleness Go1.10
22444 open griesemer cmd/compile: missing wrapper function for call of literal method expression Go1.11
22429 open TheTincho cmd/compile: invalid instruction error for FMOVD when compiling for 387 Go1.9.3
22349 open alexbrainman net: ipStackCapabilities.probe creates sockets that can escape into child process Go1.10
22224 open siebenmann cmd/go: build failure on amd64 Linux with an error in TestTwoGopathShlibsGccgo from CL 69831 onward Go1.10
22204 open tmm1 runtime: sigpanic during GC on android/arm64 Go1.10
22155 open rsc cmd/go: GOROOT override using linker -X flag is probably not right Go1.10
21431 open josharian runtime: stack split at a bad time on mipsle Go1.10
21282 open dsnet cmd/compile: incorrect type assertions on conflicting package names Go1.11
21221 open vibhavp cmd/compile: internal compiler error: constant type mismatch when comparing two unsafe.Pointer rvalues Go1.11
20790 open mikioh net: DefaultResolver.Lookup{Host,IPAddr} and LookupHost fail to parse a literal IPv6 address w/ zone Go1.11

ex4.14 report.html

相关

comments powered by Disqus