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
)
resp
.Body
.Close()
if err
!= nil{
fmt
.Fprintf(os
.Stderr
, "fetch: reading %s: %v\n", url
, err
)
os
.Exit(1)
}
}
}
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,但不知道怎么修改题目要求那个东西。有大佬做出来告诉一下。