## 2019年9月14日土曜日

### Go - 関数 - 複数戻り値 - 名前付き結果と空リターン文

プログラミング言語Go (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES) (Alan A.A. Donovan(著)、Brian W. Kernighan(著)、柴田 芳樹(翻訳)、丸善出版)の第5章(関数)、5.3(複数戻り値)、練習問題5.6の解答を求めてみる。

コード

```package main

import (
"fmt"
"log"
"math"
"net/http"
"strconv"
)

const (
width, height = 600, 320
cells         = 100
xyrange       = 30.0
xyscale       = width / 2 / xyrange
zscale        = height * 0.4
angle         = math.Pi / 6
)

var sin30, cos30 = math.Sin(angle), math.Cos(angle)

func main() {
handler := func(w http.ResponseWriter, r *http.Request) {
fmt.Println(r.URL)
if err := r.ParseForm(); err != nil {
log.Print(err)
} else {
var (
formWidth, formHeight int
formColor             string
)
form, bln := r.Form["width"]
if bln {
t, err := strconv.Atoi(form[0])
if err != nil {
formWidth = width
} else {
formWidth = t
}
} else {
formWidth = width
}
form, bln = r.Form["height"]
if bln {
t, err := strconv.Atoi(form[0])
if err != nil {
formHeight = height
} else {
formHeight = t
}
} else {
formHeight = height
}
form, bln = r.Form["color"]
if bln {
formColor = form[0]
} else {
formColor = "green"
}
fmt.Println(formWidth, formHeight, formColor)
fmt.Fprintf(w, "<svg xmlns='http://www.w3.org/2000/svg' "+
"style='stroke: grey; fill: %s; stroke-wdith: 0.7' "+
"width='%d' height='%d'>\n", formColor, formWidth, formHeight)
for i := 0; i < cells; i++ {
for j := 0; j < cells; j++ {
ax, ay, aOk := corner(i+1, j)
bx, by, bOk := corner(i, j)
cx, cy, cOk := corner(i, j+1)
dx, dy, dOk := corner(i+1, j+1)
if aOk && bOk && cOk && dOk {
fmt.Fprintf(w,
"<polygon points='%g,%g,%g,%g,%g,%g,%g,%g' />\n",
ax, ay, bx, by, cx, cy, dx, dy)
}
}
}
fmt.Fprintf(w, "</svg>\n")
}
}
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe("localhost:8000", nil))
}

func corner(i, j int) (sx float64, sy float64, finite bool) {
x := xyrange * (float64(i)/cells - 0.5)
y := xyrange * (float64(j)/cells - 0.5)
z, ok := f(x, y)
if !ok {
fmt.Printf("z=%g\n", z)
sx = 0
sy = 0
finite = false
return
}
sx = width/2 + (x-y)*cos30*xyscale
sy = height/2 + (x+y)*sin30*xyscale - z*zscale
if !isFinite(sx) || !isFinite(sy) {
fmt.Printf("sx=%g, sy=%g\n", sx, sy)
finite = false
sx = 0
sy = 0
finite = false
}
return
}

func f(x, y float64) (value float64, finite bool) {
r := math.Hypot(x, y)
value = math.Sin(r) / r
finite = isFinite(value)
if !finite {
fmt.Printf("value=%g\n", value)
}
return
}

func isFinite(f float64) (finite bool) {
finite = math.Abs(f) < math.Inf(1)
return
}
```

```\$ go run sample6.go
/
600 320 green
value=NaN
z=NaN
value=NaN
z=NaN
value=NaN
z=NaN
value=NaN
z=NaN
/
600 320 green
value=NaN
z=NaN
value=NaN
z=NaN
value=NaN
z=NaN
value=NaN
z=NaN
/
600 320 green
value=NaN
z=NaN
value=NaN
z=NaN
value=NaN
z=NaN
value=NaN
z=NaN
/?color=red&width=500&height=250
500 250 red
value=NaN
z=NaN
value=NaN
z=NaN
value=NaN
z=NaN
value=NaN
z=NaN
/favicon.ico
600 320 green
value=NaN
z=NaN
value=NaN
z=NaN
value=NaN
z=NaN
value=NaN
z=NaN
/
600 320 green
value=NaN
z=NaN
value=NaN
z=NaN
value=NaN
z=NaN
value=NaN
z=NaN
/?width=320&height=600
320 600 green
value=NaN
z=NaN
value=NaN
z=NaN
value=NaN
z=NaN
value=NaN
z=NaN
/favicon.ico
600 320 green
value=NaN
z=NaN
value=NaN
z=NaN
value=NaN
z=NaN
value=NaN
z=NaN
signal: terminated
\$
```