<The Go programming language>第一章课后练习

    科技2022-07-20  107

    1.1:修改echo程序输出os.Args[0],即命令的名称。 package main import( "fmt" "os" ) func main(){ for i := 1; i < len(os.Args);i++{ fmt.Println(os.Args[i]) } } go run main.go monther father sun monther father sun 1.2:修改echo程序,输出参数的索引和值,每行一个 package main import ( "fmt" "os" ) func main(){ for i := 1; i < len(os.Args); i++{ fmt.Println(i) fmt.Println(os.Args[i]) } } go run main.go monther father sun 1 monther 2 father 3 sun 1.3:尝试测量可能低效的程序和使用strings.Join的程序在执行时间上的差异。 package main import( "fmt" "os" "time" ) func echo1(){ start := time.Now() var s, sep string for i := 1; i < len(os.Args); i++{ s += sep + os.Args[i] sep = " " } fmt.Println(s) secs := time.Since(start).Seconds() fmt.Println(secs) } func echo2(){ start := time.Now() s, sep := "", "" for _, arg := range os.Args[1:]{ s += sep + arg sep = " " } fmt.Println(s) secs := time.Since(start).Seconds() fmt.Println(secs) } func echo3(){ start := time.Now() fmt.Println(strings.Join(os.Args[1:]," ")) secs := time.Since(start).Seconds() fmt.Println(secs) } func main(){ echo1() echo2() echo3() } go run main.go mother father sun mohter father son 2.9647e-05 mohter father son 1.704e-06 mohter father son 1.648e-06 1.4:修改dup2程序,输出出现重复行的文件的名称。 func dup2(){ counts := make(map[string]int) files := os.Args[1:] if len(files) == 0{ countLines(os.Stdin, counts) }else{ for _, arg := range files{ f, err := os.Open(arg) if err != nil{ fmt.Fprintf(os.Stderr, "dup2: %v\n", err) continue } countLines(f, counts) f.Close() } } for line, n := range counts{ if n > 1{ fmt.Printf("%d\t%s\n", n, line) } } } func countLines(f *os.File, counts map[string]int){ input := bufio.NewScanner(f) for input.Scan(){ if counts[input.Text()] > 1{ fmt.Printf("%s\n",f.Name()) } counts[input.Text()]++ } } func main(){ dup2() } 1.5:将Lissajous程序的调色板更改为黑色上绿色,以增加真实性。要创建Web颜色#RRGGBB,请使用color.RGBA {0xRR,0xGG,0xBB,0xff},其中每对十六进制数字代表红色的强度, 像素的绿色或蓝色分量。 var palette = []color.Color{color.RGBA{127, 255, 170,255}, color.Black} const( whiteIndex = 0 blackIndex = 1 ) func lissajous(out io.Writer){ const( cycles = 5 res = 0.001 size = 100 nframes = 64 delay = 8 ) freq := rand.Float64() * 3.0 anim := gif.GIF{LoopCount: nframes} phase := 0.0 for i := 0; i < nframes; i++{ rect := image.Rect(0, 0, 2*size+1, 2*size+1) img := image.NewPaletted(rect, palette) for t := 0.0; t < cycles*2*math.Pi; t += res { x := math.Sin(t) y := math.Sin(t*freq + phase) img.SetColorIndex(size+int(x*size+0.5), size+int(y*size+0.5), blackIndex) } phase += 0.1 anim.Delay = append(anim.Delay, delay) anim.Image = append(anim.Image, img) } gif.EncodeAll(out, &anim) } func main(){ lissajous(os.Stdout) } 1.6:修改Lissajous程序,以通过向调色板中添加更多值,然后通过以一些有趣的方式更改SetColorIndex的第三个参数来显示它们来生成多种颜色的图像。 修改调色盘里的参数就可以了。 1.7: 函数io.Copy(dst, src)从src读,并且写入dst。使用它代替ioutil.ReadAll来复制响应内容到os.Stdout,这样不需要装下整个响应数据流的缓冲区。确保检查io.Copy返回的错误结果。 func fetch(){ for _, url := range os.Args[1:]{ resp, err := http.Get(url) if err != nil{ fmt.Fprintf(os.Stderr, "fetch: %v\n", err) os.Exit(1) } _, err = io.Copy(os.Stdout, resp.Body) resp.Body.Close() if err != nil { fmt.Fprintf(os.Stderr, "fetch: reading %s: %v\n", url, err) os.Exit(1) } } } func main(){ fetch() } 1.8:修改fetch程序添加一个http://前缀(假设该URL参数缺失协议前缀)。可能会用到strings.HasPrefix。 func fetch(){ for _, url := range os.Args[1:]{ if !strings.HasPrefix(url, "http://"){ url = "http://" + url } resp, err := http.Get(url) if err != nil { fmt.Fprintf(os.Stderr, "fetch: %v\n", err) os.Exit(1) } b, err := ioutil.ReadAll(resp.Body) resp.Body.Close() if err != nil{ fmt.Fprintf(os.Stderr, "fetch: reading %s: %v\n", url, err) os.Exit(1) } fmt.Printf("%s",b) } } func main(){ fetch() } 1.9:修改fetch来输出HTTP的状态码,可以在resp.Status中找到它。 func fetch(){ for _, url := range os.Args[1:]{ if !strings.HasPrefix(url, "http://"){ url = "http://" + url } resp, err := http.Get(url) if err != nil { fmt.Fprintf(os.Stderr, "fetch: %v\n", err) os.Exit(1) } fmt.Printf("%s\n",resp.Status) //b, err := ioutil.ReadAll(resp.Body) resp.Body.Close() if err != nil{ fmt.Fprintf(os.Stderr, "fetch: reading %s: %v\n", url, err) os.Exit(1) } //fmt.Printf("%s",b) } } func main(){ fetch() } 1.10:找一个产生大量数据的网站。连续两次运行fetchall,看报告的时间是否会有很大的变化,调查缓存情况。每一次获取的内容一样吗?修改fetchall将内容输出到文件,这样可以检查它是否一致。 func fetchall(){ start := time.Now() ch := make(chan string) for _, url := range os.Args[1:]{ go fetch(url, ch) } for range os.Args[1:]{ fmt.Println(<-ch) } fmt.Printf("%.2fs elapsed\n", time.Since(start).Seconds()) } func fetch(url string, ch chan<- string){ start := time.Now() resp, err := http.Get(url) if err != nil { ch <- fmt.Sprint(err) return } b, _ := ioutil.ReadAll(resp.Body) nbytes, err := io.Copy(ioutil.Discard, resp.Body) resp.Body.Close() if err != nil { ch <- fmt.Sprintf("while reading %s: %v", url, err) return } secs := time.Since(start).Seconds() ch <- fmt.Sprintf("%.2fs } %s\n %s", secs, nbytes, url, b) } func main(){ fetchall() } 我ping的是百度,时间不一样,内容一样的,内容具体我也没怎么比较,就滚了一下。 1.11:使用更长的参数列表来尝试fetchall,例如使用alexa.com排名前100万的网站。如果一个网站没有响应,程序的行为是怎样的? ye@yewenweis-MacBook-Pro src % ./1 https://golang.org http://gopl.io http://godoc.org 1.47s 7510 http://godoc.org %!s(MISSING) Get "http://www.gopl.io/": dial tcp [::1]:80: connect: connection refused Get "https://golang.org": dial tcp 216.239.37.1:443: i/o timeout 30.01s elapsed

    [旺柴]书上的网站就进不去。

    1.12:修改Lissajous服务器以从URL读取参数值。 例如,您可以进行排列,以使诸如http:// localhost:8000 /?cycles = 20之类的URL将循环数设置为20,而不是默认值5。使用strconv.Atoi函数将字符串参数转换为 整数。您可以通过go doc strconv.Atoi查看其文档。 package main import ( "fmt" "image" "image/color" "image/gif" "io" "log" "math" "math/rand" "net/http" ) var palette = []color.Color{color.RGBA{127, 255, 170,255}, color.Black} const( whiteIndex = 0 blackIndex = 1 ) func lissajous(out io.Writer){ const( cycles = 5 res = 0.001 size = 100 nframes = 64 delay = 8 ) freq := rand.Float64() * 3.0 anim := gif.GIF{LoopCount: nframes} phase := 0.0 for i := 0; i < nframes; i++{ rect := image.Rect(0, 0, 2*size+1, 2*size+1) img := image.NewPaletted(rect, palette) for t := 0.0; t < cycles*2*math.Pi; t += res { x := math.Sin(t) y := math.Sin(t*freq + phase) img.SetColorIndex(size+int(x*size+0.5), size+int(y*size+0.5), blackIndex) } phase += 0.1 anim.Delay = append(anim.Delay, delay) anim.Image = append(anim.Image, img) } gif.EncodeAll(out, &anim) } func handler(w http.ResponseWriter, r *http.Request){ fmt.Fprintf(w, "%s %s %s\n", r.Method, r.URL, r.Proto) for k, v := range r.Header{ fmt.Fprintf(w, "Header[%q] = %q\n", k, v) } fmt.Fprintf(w, "host = %q\n", r.RemoteAddr) if err := r.ParseForm(); err != nil{ log.Print(err) } for k, v := range r.Form{ fmt.Fprintf(w, "Form[%q] = %q\n", k, v) } } func main(){ http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request){ lissajous(w) }) log.Fatal(http.ListenAndServe("localhost:8000", nil)) }

    只能输出gif,但不知道怎么修改题目要求那个东西。有大佬做出来告诉一下。

    Processed: 0.012, SQL: 8