remove unused file

pull/1/head
chai2010 2015-12-25 12:30:53 +08:00
parent 745a165b6f
commit 2284164524
195 changed files with 8 additions and 67059 deletions

8
.gitignore vendored
View File

@ -14,3 +14,11 @@ _book
*.epub
*.mobi
*.pdf
# user defined
vendor
docs
cover_bgd.png
cover_patch.png
/images/cover.png
/images/gopher/go_lang_mascot_by_kirael_art-d7kunhu.gif

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1 +0,0 @@
TODO

View File

@ -1,2 +0,0 @@
**練習 1.1:** 脩改echo程序使其能夠打印os.Args[0]。

View File

@ -1 +0,0 @@
**練習 1.2:** 脩改echo程序使其打印value和index每個value和index顯示一行。

View File

@ -1,2 +0,0 @@
**練習 1.3:** 上手實踐前麫提到的strings.Join和直接Println併觀察輸齣結果的區彆。

View File

@ -1,2 +0,0 @@
**練習 1.4:** 脩改dup2使其可以打印重復的行分彆齣現在哪些文件。

View File

@ -1 +0,0 @@
**練習 1.5:** 脩改前麫的Lissajous程序裏的調色闆由緑色改為黑色。我們可以用color.RGBA{0xRR, 0xGG, 0xBB}來得到#RRGGBB這個色值三個十六進製的字符串分彆代錶紅、緑、藍像素。

View File

@ -1,2 +0,0 @@
**練習 1.6:** 脩改Lissajous程序脩改其調色闆來生成更豐富的顔色然後脩改SetColorIndex的第三個參數看看顯示結果吧。

View File

@ -1,2 +0,0 @@
**練習 1.7:** 函數調用io.Copy(dst, src)會從src中讀取內容併將讀到的結果寫入到dst中使用這個函數替代掉例子中的ioutil.ReadAll來拷貝響應結構體到os.Stdout避免申請一個緩衝區(例子中的b)來存儲。記得處理io.Copy返迴結果中的錯誤。

View File

@ -1,2 +0,0 @@
**練習 1.8:** 脩改fetch這個範例如果輸入的url參數沒有http://前綴的話為這個url加上該前綴。你可能會用到strings.HasPrefix這個函數。

View File

@ -1,2 +0,0 @@
**練習 1.9:** 脩改fetch打印齣HTTP協議的狀態碼可以從resp.Status變量得到該狀態碼。

View File

@ -1,2 +0,0 @@
**練習 1.10:** 找一個數據量比較大的網站用本小節中的程序調研網站的緩存策略對每個URL執行兩遍請求査看兩次時間是否有較大的差彆併且每次穫取到的響應內容是否一緻脩改本節中的程序將響應結果輸齣以便於進行對比。

View File

@ -1,2 +0,0 @@
**練習 1.11:** Try fetchall with longer argument lists, such as samples from the top million web sites available at alexa.com. How does the program behave if a web site just doesnt respond? (Section 8.9 describes mechanisms for coping in such cases.)

View File

@ -1,2 +0,0 @@
**練習 1.12:** 脩改Lissajour服務從URL讀取變量比如你可以訪問http://localhost:8000/?cycles=20這個URL這樣訪問可以將程序裏的cycles默認的5脩改為20。字符串轉換為數字可以調用strconv.Atoi函數。你可以在dodoc裏査看strconv.Atoi的詳細說明。

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,62 +0,0 @@
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ingore
package main
import (
"bufio"
"bytes"
"fmt"
"io/ioutil"
"log"
"os"
"strings"
"unicode/utf8"
)
func main() {
f, err := os.Open("./TSCharacters.txt")
if err != nil {
log.Fatal("open failed:", err)
}
defer f.Close()
br := bufio.NewReader(f)
var out bytes.Buffer
fmt.Fprintf(&out, `
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Auto generated by go generate, DO NOT EDIT !!!
package main
var _TSCharactersMap = map[rune]rune{
`[1:])
for i := 0; i < 1<<20; i++ {
data, isPrefix, err := br.ReadLine()
if err != nil || isPrefix {
break
}
if !utf8.ValidString(string(data)) {
continue
}
line := strings.Replace(string(data), "\t", " ", -1)
ss := strings.Split(string(line), " ")
if len(ss) >= 2 {
tw := strings.TrimSpace(ss[0])
zh := strings.TrimSpace(ss[1])
fmt.Fprintf(&out, "\t'%s': '%s',\n", tw, zh)
}
}
fmt.Fprintf(&out, "}\n")
ioutil.WriteFile("z_TSCharacters.go", []byte(out.Bytes()), 0666)
}

21
vendor/gopl.io/README.md generated vendored
View File

@ -1,21 +0,0 @@
# The Go Programming Language
This repository provides the downloadable example programs
for the book, "The Go Programming Language"; see http://www.gopl.io.
These example programs are licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>.<br/>
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png"/></a>
You can download, build, and run the programs with the following commands:
$ export GOPATH=$HOME/gobook # choose workspace directory
$ go get gopl.io/ch1/helloworld # fetch, build, install
$ $GOPATH/bin/helloworld # run
Hello, 世界
Many of the programs contain comments of the form `//!+` and `//!-`.
These comments bracket the parts of the programs that are excerpted in the
book; you can safely ignore them. In a few cases, programs
have been reformatted in an unnatural way so that they can be presented
in stages in the book.

31
vendor/gopl.io/ch1/dup1/main.go generated vendored
View File

@ -1,31 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 8.
//!+
// Dup1 prints the text of each line that appears more than
// once in the standard input, preceded by its count.
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
counts := make(map[string]int)
input := bufio.NewScanner(os.Stdin)
for input.Scan() {
counts[input.Text()]++
}
// NOTE: ignoring potential errors from input.Err()
for line, n := range counts {
if n > 1 {
fmt.Printf("%d\t%s\n", n, line)
}
}
}
//!-

48
vendor/gopl.io/ch1/dup2/main.go generated vendored
View File

@ -1,48 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 10.
//!+
// Dup2 prints the count and text of lines that appear more than once
// in the input. It reads from stdin or from a list of named files.
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
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() {
counts[input.Text()]++
}
// NOTE: ignoring potential errors from input.Err()
}
//!-

38
vendor/gopl.io/ch1/dup3/main.go generated vendored
View File

@ -1,38 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 12.
//!+
// Dup3 prints the count and text of lines that
// appear more than once in the named input files.
package main
import (
"fmt"
"io/ioutil"
"os"
"strings"
)
func main() {
counts := make(map[string]int)
for _, filename := range os.Args[1:] {
data, err := ioutil.ReadFile(filename)
if err != nil {
fmt.Fprintf(os.Stderr, "dup3: %v\n", err)
continue
}
for _, line := range strings.Split(string(data), "\n") {
counts[line]++
}
}
for line, n := range counts {
if n > 1 {
fmt.Printf("%d\t%s\n", n, line)
}
}
}
//!-

24
vendor/gopl.io/ch1/echo1/main.go generated vendored
View File

@ -1,24 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 4.
//!+
// Echo1 prints its command-line arguments.
package main
import (
"fmt"
"os"
)
func main() {
var s, sep string
for i := 1; i < len(os.Args); i++ {
s += sep + os.Args[i]
sep = " "
}
fmt.Println(s)
}
//!-

24
vendor/gopl.io/ch1/echo2/main.go generated vendored
View File

@ -1,24 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 6.
//!+
// Echo2 prints its command-line arguments.
package main
import (
"fmt"
"os"
)
func main() {
s, sep := "", ""
for _, arg := range os.Args[1:] {
s += sep + arg
sep = " "
}
fmt.Println(s)
}
//!-

20
vendor/gopl.io/ch1/echo3/main.go generated vendored
View File

@ -1,20 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 8.
// Echo3 prints its command-line arguments.
package main
import (
"fmt"
"os"
"strings"
)
//!+
func main() {
fmt.Println(strings.Join(os.Args[1:], " "))
}
//!-

34
vendor/gopl.io/ch1/fetch/main.go generated vendored
View File

@ -1,34 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 16.
//!+
// Fetch prints the content found at each specified URL.
package main
import (
"fmt"
"io/ioutil"
"net/http"
"os"
)
func main() {
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)
}
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)
}
}
//!-

49
vendor/gopl.io/ch1/fetchall/main.go generated vendored
View File

@ -1,49 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 17.
//!+
// Fetchall fetches URLs in parallel and reports their times and sizes.
package main
import (
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"time"
)
func main() {
start := time.Now()
ch := make(chan string)
for _, url := range os.Args[1:] {
go fetch(url, ch) // start a goroutine
}
for range os.Args[1:] {
fmt.Println(<-ch) // receive from channel 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) // send to channel ch
return
}
nbytes, err := io.Copy(ioutil.Discard, resp.Body)
resp.Body.Close() // don't leak resources
if err != nil {
ch <- fmt.Sprintf("while reading %s: %v", url, err)
return
}
secs := time.Since(start).Seconds()
ch <- fmt.Sprintf("%.2fs %7d %s", secs, nbytes, url)
}
//!-

View File

@ -1,16 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 1.
// Helloworld is our first Go program.
//!+
package main
import "fmt"
func main() {
fmt.Println("Hello, 世界")
}
//!-

86
vendor/gopl.io/ch1/lissajous/main.go generated vendored
View File

@ -1,86 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// Run with "web" command-line argument for web server.
// See page 13.
//!+main
// Lissajous generates GIF animations of random Lissajous figures.
package main
import (
"image"
"image/color"
"image/gif"
"io"
"math"
"math/rand"
"os"
)
//!-main
// Packages not needed by version in book.
import (
"log"
"net/http"
"time"
)
//!+main
var palette = []color.Color{color.White, color.Black}
const (
whiteIndex = 0 // first color in palette
blackIndex = 1 // next color in palette
)
func main() {
//!-main
// The sequence of images is deterministic unless we seed
// the pseudo-random number generator using the current time.
// Thanks to Randall McPherson for pointing out the omission.
rand.Seed(time.Now().UTC().UnixNano())
if len(os.Args) > 1 && os.Args[1] == "web" {
//!+http
handler := func(w http.ResponseWriter, r *http.Request) {
lissajous(w)
}
http.HandleFunc("/", handler)
//!-http
log.Fatal(http.ListenAndServe("localhost:8000", nil))
return
}
//!+main
lissajous(os.Stdout)
}
func lissajous(out io.Writer) {
const (
cycles = 5 // number of complete x oscillator revolutions
res = 0.001 // angular resolution
size = 100 // image canvas covers [-size..+size]
nframes = 64 // number of animation frames
delay = 8 // delay between frames in 10ms units
)
freq := rand.Float64() * 3.0 // relative frequency of y oscillator
anim := gif.GIF{LoopCount: nframes}
phase := 0.0 // phase difference
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) // NOTE: ignoring encoding errors
}
//!-main

26
vendor/gopl.io/ch1/server1/main.go generated vendored
View File

@ -1,26 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 19.
//!+
// Server1 is a minimal "echo" server.
package main
import (
"fmt"
"log"
"net/http"
)
func main() {
http.HandleFunc("/", handler) // each request calls handler
log.Fatal(http.ListenAndServe("localhost:8000", nil))
}
// handler echoes the Path component of the requested URL.
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "URL.Path = %q\n", r.URL.Path)
}
//!-

41
vendor/gopl.io/ch1/server2/main.go generated vendored
View File

@ -1,41 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 20.
//!+
// Server2 is a minimal "echo" and counter server.
package main
import (
"fmt"
"log"
"net/http"
"sync"
)
var mu sync.Mutex
var count int
func main() {
http.HandleFunc("/", handler)
http.HandleFunc("/count", counter)
log.Fatal(http.ListenAndServe("localhost:8000", nil))
}
// handler echoes the Path component of the requested URL.
func handler(w http.ResponseWriter, r *http.Request) {
mu.Lock()
count++
mu.Unlock()
fmt.Fprintf(w, "URL.Path = %q\n", r.URL.Path)
}
// counter echoes the number of calls so far.
func counter(w http.ResponseWriter, r *http.Request) {
mu.Lock()
fmt.Fprintf(w, "Count %d\n", count)
mu.Unlock()
}
//!-

37
vendor/gopl.io/ch1/server3/main.go generated vendored
View File

@ -1,37 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 21.
// Server3 is an "echo" server that displays request parameters.
package main
import (
"fmt"
"log"
"net/http"
)
func main() {
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe("localhost:8000", nil))
}
//!+handler
// handler echoes the HTTP request.
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.Host)
fmt.Fprintf(w, "RemoteAddr = %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)
}
}
//!-handler

19
vendor/gopl.io/ch10/cross/main.go generated vendored
View File

@ -1,19 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 295.
// The cross command prints the values of GOOS and GOARCH for this target.
package main
import (
"fmt"
"runtime"
)
//!+
func main() {
fmt.Println(runtime.GOOS, runtime.GOARCH)
}
//!-

52
vendor/gopl.io/ch10/jpeg/main.go generated vendored
View File

@ -1,52 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 287.
//!+main
// The jpeg command reads a PNG image from the standard input
// and writes it as a JPEG image to the standard output.
package main
import (
"fmt"
"image"
"image/jpeg"
_ "image/png" // register PNG decoder
"io"
"os"
)
func main() {
if err := toJPEG(os.Stdin, os.Stdout); err != nil {
fmt.Fprintf(os.Stderr, "jpeg: %v\n", err)
os.Exit(1)
}
}
func toJPEG(in io.Reader, out io.Writer) error {
img, kind, err := image.Decode(in)
if err != nil {
return err
}
fmt.Fprintln(os.Stderr, "Input format =", kind)
return jpeg.Encode(out, img, &jpeg.Options{Quality: 95})
}
//!-main
/*
//!+with
$ go build gopl.io/ch3/mandelbrot
$ go build gopl.io/ch10/jpeg
$ ./mandelbrot | ./jpeg >mandelbrot.jpg
Input format = png
//!-with
//!+without
$ go build gopl.io/ch10/jpeg
$ ./mandelbrot | ./jpeg >mandelbrot.jpg
jpeg: image: unknown format
//!-without
*/

41
vendor/gopl.io/ch11/echo/echo.go generated vendored
View File

@ -1,41 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 308.
//!+
// Echo prints its command-line arguments.
package main
import (
"flag"
"fmt"
"io"
"os"
"strings"
)
var (
n = flag.Bool("n", false, "omit trailing newline")
s = flag.String("s", " ", "separator")
)
var out io.Writer = os.Stdout // modified during testing
func main() {
flag.Parse()
if err := echo(!*n, *s, flag.Args()); err != nil {
fmt.Fprintf(os.Stderr, "echo: %v\n", err)
os.Exit(1)
}
}
func echo(newline bool, sep string, args []string) error {
fmt.Fprint(out, strings.Join(args, sep))
if newline {
fmt.Fprintln(out)
}
return nil
}
//!-

View File

@ -1,45 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// Test of echo command. Run with: go test gopl.io/ch11/echo
//!+
package main
import (
"bytes"
"fmt"
"testing"
)
func TestEcho(t *testing.T) {
var tests = []struct {
newline bool
sep string
args []string
want string
}{
{true, "", []string{}, "\n"},
{false, "", []string{}, ""},
{true, "\t", []string{"one", "two", "three"}, "one\ttwo\tthree\n"},
{true, ",", []string{"a", "b", "c"}, "a,b,c\n"},
{false, ":", []string{"1", "2", "3"}, "1:2:3"},
}
for _, test := range tests {
descr := fmt.Sprintf("echo(%v, %q, %q)",
test.newline, test.sep, test.args)
out = new(bytes.Buffer) // captured output
if err := echo(test.newline, test.sep, test.args); err != nil {
t.Errorf("%s failed: %v", descr, err)
continue
}
got := out.(*bytes.Buffer).String()
if got != test.want {
t.Errorf("%s = %q, want %q", descr, got, test.want)
}
}
}
//!-

View File

@ -1,45 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 311.
// Package storage is part of a hypothetical cloud storage server.
//!+main
package storage
import (
"fmt"
"log"
"net/smtp"
)
var usage = make(map[string]int64)
func bytesInUse(username string) int64 { return usage[username] }
// Email sender configuration.
// NOTE: never put passwords in source code!
const sender = "notifications@example.com"
const password = "correcthorsebatterystaple"
const hostname = "smtp.example.com"
const template = `Warning: you are using %d bytes of storage,
%d%% of your quota.`
func CheckQuota(username string) {
used := bytesInUse(username)
const quota = 1000000000 // 1GB
percent := 100 * used / quota
if percent < 90 {
return // OK
}
msg := fmt.Sprintf(template, used, percent)
auth := smtp.PlainAuth("", sender, password, hostname)
err := smtp.SendMail(hostname+":587", auth, sender,
[]string{username}, []byte(msg))
if err != nil {
log.Printf("smtp.SendMail(%s) failed: %s", username, err)
}
}
//!-main

View File

@ -1,53 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//!+test
package storage
import (
"strings"
"testing"
)
func TestCheckQuotaNotifiesUser(t *testing.T) {
var notifiedUser, notifiedMsg string
notifyUser = func(user, msg string) {
notifiedUser, notifiedMsg = user, msg
}
const user = "joe@example.org"
usage[user] = 980000000 // simulate a 980MB-used condition
CheckQuota(user)
if notifiedUser == "" && notifiedMsg == "" {
t.Fatalf("notifyUser not called")
}
if notifiedUser != user {
t.Errorf("wrong user (%s) notified, want %s",
notifiedUser, user)
}
const wantSubstring = "98% of your quota"
if !strings.Contains(notifiedMsg, wantSubstring) {
t.Errorf("unexpected notification message <<%s>>, "+
"want substring %q", notifiedMsg, wantSubstring)
}
}
//!-test
/*
//!+defer
func TestCheckQuotaNotifiesUser(t *testing.T) {
// Save and restore original notifyUser.
saved := notifyUser
defer func() { notifyUser = saved }()
// Install the test's fake notifyUser.
var notifiedUser, notifiedMsg string
notifyUser = func(user, msg string) {
notifiedUser, notifiedMsg = user, msg
}
// ...rest of test...
}
//!-defer
*/

View File

@ -1,49 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 312.
// Package storage is part of a hypothetical cloud storage server.
package storage
import (
"fmt"
"log"
"net/smtp"
)
var usage = make(map[string]int64)
func bytesInUse(username string) int64 { return usage[username] }
// E-mail sender configuration.
// NOTE: never put passwords in source code!
const sender = "notifications@example.com"
const password = "correcthorsebatterystaple"
const hostname = "smtp.example.com"
const template = `Warning: you are using %d bytes of storage,
%d%% of your quota.`
//!+factored
var notifyUser = func(username, msg string) {
auth := smtp.PlainAuth("", sender, password, hostname)
err := smtp.SendMail(hostname+":587", auth, sender,
[]string{username}, []byte(msg))
if err != nil {
log.Printf("smtp.SendEmail(%s) failed: %s", username, err)
}
}
func CheckQuota(username string) {
used := bytesInUse(username)
const quota = 1000000000 // 1GB
percent := 100 * used / quota
if percent < 90 {
return // OK
}
msg := fmt.Sprintf(template, used, percent)
notifyUser(username, msg)
}
//!-factored

21
vendor/gopl.io/ch11/word1/word.go generated vendored
View File

@ -1,21 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 303.
//!+
// Package word provides utilities for word games.
package word
// IsPalindrome reports whether s reads the same forward and backward.
// (Our first attempt.)
func IsPalindrome(s string) bool {
for i := range s {
if s[i] != s[len(s)-1-i] {
return false
}
}
return true
}
//!-

View File

@ -1,43 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//!+test
package word
import "testing"
func TestPalindrome(t *testing.T) {
if !IsPalindrome("detartrated") {
t.Error(`IsPalindrome("detartrated") = false`)
}
if !IsPalindrome("kayak") {
t.Error(`IsPalindrome("kayak") = false`)
}
}
func TestNonPalindrome(t *testing.T) {
if IsPalindrome("palindrome") {
t.Error(`IsPalindrome("palindrome") = true`)
}
}
//!-test
// The tests below are expected to fail.
// See package gopl.io/ch11/word2 for the fix.
//!+more
func TestFrenchPalindrome(t *testing.T) {
if !IsPalindrome("été") {
t.Error(`IsPalindrome("été") = false`)
}
}
func TestCanalPalindrome(t *testing.T) {
input := "A man, a plan, a canal: Panama"
if !IsPalindrome(input) {
t.Errorf(`IsPalindrome(%q) = false`, input)
}
}
//!-more

29
vendor/gopl.io/ch11/word2/word.go generated vendored
View File

@ -1,29 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 305.
//!+
// Package word provides utilities for word games.
package word
import "unicode"
// IsPalindrome reports whether s reads the same forward and backward.
// Letter case is ignored, as are non-letters.
func IsPalindrome(s string) bool {
var letters []rune
for _, r := range s {
if unicode.IsLetter(r) {
letters = append(letters, unicode.ToLower(r))
}
}
for i := range letters {
if letters[i] != letters[len(letters)-1-i] {
return false
}
}
return true
}
//!-

View File

@ -1,148 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
package word
import (
"fmt"
"math/rand"
"time"
)
//!+bench
import "testing"
//!-bench
//!+test
func TestIsPalindrome(t *testing.T) {
var tests = []struct {
input string
want bool
}{
{"", true},
{"a", true},
{"aa", true},
{"ab", false},
{"kayak", true},
{"detartrated", true},
{"A man, a plan, a canal: Panama", true},
{"Evil I did dwell; lewd did I live.", true},
{"Able was I ere I saw Elba", true},
{"été", true},
{"Et se resservir, ivresse reste.", true},
{"palindrome", false}, // non-palindrome
{"desserts", false}, // semi-palindrome
}
for _, test := range tests {
if got := IsPalindrome(test.input); got != test.want {
t.Errorf("IsPalindrome(%q) = %v", test.input, got)
}
}
}
//!-test
//!+bench
func BenchmarkIsPalindrome(b *testing.B) {
for i := 0; i < b.N; i++ {
IsPalindrome("A man, a plan, a canal: Panama")
}
}
//!-bench
//!+example
func ExampleIsPalindrome() {
fmt.Println(IsPalindrome("A man, a plan, a canal: Panama"))
fmt.Println(IsPalindrome("palindrome"))
// Output:
// true
// false
}
//!-example
/*
//!+random
import "math/rand"
//!-random
*/
//!+random
// randomPalindrome returns a palindrome whose length and contents
// are derived from the pseudo-random number generator rng.
func randomPalindrome(rng *rand.Rand) string {
n := rng.Intn(25) // random length up to 24
runes := make([]rune, n)
for i := 0; i < (n+1)/2; i++ {
r := rune(rng.Intn(0x1000)) // random rune up to '\u0999'
runes[i] = r
runes[n-1-i] = r
}
return string(runes)
}
func TestRandomPalindromes(t *testing.T) {
// Initialize a pseudo-random number generator.
seed := time.Now().UTC().UnixNano()
t.Logf("Random seed: %d", seed)
rng := rand.New(rand.NewSource(seed))
for i := 0; i < 1000; i++ {
p := randomPalindrome(rng)
if !IsPalindrome(p) {
t.Errorf("IsPalindrome(%q) = false", p)
}
}
}
//!-random
/*
// Answer for Exercicse 11.1: Modify randomPalindrome to exercise
// IsPalindrome's handling of punctuation and spaces.
// WARNING: the conversion r -> upper -> lower doesn't preserve
// the value of r in some cases, e.g., µ Μ, ſ S, ı I
// randomPalindrome returns a palindrome whose length and contents
// are derived from the pseudo-random number generator rng.
func randomNoisyPalindrome(rng *rand.Rand) string {
n := rng.Intn(25) // random length up to 24
runes := make([]rune, n)
for i := 0; i < (n+1)/2; i++ {
r := rune(rng.Intn(0x200)) // random rune up to \u99
runes[i] = r
r1 := r
if unicode.IsLetter(r) && unicode.IsLower(r) {
r = unicode.ToUpper(r)
if unicode.ToLower(r) != r1 {
fmt.Printf("cap? %c %c\n", r1, r)
}
}
runes[n-1-i] = r
}
return "?" + string(runes) + "!"
}
func TestRandomNoisyPalindromes(t *testing.T) {
// Initialize a pseudo-random number generator.
seed := time.Now().UTC().UnixNano()
t.Logf("Random seed: %d", seed)
rng := rand.New(rand.NewSource(seed))
n := 0
for i := 0; i < 1000; i++ {
p := randomNoisyPalindrome(rng)
if !IsPalindrome(p) {
t.Errorf("IsNoisyPalindrome(%q) = false", p)
n++
}
}
fmt.Fprintf(os.Stderr, "fail = %d\n", n)
}
*/

View File

@ -1,90 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 333.
// Package display provides a means to display structured data.
package display
import (
"fmt"
"reflect"
"strconv"
)
//!+Display
func Display(name string, x interface{}) {
fmt.Printf("Display %s (%T):\n", name, x)
display(name, reflect.ValueOf(x))
}
//!-Display
// formatAtom formats a value without inspecting its internal structure.
// It is a copy of the the function in gopl.io/ch11/format.
func formatAtom(v reflect.Value) string {
switch v.Kind() {
case reflect.Invalid:
return "invalid"
case reflect.Int, reflect.Int8, reflect.Int16,
reflect.Int32, reflect.Int64:
return strconv.FormatInt(v.Int(), 10)
case reflect.Uint, reflect.Uint8, reflect.Uint16,
reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return strconv.FormatUint(v.Uint(), 10)
// ...floating-point and complex cases omitted for brevity...
case reflect.Bool:
if v.Bool() {
return "true"
}
return "false"
case reflect.String:
return strconv.Quote(v.String())
case reflect.Chan, reflect.Func, reflect.Ptr,
reflect.Slice, reflect.Map:
return v.Type().String() + " 0x" +
strconv.FormatUint(uint64(v.Pointer()), 16)
default: // reflect.Array, reflect.Struct, reflect.Interface
return v.Type().String() + " value"
}
}
//!+display
func display(path string, v reflect.Value) {
switch v.Kind() {
case reflect.Invalid:
fmt.Printf("%s = invalid\n", path)
case reflect.Slice, reflect.Array:
for i := 0; i < v.Len(); i++ {
display(fmt.Sprintf("%s[%d]", path, i), v.Index(i))
}
case reflect.Struct:
for i := 0; i < v.NumField(); i++ {
fieldPath := fmt.Sprintf("%s.%s", path, v.Type().Field(i).Name)
display(fieldPath, v.Field(i))
}
case reflect.Map:
for _, key := range v.MapKeys() {
display(fmt.Sprintf("%s[%s]", path,
formatAtom(key)), v.MapIndex(key))
}
case reflect.Ptr:
if v.IsNil() {
fmt.Printf("%s = nil\n", path)
} else {
display(fmt.Sprintf("(*%s)", path), v.Elem())
}
case reflect.Interface:
if v.IsNil() {
fmt.Printf("%s = nil\n", path)
} else {
fmt.Printf("%s.type = %s\n", path, v.Elem().Type())
display(path+".value", v.Elem())
}
default: // basic types, channels, funcs
fmt.Printf("%s = %s\n", path, formatAtom(v))
}
}
//!-display

View File

@ -1,259 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
package display
import (
"io"
"net"
"os"
"reflect"
"sync"
"testing"
"gopl.io/ch7/eval"
)
// NOTE: we can't use !+..!- comments to excerpt these tests
// into the book because it defeats the Example mechanism,
// which requires the // Output comment to be at the end
// of the function.
func Example_expr() {
e, _ := eval.Parse("sqrt(A / pi)")
Display("e", e)
// Output:
// Display e (eval.call):
// e.fn = "sqrt"
// e.args[0].type = eval.binary
// e.args[0].value.op = 47
// e.args[0].value.x.type = eval.Var
// e.args[0].value.x.value = "A"
// e.args[0].value.y.type = eval.Var
// e.args[0].value.y.value = "pi"
}
func Example_slice() {
Display("slice", []*int{new(int), nil})
// Output:
// Display slice ([]*int):
// (*slice[0]) = 0
// slice[1] = nil
}
func Example_nilInterface() {
var w io.Writer
Display("w", w)
// Output:
// Display w (<nil>):
// w = invalid
}
func Example_ptrToInterface() {
var w io.Writer
Display("&w", &w)
// Output:
// Display &w (*io.Writer):
// (*&w) = nil
}
func Example_struct() {
Display("x", struct{ x interface{} }{3})
// Output:
// Display x (struct { x interface {} }):
// x.x.type = int
// x.x.value = 3
}
func Example_interface() {
var i interface{} = 3
Display("i", i)
// Output:
// Display i (int):
// i = 3
}
func Example_ptrToInterface2() {
var i interface{} = 3
Display("&i", &i)
// Output:
// Display &i (*interface {}):
// (*&i).type = int
// (*&i).value = 3
}
func Example_array() {
Display("x", [1]interface{}{3})
// Output:
// Display x ([1]interface {}):
// x[0].type = int
// x[0].value = 3
}
func Example_movie() {
//!+movie
type Movie struct {
Title, Subtitle string
Year int
Color bool
Actor map[string]string
Oscars []string
Sequel *string
}
//!-movie
//!+strangelove
strangelove := Movie{
Title: "Dr. Strangelove",
Subtitle: "How I Learned to Stop Worrying and Love the Bomb",
Year: 1964,
Color: false,
Actor: map[string]string{
"Dr. Strangelove": "Peter Sellers",
"Grp. Capt. Lionel Mandrake": "Peter Sellers",
"Pres. Merkin Muffley": "Peter Sellers",
"Gen. Buck Turgidson": "George C. Scott",
"Brig. Gen. Jack D. Ripper": "Sterling Hayden",
`Maj. T.J. "King" Kong`: "Slim Pickens",
},
Oscars: []string{
"Best Actor (Nomin.)",
"Best Adapted Screenplay (Nomin.)",
"Best Director (Nomin.)",
"Best Picture (Nomin.)",
},
}
//!-strangelove
Display("strangelove", strangelove)
// We don't use an Output: comment since displaying
// a map is nondeterministic.
/*
//!+output
Display strangelove (display.Movie):
strangelove.Title = "Dr. Strangelove"
strangelove.Subtitle = "How I Learned to Stop Worrying and Love the Bomb"
strangelove.Year = 1964
strangelove.Color = false
strangelove.Actor["Gen. Buck Turgidson"] = "George C. Scott"
strangelove.Actor["Brig. Gen. Jack D. Ripper"] = "Sterling Hayden"
strangelove.Actor["Maj. T.J. \"King\" Kong"] = "Slim Pickens"
strangelove.Actor["Dr. Strangelove"] = "Peter Sellers"
strangelove.Actor["Grp. Capt. Lionel Mandrake"] = "Peter Sellers"
strangelove.Actor["Pres. Merkin Muffley"] = "Peter Sellers"
strangelove.Oscars[0] = "Best Actor (Nomin.)"
strangelove.Oscars[1] = "Best Adapted Screenplay (Nomin.)"
strangelove.Oscars[2] = "Best Director (Nomin.)"
strangelove.Oscars[3] = "Best Picture (Nomin.)"
strangelove.Sequel = nil
//!-output
*/
}
// This test ensures that the program terminates without crashing.
func Test(t *testing.T) {
// Some other values (YMMV)
Display("os.Stderr", os.Stderr)
// Output:
// Display os.Stderr (*os.File):
// (*(*os.Stderr).file).fd = 2
// (*(*os.Stderr).file).name = "/dev/stderr"
// (*(*os.Stderr).file).nepipe = 0
var w io.Writer = os.Stderr
Display("&w", &w)
// Output:
// Display &w (*io.Writer):
// (*&w).type = *os.File
// (*(*(*&w).value).file).fd = 2
// (*(*(*&w).value).file).name = "/dev/stderr"
// (*(*(*&w).value).file).nepipe = 0
var locker sync.Locker = new(sync.Mutex)
Display("(&locker)", &locker)
// Output:
// Display (&locker) (*sync.Locker):
// (*(&locker)).type = *sync.Mutex
// (*(*(&locker)).value).state = 0
// (*(*(&locker)).value).sema = 0
Display("locker", locker)
// Output:
// Display locker (*sync.Mutex):
// (*locker).state = 0
// (*locker).sema = 0
// (*(&locker)) = nil
locker = nil
Display("(&locker)", &locker)
// Output:
// Display (&locker) (*sync.Locker):
// (*(&locker)) = nil
ips, _ := net.LookupHost("golang.org")
Display("ips", ips)
// Output:
// Display ips ([]string):
// ips[0] = "173.194.68.141"
// ips[1] = "2607:f8b0:400d:c06::8d"
// Even metarecursion! (YMMV)
Display("rV", reflect.ValueOf(os.Stderr))
// Output:
// Display rV (reflect.Value):
// (*rV.typ).size = 8
// (*rV.typ).ptrdata = 8
// (*rV.typ).hash = 871609668
// (*rV.typ)._ = 0
// ...
// a pointer that points to itself
type P *P
var p P
p = &p
if false {
Display("p", p)
// Output:
// Display p (display.P):
// ...stuck, no output...
}
// a map that contains itself
type M map[string]M
m := make(M)
m[""] = m
if false {
Display("m", m)
// Output:
// Display m (display.M):
// ...stuck, no output...
}
// a slice that contains itself
type S []S
s := make(S, 1)
s[0] = s
if false {
Display("s", s)
// Output:
// Display s (display.S):
// ...stuck, no output...
}
// a linked list that eats its own tail
type Cycle struct {
Value int
Tail *Cycle
}
var c Cycle
c = Cycle{42, &c}
if false {
Display("c", c)
// Output:
// Display c (display.Cycle):
// c.Value = 42
// (*c.Tail).Value = 42
// (*(*c.Tail).Tail).Value = 42
// ...ad infinitum...
}
}

44
vendor/gopl.io/ch12/format/format.go generated vendored
View File

@ -1,44 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 332.
// Package format provides an Any function that can format any value.
//!+
package format
import (
"reflect"
"strconv"
)
// Any formats any value as a string.
func Any(value interface{}) string {
return formatAtom(reflect.ValueOf(value))
}
// formatAtom formats a value without inspecting its internal structure.
func formatAtom(v reflect.Value) string {
switch v.Kind() {
case reflect.Invalid:
return "invalid"
case reflect.Int, reflect.Int8, reflect.Int16,
reflect.Int32, reflect.Int64:
return strconv.FormatInt(v.Int(), 10)
case reflect.Uint, reflect.Uint8, reflect.Uint16,
reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return strconv.FormatUint(v.Uint(), 10)
// ...floating-point and complex cases omitted for brevity...
case reflect.Bool:
return strconv.FormatBool(v.Bool())
case reflect.String:
return strconv.Quote(v.String())
case reflect.Chan, reflect.Func, reflect.Ptr, reflect.Slice, reflect.Map:
return v.Type().String() + " 0x" +
strconv.FormatUint(uint64(v.Pointer()), 16)
default: // reflect.Array, reflect.Struct, reflect.Interface
return v.Type().String() + " value"
}
}
//!-

View File

@ -1,24 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
package format_test
import (
"fmt"
"testing"
"time"
"gopl.io/ch12/format"
)
func Test(t *testing.T) {
// The pointer values are just examples, and may vary from run to run.
//!+time
var x int64 = 1
var d time.Duration = 1 * time.Nanosecond
fmt.Println(format.Any(x)) // "1"
fmt.Println(format.Any(d)) // "1"
fmt.Println(format.Any([]int64{x})) // "[]int64 0x8202b87b0"
fmt.Println(format.Any([]time.Duration{d})) // "[]time.Duration 0x8202b87e0"
//!-time
}

View File

@ -1,29 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 351.
// Package methods provides a function to print the methods of any value.
package methods
import (
"fmt"
"reflect"
"strings"
)
//!+print
// Print prints the method set of the value x.
func Print(x interface{}) {
v := reflect.ValueOf(x)
t := v.Type()
fmt.Printf("type %s\n", t)
for i := 0; i < v.NumMethod(); i++ {
methType := v.Method(i).Type()
fmt.Printf("func (%s) %s%s\n", t, t.Method(i).Name,
strings.TrimPrefix(methType.String(), "func"))
}
}
//!-print

View File

@ -1,49 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
package methods_test
import (
"strings"
"time"
"gopl.io/ch12/methods"
)
func ExamplePrintDuration() {
methods.Print(time.Hour)
// Output:
// type time.Duration
// func (time.Duration) Hours() float64
// func (time.Duration) Minutes() float64
// func (time.Duration) Nanoseconds() int64
// func (time.Duration) Seconds() float64
// func (time.Duration) String() string
}
func ExamplePrintReplacer() {
methods.Print(new(strings.Replacer))
// Output:
// type *strings.Replacer
// func (*strings.Replacer) Replace(string) string
// func (*strings.Replacer) WriteString(io.Writer, string) (int, error)
}
/*
//!+output
methods.Print(time.Hour)
// Output:
// type time.Duration
// func (time.Duration) Hours() float64
// func (time.Duration) Minutes() float64
// func (time.Duration) Nanoseconds() int64
// func (time.Duration) Seconds() float64
// func (time.Duration) String() string
methods.Print(new(strings.Replacer))
// Output:
// type *strings.Replacer
// func (*strings.Replacer) Replace(string) string
// func (*strings.Replacer) WriteString(io.Writer, string) (int, error)
//!-output
*/

90
vendor/gopl.io/ch12/params/params.go generated vendored
View File

@ -1,90 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 349.
// Package params provides a reflection-based parser for URL parameters.
package params
import (
"fmt"
"net/http"
"reflect"
"strconv"
"strings"
)
//!+Unpack
// Unpack populates the fields of the struct pointed to by ptr
// from the HTTP request parameters in req.
func Unpack(req *http.Request, ptr interface{}) error {
if err := req.ParseForm(); err != nil {
return err
}
// Build map of fields keyed by effective name.
fields := make(map[string]reflect.Value)
v := reflect.ValueOf(ptr).Elem() // the struct variable
for i := 0; i < v.NumField(); i++ {
fieldInfo := v.Type().Field(i) // a reflect.StructField
tag := fieldInfo.Tag // a reflect.StructTag
name := tag.Get("http")
if name == "" {
name = strings.ToLower(fieldInfo.Name)
}
fields[name] = v.Field(i)
}
// Update struct field for each parameter in the request.
for name, values := range req.Form {
f := fields[name]
if !f.IsValid() {
continue // ignore unrecognized HTTP parameters
}
for _, value := range values {
if f.Kind() == reflect.Slice {
elem := reflect.New(f.Type().Elem()).Elem()
if err := populate(elem, value); err != nil {
return fmt.Errorf("%s: %v", name, err)
}
f.Set(reflect.Append(f, elem))
} else {
if err := populate(f, value); err != nil {
return fmt.Errorf("%s: %v", name, err)
}
}
}
}
return nil
}
//!-Unpack
//!+populate
func populate(v reflect.Value, value string) error {
switch v.Kind() {
case reflect.String:
v.SetString(value)
case reflect.Int:
i, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return err
}
v.SetInt(i)
case reflect.Bool:
b, err := strconv.ParseBool(value)
if err != nil {
return err
}
v.SetBool(b)
default:
return fmt.Errorf("unsupported kind %s", v.Type())
}
return nil
}
//!-populate

60
vendor/gopl.io/ch12/search/main.go generated vendored
View File

@ -1,60 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 348.
// Search is a demo of the params.Unpack function.
package main
import (
"fmt"
"log"
"net/http"
)
//!+
import "gopl.io/ch12/params"
// search implements the /search URL endpoint.
func search(resp http.ResponseWriter, req *http.Request) {
var data struct {
Labels []string `http:"l"`
MaxResults int `http:"max"`
Exact bool `http:"x"`
}
data.MaxResults = 10 // set default
if err := params.Unpack(req, &data); err != nil {
http.Error(resp, err.Error(), http.StatusBadRequest) // 400
return
}
// ...rest of handler...
fmt.Fprintf(resp, "Search: %+v\n", data)
}
//!-
func main() {
http.HandleFunc("/search", search)
log.Fatal(http.ListenAndServe(":12345", nil))
}
/*
//!+output
$ go build gopl.io/ch12/search
$ ./search &
$ ./fetch 'http://localhost:12345/search'
Search: {Labels:[] MaxResults:10 Exact:false}
$ ./fetch 'http://localhost:12345/search?l=golang&l=programming'
Search: {Labels:[golang programming] MaxResults:10 Exact:false}
$ ./fetch 'http://localhost:12345/search?l=golang&l=programming&max=100'
Search: {Labels:[golang programming] MaxResults:100 Exact:false}
$ ./fetch 'http://localhost:12345/search?x=true&l=golang&l=programming'
Search: {Labels:[golang programming] MaxResults:10 Exact:true}
$ ./fetch 'http://localhost:12345/search?q=hello&x=123'
x: strconv.ParseBool: parsing "123": invalid syntax
$ ./fetch 'http://localhost:12345/search?q=hello&max=lots'
max: strconv.ParseInt: parsing "lots": invalid syntax
//!-output
*/

162
vendor/gopl.io/ch12/sexpr/decode.go generated vendored
View File

@ -1,162 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 344.
// Package sexpr provides a means for converting Go objects to and
// from S-expressions.
package sexpr
import (
"bytes"
"fmt"
"reflect"
"strconv"
"text/scanner"
)
//!+Unmarshal
// Unmarshal parses S-expression data and populates the variable
// whose address is in the non-nil pointer out.
func Unmarshal(data []byte, out interface{}) (err error) {
lex := &lexer{scan: scanner.Scanner{Mode: scanner.GoTokens}}
lex.scan.Init(bytes.NewReader(data))
lex.next() // get the first token
defer func() {
// NOTE: this is not an example of ideal error handling.
if x := recover(); x != nil {
err = fmt.Errorf("error at %s: %v", lex.scan.Position, x)
}
}()
read(lex, reflect.ValueOf(out).Elem())
return nil
}
//!-Unmarshal
//!+lexer
type lexer struct {
scan scanner.Scanner
token rune // the current token
}
func (lex *lexer) next() { lex.token = lex.scan.Scan() }
func (lex *lexer) text() string { return lex.scan.TokenText() }
func (lex *lexer) consume(want rune) {
if lex.token != want { // NOTE: Not an example of good error handling.
panic(fmt.Sprintf("got %q, want %q", lex.text(), want))
}
lex.next()
}
//!-lexer
// The read function is a decoder for a small subset of well-formed
// S-expressions. For brevity of our example, it takes many dubious
// shortcuts.
//
// The parser assumes
// - that the S-expression input is well-formed; it does no error checking.
// - that the S-expression input corresponds to the type of the variable.
// - that all numbers in the input are non-negative decimal integers.
// - that all keys in ((key value) ...) struct syntax are unquoted symbols.
// - that the input does not contain dotted lists such as (1 2 . 3).
// - that the input does not contain Lisp reader macros such 'x and #'x.
//
// The reflection logic assumes
// - that v is always a variable of the appropriate type for the
// S-expression value. For example, v must not be a boolean,
// interface, channel, or function, and if v is an array, the input
// must have the correct number of elements.
// - that v in the top-level call to read has the zero value of its
// type and doesn't need clearing.
// - that if v is a numeric variable, it is a signed integer.
//!+read
func read(lex *lexer, v reflect.Value) {
switch lex.token {
case scanner.Ident:
// The only valid identifiers are
// "nil" and struct field names.
if lex.text() == "nil" {
v.Set(reflect.Zero(v.Type()))
lex.next()
return
}
case scanner.String:
s, _ := strconv.Unquote(lex.text()) // NOTE: ignoring errors
v.SetString(s)
lex.next()
return
case scanner.Int:
i, _ := strconv.Atoi(lex.text()) // NOTE: ignoring errors
v.SetInt(int64(i))
lex.next()
return
case '(':
lex.next()
readList(lex, v)
lex.next() // consume ')'
return
}
panic(fmt.Sprintf("unexpected token %q", lex.text()))
}
//!-read
//!+readlist
func readList(lex *lexer, v reflect.Value) {
switch v.Kind() {
case reflect.Array: // (item ...)
for i := 0; !endList(lex); i++ {
read(lex, v.Index(i))
}
case reflect.Slice: // (item ...)
for !endList(lex) {
item := reflect.New(v.Type().Elem()).Elem()
read(lex, item)
v.Set(reflect.Append(v, item))
}
case reflect.Struct: // ((name value) ...)
for !endList(lex) {
lex.consume('(')
if lex.token != scanner.Ident {
panic(fmt.Sprintf("got token %q, want field name", lex.text()))
}
name := lex.text()
lex.next()
read(lex, v.FieldByName(name))
lex.consume(')')
}
case reflect.Map: // ((key value) ...)
v.Set(reflect.MakeMap(v.Type()))
for !endList(lex) {
lex.consume('(')
key := reflect.New(v.Type().Key()).Elem()
read(lex, key)
value := reflect.New(v.Type().Elem()).Elem()
read(lex, value)
v.SetMapIndex(key, value)
lex.consume(')')
}
default:
panic(fmt.Sprintf("cannot decode list into %v", v.Type()))
}
}
func endList(lex *lexer) bool {
switch lex.token {
case scanner.EOF:
panic("end of file")
case ')':
return true
}
return false
}
//!-readlist

97
vendor/gopl.io/ch12/sexpr/encode.go generated vendored
View File

@ -1,97 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 339.
package sexpr
import (
"bytes"
"fmt"
"reflect"
)
//!+Marshal
// Marshal encodes a Go value in S-expression form.
func Marshal(v interface{}) ([]byte, error) {
var buf bytes.Buffer
if err := encode(&buf, reflect.ValueOf(v)); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
//!-Marshal
// encode writes to buf an S-expression representation of v.
//!+encode
func encode(buf *bytes.Buffer, v reflect.Value) error {
switch v.Kind() {
case reflect.Invalid:
buf.WriteString("nil")
case reflect.Int, reflect.Int8, reflect.Int16,
reflect.Int32, reflect.Int64:
fmt.Fprintf(buf, "%d", v.Int())
case reflect.Uint, reflect.Uint8, reflect.Uint16,
reflect.Uint32, reflect.Uint64, reflect.Uintptr:
fmt.Fprintf(buf, "%d", v.Uint())
case reflect.String:
fmt.Fprintf(buf, "%q", v.String())
case reflect.Ptr:
return encode(buf, v.Elem())
case reflect.Array, reflect.Slice: // (value ...)
buf.WriteByte('(')
for i := 0; i < v.Len(); i++ {
if i > 0 {
buf.WriteByte(' ')
}
if err := encode(buf, v.Index(i)); err != nil {
return err
}
}
buf.WriteByte(')')
case reflect.Struct: // ((name value) ...)
buf.WriteByte('(')
for i := 0; i < v.NumField(); i++ {
if i > 0 {
buf.WriteByte(' ')
}
fmt.Fprintf(buf, "(%s ", v.Type().Field(i).Name)
if err := encode(buf, v.Field(i)); err != nil {
return err
}
buf.WriteByte(')')
}
buf.WriteByte(')')
case reflect.Map: // ((key value) ...)
buf.WriteByte('(')
for i, key := range v.MapKeys() {
if i > 0 {
buf.WriteByte(' ')
}
buf.WriteByte('(')
if err := encode(buf, key); err != nil {
return err
}
buf.WriteByte(' ')
if err := encode(buf, v.MapIndex(key)); err != nil {
return err
}
buf.WriteByte(')')
}
buf.WriteByte(')')
default: // float, complex, bool, chan, func, interface
return fmt.Errorf("unsupported type: %s", v.Type())
}
return nil
}
//!-encode

183
vendor/gopl.io/ch12/sexpr/pretty.go generated vendored
View File

@ -1,183 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
package sexpr
// This file implements the algorithm described in Derek C. Oppen's
// 1979 Stanford technical report, "Pretty Printing".
import (
"bytes"
"fmt"
"reflect"
)
func MarshalIndent(v interface{}) ([]byte, error) {
p := printer{width: margin}
if err := pretty(&p, reflect.ValueOf(v)); err != nil {
return nil, err
}
return p.Bytes(), nil
}
const margin = 80
type token struct {
kind rune // one of "s ()" (string, blank, start, end)
str string
size int
}
type printer struct {
tokens []*token // FIFO buffer
stack []*token // stack of open ' ' and '(' tokens
rtotal int // total number of spaces needed to print stream
bytes.Buffer
indents []int
width int // remaining space
}
func (p *printer) string(str string) {
tok := &token{kind: 's', str: str, size: len(str)}
if len(p.stack) == 0 {
p.print(tok)
} else {
p.tokens = append(p.tokens, tok)
p.rtotal += len(str)
}
}
func (p *printer) pop() (top *token) {
last := len(p.stack) - 1
top, p.stack = p.stack[last], p.stack[:last]
return
}
func (p *printer) begin() {
if len(p.stack) == 0 {
p.rtotal = 1
}
t := &token{kind: '(', size: -p.rtotal}
p.tokens = append(p.tokens, t)
p.stack = append(p.stack, t) // push
p.string("(")
}
func (p *printer) end() {
p.string(")")
p.tokens = append(p.tokens, &token{kind: ')'})
x := p.pop()
x.size += p.rtotal
if x.kind == ' ' {
p.pop().size += p.rtotal
}
if len(p.stack) == 0 {
for _, tok := range p.tokens {
p.print(tok)
}
p.tokens = nil
}
}
func (p *printer) space() {
last := len(p.stack) - 1
x := p.stack[last]
if x.kind == ' ' {
x.size += p.rtotal
p.stack = p.stack[:last] // pop
}
t := &token{kind: ' ', size: -p.rtotal}
p.tokens = append(p.tokens, t)
p.stack = append(p.stack, t)
p.rtotal++
}
func (p *printer) print(t *token) {
switch t.kind {
case 's':
p.WriteString(t.str)
p.width -= len(t.str)
case '(':
p.indents = append(p.indents, p.width)
case ')':
p.indents = p.indents[:len(p.indents)-1] // pop
case ' ':
if t.size > p.width {
p.width = p.indents[len(p.indents)-1] - 1
fmt.Fprintf(&p.Buffer, "\n%*s", margin-p.width, "")
} else {
p.WriteByte(' ')
p.width--
}
}
}
func (p *printer) stringf(format string, args ...interface{}) {
p.string(fmt.Sprintf(format, args...))
}
func pretty(p *printer, v reflect.Value) error {
switch v.Kind() {
case reflect.Invalid:
p.string("nil")
case reflect.Int, reflect.Int8, reflect.Int16,
reflect.Int32, reflect.Int64:
p.stringf("%d", v.Int())
case reflect.Uint, reflect.Uint8, reflect.Uint16,
reflect.Uint32, reflect.Uint64, reflect.Uintptr:
p.stringf("%d", v.Uint())
case reflect.String:
p.stringf("%q", v.String())
case reflect.Array, reflect.Slice: // (value ...)
p.begin()
for i := 0; i < v.Len(); i++ {
if i > 0 {
p.space()
}
if err := pretty(p, v.Index(i)); err != nil {
return err
}
}
p.end()
case reflect.Struct: // ((name value ...)
p.begin()
for i := 0; i < v.NumField(); i++ {
if i > 0 {
p.space()
}
p.begin()
p.string(v.Type().Field(i).Name)
p.space()
if err := pretty(p, v.Field(i)); err != nil {
return err
}
p.end()
}
p.end()
case reflect.Map: // ((key value ...)
p.begin()
for i, key := range v.MapKeys() {
if i > 0 {
p.space()
}
p.begin()
if err := pretty(p, key); err != nil {
return err
}
p.space()
if err := pretty(p, v.MapIndex(key)); err != nil {
return err
}
p.end()
}
p.end()
case reflect.Ptr:
return pretty(p, v.Elem())
default: // float, complex, bool, chan, func, interface
return fmt.Errorf("unsupported type: %s", v.Type())
}
return nil
}

View File

@ -1,74 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
package sexpr
import (
"reflect"
"testing"
)
// Test verifies that encoding and decoding a complex data value
// produces an equal result.
//
// The test does not make direct assertions about the encoded output
// because the output depends on map iteration order, which is
// nondeterministic. The output of the t.Log statements can be
// inspected by running the test with the -v flag:
//
// $ go test -v gopl.io/ch12/sexpr
//
func Test(t *testing.T) {
type Movie struct {
Title, Subtitle string
Year int
Actor map[string]string
Oscars []string
Sequel *string
}
strangelove := Movie{
Title: "Dr. Strangelove",
Subtitle: "How I Learned to Stop Worrying and Love the Bomb",
Year: 1964,
Actor: map[string]string{
"Dr. Strangelove": "Peter Sellers",
"Grp. Capt. Lionel Mandrake": "Peter Sellers",
"Pres. Merkin Muffley": "Peter Sellers",
"Gen. Buck Turgidson": "George C. Scott",
"Brig. Gen. Jack D. Ripper": "Sterling Hayden",
`Maj. T.J. "King" Kong`: "Slim Pickens",
},
Oscars: []string{
"Best Actor (Nomin.)",
"Best Adapted Screenplay (Nomin.)",
"Best Director (Nomin.)",
"Best Picture (Nomin.)",
},
}
// Encode it
data, err := Marshal(strangelove)
if err != nil {
t.Fatalf("Marshal failed: %v", err)
}
t.Logf("Marshal() = %s\n", data)
// Decode it
var movie Movie
if err := Unmarshal(data, &movie); err != nil {
t.Fatalf("Unmarshal failed: %v", err)
}
t.Logf("Unmarshal() = %+v\n", movie)
// Check equality.
if !reflect.DeepEqual(movie, strangelove) {
t.Fatal("not equal")
}
// Pretty-print it:
data, err = MarshalIndent(strangelove)
if err != nil {
t.Fatal(err)
}
t.Logf("MarshalIdent() = %s\n", data)
}

View File

@ -1,28 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 362.
// This is the version that appears in print,
// but it does not comply with the proposed
// rules for passing pointers between Go and C.
// (https://github.com/golang/proposal/blob/master/design/12416-cgo-pointers.md)
// See gopl.io/ch13/bzip for an updated version.
//!+
/* This file is gopl.io/ch13/bzip/bzip2.c, */
/* a simple wrapper for libbzip2 suitable for cgo. */
#include <bzlib.h>
int bz2compress(bz_stream *s, int action,
char *in, unsigned *inlen, char *out, unsigned *outlen) {
s->next_in = in;
s->avail_in = *inlen;
s->next_out = out;
s->avail_out = *outlen;
int r = BZ2_bzCompress(s, action);
*inlen -= s->avail_in;
*outlen -= s->avail_out;
return r;
}
//!-

View File

@ -1,96 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 362.
// This is the version that appears in print,
// but it does not comply with the proposed
// rules for passing pointers between Go and C.
// (https://github.com/golang/proposal/blob/master/design/12416-cgo-pointers.md)
// See gopl.io/ch13/bzip for an updated version.
//!+
// Package bzip provides a writer that uses bzip2 compression (bzip.org).
package bzip
/*
#cgo CFLAGS: -I/usr/include
#cgo LDFLAGS: -L/usr/lib -lbz2
#include <bzlib.h>
int bz2compress(bz_stream *s, int action,
char *in, unsigned *inlen, char *out, unsigned *outlen);
*/
import "C"
import (
"io"
"unsafe"
)
type writer struct {
w io.Writer // underlying output stream
stream *C.bz_stream
outbuf [64 * 1024]byte
}
// NewWriter returns a writer for bzip2-compressed streams.
func NewWriter(out io.Writer) io.WriteCloser {
const (
blockSize = 9
verbosity = 0
workFactor = 30
)
w := &writer{w: out, stream: new(C.bz_stream)}
C.BZ2_bzCompressInit(w.stream, blockSize, verbosity, workFactor)
return w
}
//!-
//!+write
func (w *writer) Write(data []byte) (int, error) {
if w.stream == nil {
panic("closed")
}
var total int // uncompressed bytes written
for len(data) > 0 {
inlen, outlen := C.uint(len(data)), C.uint(cap(w.outbuf))
C.bz2compress(w.stream, C.BZ_RUN,
(*C.char)(unsafe.Pointer(&data[0])), &inlen,
(*C.char)(unsafe.Pointer(&w.outbuf)), &outlen)
total += int(inlen)
data = data[inlen:]
if _, err := w.w.Write(w.outbuf[:outlen]); err != nil {
return total, err
}
}
return total, nil
}
//!-write
//!+close
// Close flushes the compressed data and closes the stream.
// It does not close the underlying io.Writer.
func (w *writer) Close() error {
if w.stream == nil {
panic("closed")
}
defer func() {
C.BZ2_bzCompressEnd(w.stream)
w.stream = nil
}()
for {
inlen, outlen := C.uint(0), C.uint(cap(w.outbuf))
r := C.bz2compress(w.stream, C.BZ_FINISH, nil, &inlen,
(*C.char)(unsafe.Pointer(&w.outbuf)), &outlen)
if _, err := w.w.Write(w.outbuf[:outlen]); err != nil {
return err
}
if r == C.BZ_STREAM_END {
return nil
}
}
}
//!-close

View File

@ -1,40 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
package bzip_test
import (
"bytes"
"compress/bzip2" // reader
"io"
"testing"
"gopl.io/ch13/bzip" // writer
)
func TestBzip2(t *testing.T) {
var compressed, uncompressed bytes.Buffer
w := bzip.NewWriter(&compressed)
// Write a repetitive message in a million pieces,
// compressing one copy but not the other.
tee := io.MultiWriter(w, &uncompressed)
for i := 0; i < 1000000; i++ {
io.WriteString(tee, "hello")
}
if err := w.Close(); err != nil {
t.Fatal(err)
}
// Check the size of the compressed stream.
if got, want := compressed.Len(), 255; got != want {
t.Errorf("1 million hellos compressed to %d bytes, want %d", got, want)
}
// Decompress and compare with original.
var decompressed bytes.Buffer
io.Copy(&decompressed, bzip2.NewReader(&compressed))
if !bytes.Equal(uncompressed.Bytes(), decompressed.Bytes()) {
t.Error("decompression yielded a different message")
}
}

32
vendor/gopl.io/ch13/bzip/bzip2.c generated vendored
View File

@ -1,32 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 362.
//
// The version of this program that appeared in the first and second
// printings did not comply with the proposed rules for passing
// pointers between Go and C, described here:
// https://github.com/golang/proposal/blob/master/design/12416-cgo-pointers.md
//
// The version below, which appears in the third printing,
// has been corrected. See bzip2.go for explanation.
//!+
/* This file is gopl.io/ch13/bzip/bzip2.c, */
/* a simple wrapper for libbzip2 suitable for cgo. */
#include <bzlib.h>
int bz2compress(bz_stream *s, int action,
char *in, unsigned *inlen, char *out, unsigned *outlen) {
s->next_in = in;
s->avail_in = *inlen;
s->next_out = out;
s->avail_out = *outlen;
int r = BZ2_bzCompress(s, action);
*inlen -= s->avail_in;
*outlen -= s->avail_out;
s->next_in = s->next_out = NULL;
return r;
}
//!-

111
vendor/gopl.io/ch13/bzip/bzip2.go generated vendored
View File

@ -1,111 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 362.
//
// The version of this program that appeared in the first and second
// printings did not comply with the proposed rules for passing
// pointers between Go and C, described here:
// https://github.com/golang/proposal/blob/master/design/12416-cgo-pointers.md
//
// The rules forbid a C function like bz2compress from storing 'in'
// and 'out' (pointers to variables allocated by Go) into the Go
// variable 's', even temporarily.
//
// The version below, which appears in the third printing, has been
// corrected. To comply with the rules, the bz_stream variable must
// be allocated by C code. We have introduced two C functions,
// bz2alloc and bz2free, to allocate and free instances of the
// bz_stream type. Also, we have changed bz2compress so that before
// it returns, it clears the fields of the bz_stream that contain
// pointers to Go variables.
//!+
// Package bzip provides a writer that uses bzip2 compression (bzip.org).
package bzip
/*
#cgo CFLAGS: -I/usr/include
#cgo LDFLAGS: -L/usr/lib -lbz2
#include <bzlib.h>
#include <stdlib.h>
bz_stream* bz2alloc() { return calloc(1, sizeof(bz_stream)); }
int bz2compress(bz_stream *s, int action,
char *in, unsigned *inlen, char *out, unsigned *outlen);
void bz2free(bz_stream* s) { free(s); }
*/
import "C"
import (
"io"
"unsafe"
)
type writer struct {
w io.Writer // underlying output stream
stream *C.bz_stream
outbuf [64 * 1024]byte
}
// NewWriter returns a writer for bzip2-compressed streams.
func NewWriter(out io.Writer) io.WriteCloser {
const blockSize = 9
const verbosity = 0
const workFactor = 30
w := &writer{w: out, stream: C.bz2alloc()}
C.BZ2_bzCompressInit(w.stream, blockSize, verbosity, workFactor)
return w
}
//!-
//!+write
func (w *writer) Write(data []byte) (int, error) {
if w.stream == nil {
panic("closed")
}
var total int // uncompressed bytes written
for len(data) > 0 {
inlen, outlen := C.uint(len(data)), C.uint(cap(w.outbuf))
C.bz2compress(w.stream, C.BZ_RUN,
(*C.char)(unsafe.Pointer(&data[0])), &inlen,
(*C.char)(unsafe.Pointer(&w.outbuf)), &outlen)
total += int(inlen)
data = data[inlen:]
if _, err := w.w.Write(w.outbuf[:outlen]); err != nil {
return total, err
}
}
return total, nil
}
//!-write
//!+close
// Close flushes the compressed data and closes the stream.
// It does not close the underlying io.Writer.
func (w *writer) Close() error {
if w.stream == nil {
panic("closed")
}
defer func() {
C.BZ2_bzCompressEnd(w.stream)
C.bz2free(w.stream)
w.stream = nil
}()
for {
inlen, outlen := C.uint(0), C.uint(cap(w.outbuf))
r := C.bz2compress(w.stream, C.BZ_FINISH, nil, &inlen,
(*C.char)(unsafe.Pointer(&w.outbuf)), &outlen)
if _, err := w.w.Write(w.outbuf[:outlen]); err != nil {
return err
}
if r == C.BZ_STREAM_END {
return nil
}
}
}
//!-close

View File

@ -1,40 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
package bzip_test
import (
"bytes"
"compress/bzip2" // reader
"io"
"testing"
"gopl.io/ch13/bzip" // writer
)
func TestBzip2(t *testing.T) {
var compressed, uncompressed bytes.Buffer
w := bzip.NewWriter(&compressed)
// Write a repetitive message in a million pieces,
// compressing one copy but not the other.
tee := io.MultiWriter(w, &uncompressed)
for i := 0; i < 1000000; i++ {
io.WriteString(tee, "hello")
}
if err := w.Close(); err != nil {
t.Fatal(err)
}
// Check the size of the compressed stream.
if got, want := compressed.Len(), 255; got != want {
t.Errorf("1 million hellos compressed to %d bytes, want %d", got, want)
}
// Decompress and compare with original.
var decompressed bytes.Buffer
io.Copy(&decompressed, bzip2.NewReader(&compressed))
if !bytes.Equal(uncompressed.Bytes(), decompressed.Bytes()) {
t.Error("decompression yielded a different message")
}
}

29
vendor/gopl.io/ch13/bzipper/main.go generated vendored
View File

@ -1,29 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 365.
//!+
// Bzipper reads input, bzip2-compresses it, and writes it out.
package main
import (
"io"
"log"
"os"
"gopl.io/ch13/bzip"
)
func main() {
w := bzip.NewWriter(os.Stdout)
if _, err := io.Copy(w, os.Stdin); err != nil {
log.Fatalf("bzipper: %v\n", err)
}
if err := w.Close(); err != nil {
log.Fatalf("bzipper: close: %v\n", err)
}
}
//!-

127
vendor/gopl.io/ch13/equal/equal.go generated vendored
View File

@ -1,127 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 359.
// Package equal provides a deep equivalence relation for arbitrary values.
package equal
import (
"reflect"
"unsafe"
)
//!+
func equal(x, y reflect.Value, seen map[comparison]bool) bool {
if !x.IsValid() || !y.IsValid() {
return x.IsValid() == y.IsValid()
}
if x.Type() != y.Type() {
return false
}
// ...cycle check omitted (shown later)...
//!-
//!+cyclecheck
// cycle check
if x.CanAddr() && y.CanAddr() {
xptr := unsafe.Pointer(x.UnsafeAddr())
yptr := unsafe.Pointer(y.UnsafeAddr())
if xptr == yptr {
return true // identical references
}
c := comparison{xptr, yptr, x.Type()}
if seen[c] {
return true // already seen
}
seen[c] = true
}
//!-cyclecheck
//!+
switch x.Kind() {
case reflect.Bool:
return x.Bool() == y.Bool()
case reflect.String:
return x.String() == y.String()
// ...numeric cases omitted for brevity...
//!-
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32,
reflect.Int64:
return x.Int() == y.Int()
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32,
reflect.Uint64, reflect.Uintptr:
return x.Uint() == y.Uint()
case reflect.Float32, reflect.Float64:
return x.Float() == y.Float()
case reflect.Complex64, reflect.Complex128:
return x.Complex() == y.Complex()
//!+
case reflect.Chan, reflect.UnsafePointer, reflect.Func:
return x.Pointer() == y.Pointer()
case reflect.Ptr, reflect.Interface:
return equal(x.Elem(), y.Elem(), seen)
case reflect.Array, reflect.Slice:
if x.Len() != y.Len() {
return false
}
for i := 0; i < x.Len(); i++ {
if !equal(x.Index(i), y.Index(i), seen) {
return false
}
}
return true
// ...struct and map cases omitted for brevity...
//!-
case reflect.Struct:
for i, n := 0, x.NumField(); i < n; i++ {
if !equal(x.Field(i), y.Field(i), seen) {
return false
}
}
return true
case reflect.Map:
if x.Len() != y.Len() {
return false
}
for _, k := range x.MapKeys() {
if !equal(x.MapIndex(k), y.MapIndex(k), seen) {
return false
}
}
return true
//!+
}
panic("unreachable")
}
//!-
//!+comparison
// Equal reports whether x and y are deeply equal.
//!-comparison
//
// Map keys are always compared with ==, not deeply.
// (This matters for keys containing pointers or interfaces.)
//!+comparison
func Equal(x, y interface{}) bool {
seen := make(map[comparison]bool)
return equal(reflect.ValueOf(x), reflect.ValueOf(y), seen)
}
type comparison struct {
x, y unsafe.Pointer
t reflect.Type
}
//!-comparison

View File

@ -1,133 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
package equal
import (
"bytes"
"fmt"
"testing"
)
func TestEqual(t *testing.T) {
one, oneAgain, two := 1, 1, 2
type CyclePtr *CyclePtr
var cyclePtr1, cyclePtr2 CyclePtr
cyclePtr1 = &cyclePtr1
cyclePtr2 = &cyclePtr2
type CycleSlice []CycleSlice
var cycleSlice CycleSlice
cycleSlice = append(cycleSlice, cycleSlice)
ch1, ch2 := make(chan int), make(chan int)
var ch1ro <-chan int = ch1
type mystring string
var iface1, iface1Again, iface2 interface{} = &one, &oneAgain, &two
for _, test := range []struct {
x, y interface{}
want bool
}{
// basic types
{1, 1, true},
{1, 2, false}, // different values
{1, 1.0, false}, // different types
{"foo", "foo", true},
{"foo", "bar", false},
{mystring("foo"), "foo", false}, // different types
// slices
{[]string{"foo"}, []string{"foo"}, true},
{[]string{"foo"}, []string{"bar"}, false},
{[]string{}, []string(nil), true},
// slice cycles
{cycleSlice, cycleSlice, true},
// maps
{
map[string][]int{"foo": {1, 2, 3}},
map[string][]int{"foo": {1, 2, 3}},
true,
},
{
map[string][]int{"foo": {1, 2, 3}},
map[string][]int{"foo": {1, 2, 3, 4}},
false,
},
{
map[string][]int{},
map[string][]int(nil),
true,
},
// pointers
{&one, &one, true},
{&one, &two, false},
{&one, &oneAgain, true},
{new(bytes.Buffer), new(bytes.Buffer), true},
// pointer cycles
{cyclePtr1, cyclePtr1, true},
{cyclePtr2, cyclePtr2, true},
{cyclePtr1, cyclePtr2, true}, // they're deeply equal
// functions
{(func())(nil), (func())(nil), true},
{(func())(nil), func() {}, false},
{func() {}, func() {}, false},
// arrays
{[...]int{1, 2, 3}, [...]int{1, 2, 3}, true},
{[...]int{1, 2, 3}, [...]int{1, 2, 4}, false},
// channels
{ch1, ch1, true},
{ch1, ch2, false},
{ch1ro, ch1, false}, // NOTE: not equal
// interfaces
{&iface1, &iface1, true},
{&iface1, &iface2, false},
{&iface1Again, &iface1, true},
} {
if Equal(test.x, test.y) != test.want {
t.Errorf("Equal(%v, %v) = %t",
test.x, test.y, !test.want)
}
}
}
func Example_equal() {
//!+
fmt.Println(Equal([]int{1, 2, 3}, []int{1, 2, 3})) // "true"
fmt.Println(Equal([]string{"foo"}, []string{"bar"})) // "false"
fmt.Println(Equal([]string(nil), []string{})) // "true"
fmt.Println(Equal(map[string]int(nil), map[string]int{})) // "true"
//!-
// Output:
// true
// false
// true
// true
}
func Example_equalCycle() {
//!+cycle
// Circular linked lists a -> b -> a and c -> c.
type link struct {
value string
tail *link
}
a, b, c := &link{value: "a"}, &link{value: "b"}, &link{value: "c"}
a.tail, b.tail, c.tail = b, a, c
fmt.Println(Equal(a, a)) // "true"
fmt.Println(Equal(b, b)) // "true"
fmt.Println(Equal(c, c)) // "true"
fmt.Println(Equal(a, b)) // "false"
fmt.Println(Equal(a, c)) // "false"
//!-cycle
// Output:
// true
// true
// true
// false
// false
}

View File

@ -1,38 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 357.
// Package unsafeptr demonstrates basic use of unsafe.Pointer.
package main
import (
"fmt"
"unsafe"
)
func main() {
//!+main
var x struct {
a bool
b int16
c []int
}
// equivalent to pb := &x.b
pb := (*int16)(unsafe.Pointer(
uintptr(unsafe.Pointer(&x)) + unsafe.Offsetof(x.b)))
*pb = 42
fmt.Println(x.b) // "42"
//!-main
}
/*
//!+wrong
// NOTE: subtly incorrect!
tmp := uintptr(unsafe.Pointer(&x)) + unsafe.Offsetof(x.b)
pb := (*int16)(unsafe.Pointer(tmp))
*pb = 42
//!-wrong
*/

22
vendor/gopl.io/ch2/boiling/main.go generated vendored
View File

@ -1,22 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 29.
//!+
// Boiling prints the boiling point of water.
package main
import "fmt"
const boilingF = 212.0
func main() {
var f = boilingF
var c = (f - 32) * 5 / 9
fmt.Printf("boiling point = %g°F or %g°C\n", f, c)
// Output:
// boiling point = 212°F or 100°C
}
//!-

32
vendor/gopl.io/ch2/cf/main.go generated vendored
View File

@ -1,32 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 43.
//!+
// Cf converts its numeric argument to Celsius and Fahrenheit.
package main
import (
"fmt"
"os"
"strconv"
"gopl.io/ch2/tempconv"
)
func main() {
for _, arg := range os.Args[1:] {
t, err := strconv.ParseFloat(arg, 64)
if err != nil {
fmt.Fprintf(os.Stderr, "cf: %v\n", err)
os.Exit(1)
}
f := tempconv.Fahrenheit(t)
c := tempconv.Celsius(t)
fmt.Printf("%s = %s, %s = %s\n",
f, tempconv.FToC(f), c, tempconv.CToF(c))
}
}
//!-

27
vendor/gopl.io/ch2/echo4/main.go generated vendored
View File

@ -1,27 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 33.
//!+
// Echo4 prints its command-line arguments.
package main
import (
"flag"
"fmt"
"strings"
)
var n = flag.Bool("n", false, "omit trailing newline")
var sep = flag.String("s", " ", "separator")
func main() {
flag.Parse()
fmt.Print(strings.Join(flag.Args(), *sep))
if !*n {
fmt.Println()
}
}
//!-

22
vendor/gopl.io/ch2/ftoc/main.go generated vendored
View File

@ -1,22 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 29.
//!+
// Ftoc prints two Fahrenheit-to-Celsius conversions.
package main
import "fmt"
func main() {
const freezingF, boilingF = 32.0, 212.0
fmt.Printf("%g°F = %g°C\n", freezingF, fToC(freezingF)) // "32°F = 0°C"
fmt.Printf("%g°F = %g°C\n", boilingF, fToC(boilingF)) // "212°F = 100°C"
}
func fToC(f float64) float64 {
return (f - 32) * 5 / 9
}
//!-

31
vendor/gopl.io/ch2/popcount/main.go generated vendored
View File

@ -1,31 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 45.
// (Package doc comment intentionally malformed to demonstrate golint.)
//!+
package popcount
// pc[i] is the population count of i.
var pc [256]byte
func init() {
for i := range pc {
pc[i] = pc[i/2] + byte(i&1)
}
}
// PopCount returns the population count (number of set bits) of x.
func PopCount(x uint64) int {
return int(pc[byte(x>>(0*8))] +
pc[byte(x>>(1*8))] +
pc[byte(x>>(2*8))] +
pc[byte(x>>(3*8))] +
pc[byte(x>>(4*8))] +
pc[byte(x>>(5*8))] +
pc[byte(x>>(6*8))] +
pc[byte(x>>(7*8))])
}
//!-

View File

@ -1,83 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
package popcount_test
import (
"testing"
"gopl.io/ch2/popcount"
)
// -- Alternative implementations --
func BitCount(x uint64) int {
// Hacker's Delight, Figure 5-2.
x = x - ((x >> 1) & 0x5555555555555555)
x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333)
x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0f
x = x + (x >> 8)
x = x + (x >> 16)
x = x + (x >> 32)
return int(x & 0x7f)
}
func PopCountByClearing(x uint64) int {
n := 0
for x != 0 {
x = x & (x - 1) // clear rightmost non-zero bit
n++
}
return n
}
func PopCountByShifting(x uint64) int {
n := 0
for i := uint(0); i < 64; i++ {
if x&(1<<i) != 0 {
n++
}
}
return n
}
// -- Benchmarks --
func BenchmarkPopCount(b *testing.B) {
for i := 0; i < b.N; i++ {
popcount.PopCount(0x1234567890ABCDEF)
}
}
func BenchmarkBitCount(b *testing.B) {
for i := 0; i < b.N; i++ {
BitCount(0x1234567890ABCDEF)
}
}
func BenchmarkPopCountByClearing(b *testing.B) {
for i := 0; i < b.N; i++ {
PopCountByClearing(0x1234567890ABCDEF)
}
}
func BenchmarkPopCountByShifting(b *testing.B) {
for i := 0; i < b.N; i++ {
PopCountByShifting(0x1234567890ABCDEF)
}
}
// 2.67GHz Xeon
// $ go test -cpu=4 -bench=. gopl.io/ch2/popcount
// BenchmarkPopCount-4 200000000 6.30 ns/op
// BenchmarkBitCount-4 300000000 4.15 ns/op
// BenchmarkPopCountByClearing-4 30000000 45.2 ns/op
// BenchmarkPopCountByShifting-4 10000000 153 ns/op
//
// 2.5GHz Intel Core i5
// $ go test -cpu=4 -bench=. gopl.io/ch2/popcount
// testing: warning: no tests to run
// BenchmarkPopCount-4 200000000 7.52 ns/op
// BenchmarkBitCount-4 500000000 3.36 ns/op
// BenchmarkPopCountByClearing-4 50000000 34.3 ns/op
// BenchmarkPopCountByShifting-4 20000000 108 ns/op

16
vendor/gopl.io/ch2/tempconv/conv.go generated vendored
View File

@ -1,16 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 41.
//!+
package tempconv
// CToF converts a Celsius temperature to Fahrenheit.
func CToF(c Celsius) Fahrenheit { return Fahrenheit(c*9/5 + 32) }
// FToC converts a Fahrenheit temperature to Celsius.
func FToC(f Fahrenheit) Celsius { return Celsius((f - 32) * 5 / 9) }
//!-

View File

@ -1,23 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//!+
// Package tempconv performs Celsius and Fahrenheit conversions.
package tempconv
import "fmt"
type Celsius float64
type Fahrenheit float64
const (
AbsoluteZeroC Celsius = -273.15
FreezingC Celsius = 0
BoilingC Celsius = 100
)
func (c Celsius) String() string { return fmt.Sprintf("%g°C", c) }
func (f Fahrenheit) String() string { return fmt.Sprintf("%g°F", f) }
//!-

View File

@ -1,27 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 39.
//!+
// Package tempconv performs Celsius and Fahrenheit temperature computations.
package tempconv
import "fmt"
type Celsius float64
type Fahrenheit float64
const (
AbsoluteZeroC Celsius = -273.15
FreezingC Celsius = 0
BoilingC Celsius = 100
)
func CToF(c Celsius) Fahrenheit { return Fahrenheit(c*9/5 + 32) }
func FToC(f Fahrenheit) Celsius { return Celsius((f - 32) * 5 / 9) }
//!-
func (c Celsius) String() string { return fmt.Sprintf("%g°C", c) }

View File

@ -1,45 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
package tempconv
import "fmt"
func Example_one() {
{
//!+arith
fmt.Printf("%g\n", BoilingC-FreezingC) // "100" °C
boilingF := CToF(BoilingC)
fmt.Printf("%g\n", boilingF-CToF(FreezingC)) // "180" °F
//!-arith
}
/*
//!+arith
fmt.Printf("%g\n", boilingF-FreezingC) // compile error: type mismatch
//!-arith
*/
// Output:
// 100
// 180
}
func Example_two() {
//!+printf
c := FToC(212.0)
fmt.Println(c.String()) // "100°C"
fmt.Printf("%v\n", c) // "100°C"; no need to call String explicitly
fmt.Printf("%s\n", c) // "100°C"
fmt.Println(c) // "100°C"
fmt.Printf("%g\n", c) // "100"; does not call String
fmt.Println(float64(c)) // "100"; does not call String
//!-printf
// Output:
// 100°C
// 100°C
// 100°C
// 100°C
// 100
// 100
}

44
vendor/gopl.io/ch3/basename1/main.go generated vendored
View File

@ -1,44 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 72.
// Basename1 reads file names from stdin and prints the base name of each one.
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
input := bufio.NewScanner(os.Stdin)
for input.Scan() {
fmt.Println(basename(input.Text()))
}
// NOTE: ignoring potential errors from input.Err()
}
//!+
// basename removes directory components and a .suffix.
// e.g., a => a, a.go => a, a/b/c.go => c, a/b.c.go => b.c
func basename(s string) string {
// Discard last '/' and everything before.
for i := len(s) - 1; i >= 0; i-- {
if s[i] == '/' {
s = s[i+1:]
break
}
}
// Preserve everything before last '.'.
for i := len(s) - 1; i >= 0; i-- {
if s[i] == '.' {
s = s[:i]
break
}
}
return s
}
//!-

36
vendor/gopl.io/ch3/basename2/main.go generated vendored
View File

@ -1,36 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 72.
// Basename2 reads file names from stdin and prints the base name of each one.
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
input := bufio.NewScanner(os.Stdin)
for input.Scan() {
fmt.Println(basename(input.Text()))
}
// NOTE: ignoring potential errors from input.Err()
}
// basename removes directory components and a trailing .suffix.
// e.g., a => a, a.go => a, a/b/c.go => c, a/b.c.go => b.c
//!+
func basename(s string) string {
slash := strings.LastIndex(s, "/") // -1 if "/" not found
s = s[slash+1:]
if dot := strings.LastIndex(s, "."); dot >= 0 {
s = s[:dot]
}
return s
}
//!-

40
vendor/gopl.io/ch3/comma/main.go generated vendored
View File

@ -1,40 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 73.
// Comma prints its argument numbers with a comma at each power of 1000.
//
// Example:
// $ go build gopl.io/ch3/comma
// $ ./comma 1 12 123 1234 1234567890
// 1
// 12
// 123
// 1,234
// 1,234,567,890
//
package main
import (
"fmt"
"os"
)
func main() {
for i := 1; i < len(os.Args); i++ {
fmt.Printf(" %s\n", comma(os.Args[i]))
}
}
//!+
// comma inserts commas in a non-negative decimal integer string.
func comma(s string) string {
n := len(s)
if n <= 3 {
return s
}
return comma(s[:n-3]) + "," + s[n-3:]
}
//!-

View File

@ -1,84 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 61.
//!+
// Mandelbrot emits a PNG image of the Mandelbrot fractal.
package main
import (
"image"
"image/color"
"image/png"
"math/cmplx"
"os"
)
func main() {
const (
xmin, ymin, xmax, ymax = -2, -2, +2, +2
width, height = 1024, 1024
)
img := image.NewRGBA(image.Rect(0, 0, width, height))
for py := 0; py < height; py++ {
y := float64(py)/height*(ymax-ymin) + ymin
for px := 0; px < width; px++ {
x := float64(px)/width*(xmax-xmin) + xmin
z := complex(x, y)
// Image point (px, py) represents complex value z.
img.Set(px, py, mandelbrot(z))
}
}
png.Encode(os.Stdout, img) // NOTE: ignoring errors
}
func mandelbrot(z complex128) color.Color {
const iterations = 200
const contrast = 15
var v complex128
for n := uint8(0); n < iterations; n++ {
v = v*v + z
if cmplx.Abs(v) > 2 {
return color.Gray{255 - contrast*n}
}
}
return color.Black
}
//!-
// Some other interesting functions:
func acos(z complex128) color.Color {
v := cmplx.Acos(z)
blue := uint8(real(v)*128) + 127
red := uint8(imag(v)*128) + 127
return color.YCbCr{192, blue, red}
}
func sqrt(z complex128) color.Color {
v := cmplx.Sqrt(z)
blue := uint8(real(v)*128) + 127
red := uint8(imag(v)*128) + 127
return color.YCbCr{128, blue, red}
}
// f(x) = x^4 - 1
//
// z' = z - f(z)/f'(z)
// = z - (z^4 - 1) / (4 * z^3)
// = z - (z - 1/z^3) / 4
func newton(z complex128) color.Color {
const iterations = 37
const contrast = 7
for i := uint8(0); i < iterations; i++ {
z -= (z - 1/(z*z*z)) / 4
if cmplx.Abs(z*z*z*z-1) < 1e-6 {
return color.Gray{255 - contrast*i}
}
}
return color.Black
}

View File

@ -1,30 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 77.
// Netflag demonstrates an integer type used as a bit field.
package main
import (
"fmt"
. "net"
)
//!+
func IsUp(v Flags) bool { return v&FlagUp == FlagUp }
func TurnDown(v *Flags) { *v &^= FlagUp }
func SetBroadcast(v *Flags) { *v |= FlagBroadcast }
func IsCast(v Flags) bool { return v&(FlagBroadcast|FlagMulticast) != 0 }
func main() {
var v Flags = FlagMulticast | FlagUp
fmt.Printf("%b %t\n", v, IsUp(v)) // "10001 true"
TurnDown(&v)
fmt.Printf("%b %t\n", v, IsUp(v)) // "10000 false"
SetBroadcast(&v)
fmt.Printf("%b %t\n", v, IsUp(v)) // "10010 false"
fmt.Printf("%b %t\n", v, IsCast(v)) // "10010 true"
}
//!-

33
vendor/gopl.io/ch3/printints/main.go generated vendored
View File

@ -1,33 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 74.
// Printints demonstrates the use of bytes.Buffer to format a string.
package main
import (
"bytes"
"fmt"
)
//!+
// intsToString is like fmt.Sprint(values) but adds commas.
func intsToString(values []int) string {
var buf bytes.Buffer
buf.WriteByte('[')
for i, v := range values {
if i > 0 {
buf.WriteString(", ")
}
fmt.Fprintf(&buf, "%d", v)
}
buf.WriteByte(']')
return buf.String()
}
func main() {
fmt.Println(intsToString([]int{1, 2, 3})) // "[1, 2, 3]"
}
//!-

62
vendor/gopl.io/ch3/surface/main.go generated vendored
View File

@ -1,62 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 58.
//!+
// Surface computes an SVG rendering of a 3-D surface function.
package main
import (
"fmt"
"math"
)
const (
width, height = 600, 320 // canvas size in pixels
cells = 100 // number of grid cells
xyrange = 30.0 // axis ranges (-xyrange..+xyrange)
xyscale = width / 2 / xyrange // pixels per x or y unit
zscale = height * 0.4 // pixels per z unit
angle = math.Pi / 6 // angle of x, y axes (=30°)
)
var sin30, cos30 = math.Sin(angle), math.Cos(angle) // sin(30°), cos(30°)
func main() {
fmt.Printf("<svg xmlns='http://www.w3.org/2000/svg' "+
"style='stroke: grey; fill: white; stroke-width: 0.7' "+
"width='%d' height='%d'>", width, height)
for i := 0; i < cells; i++ {
for j := 0; j < cells; j++ {
ax, ay := corner(i+1, j)
bx, by := corner(i, j)
cx, cy := corner(i, j+1)
dx, dy := corner(i+1, j+1)
fmt.Printf("<polygon points='%g,%g %g,%g %g,%g %g,%g'/>\n",
ax, ay, bx, by, cx, cy, dx, dy)
}
}
fmt.Println("</svg>")
}
func corner(i, j int) (float64, float64) {
// Find point (x,y) at corner of cell (i,j).
x := xyrange * (float64(i)/cells - 0.5)
y := xyrange * (float64(j)/cells - 0.5)
// Compute surface height z.
z := f(x, y)
// Project (x,y,z) isometrically onto 2-D SVG canvas (sx,sy).
sx := width/2 + (x-y)*cos30*xyscale
sy := height/2 + (x+y)*sin30*xyscale - z*zscale
return sx, sy
}
func f(x, y float64) float64 {
r := math.Hypot(x, y) // distance from (0,0)
return math.Sin(r) / r
}
//!-

79
vendor/gopl.io/ch4/append/main.go generated vendored
View File

@ -1,79 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 88.
// Append illustrates the behavior of the built-in append function.
package main
import "fmt"
func appendslice(x []int, y ...int) []int {
var z []int
zlen := len(x) + len(y)
if zlen <= cap(x) {
// There is room to expand the slice.
z = x[:zlen]
} else {
// There is insufficient space.
// Grow by doubling, for amortized linear complexity.
zcap := zlen
if zcap < 2*len(x) {
zcap = 2 * len(x)
}
z = make([]int, zlen, zcap)
copy(z, x)
}
copy(z[len(x):], y)
return z
}
//!+append
func appendInt(x []int, y int) []int {
var z []int
zlen := len(x) + 1
if zlen <= cap(x) {
// There is room to grow. Extend the slice.
z = x[:zlen]
} else {
// There is insufficient space. Allocate a new array.
// Grow by doubling, for amortized linear complexity.
zcap := zlen
if zcap < 2*len(x) {
zcap = 2 * len(x)
}
z = make([]int, zlen, zcap)
copy(z, x) // a built-in function; see text
}
z[len(x)] = y
return z
}
//!-append
//!+growth
func main() {
var x, y []int
for i := 0; i < 10; i++ {
y = appendInt(x, i)
fmt.Printf("%d cap=%d\t%v\n", i, cap(y), y)
x = y
}
}
//!-growth
/*
//!+output
0 cap=1 [0]
1 cap=2 [0 1]
2 cap=4 [0 1 2]
3 cap=4 [0 1 2 3]
4 cap=8 [0 1 2 3 4]
5 cap=8 [0 1 2 3 4 5]
6 cap=8 [0 1 2 3 4 5 6]
7 cap=8 [0 1 2 3 4 5 6 7]
8 cap=16 [0 1 2 3 4 5 6 7 8]
9 cap=16 [0 1 2 3 4 5 6 7 8 9]
//!-output
*/

View File

@ -1,30 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 117.
// Autoescape demonstrates automatic HTML escaping in html/template.
package main
import (
"html/template"
"log"
"os"
)
//!+
func main() {
const templ = `<p>A: {{.A}}</p><p>B: {{.B}}</p>`
t := template.Must(template.New("escape").Parse(templ))
var data struct {
A string // untrusted plain text
B template.HTML // trusted HTML
}
data.A = "<b>Hello!</b>"
data.B = "<b>Hello!</b>"
if err := t.Execute(os.Stdout, data); err != nil {
log.Fatal(err)
}
}
//!-

56
vendor/gopl.io/ch4/charcount/main.go generated vendored
View File

@ -1,56 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 97.
//!+
// Charcount computes counts of Unicode characters.
package main
import (
"bufio"
"fmt"
"io"
"os"
"unicode"
"unicode/utf8"
)
func main() {
counts := make(map[rune]int) // counts of Unicode characters
var utflen [utf8.UTFMax + 1]int // count of lengths of UTF-8 encodings
invalid := 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
}
counts[r]++
utflen[n]++
}
fmt.Printf("rune\tcount\n")
for c, n := range counts {
fmt.Printf("%q\t%d\n", c, n)
}
fmt.Print("\nlen\tcount\n")
for i, n := range utflen {
if i > 0 {
fmt.Printf("%d\t%d\n", i, n)
}
}
if invalid > 0 {
fmt.Printf("\n%d invalid UTF-8 characters\n", invalid)
}
}
//!-

33
vendor/gopl.io/ch4/dedup/main.go generated vendored
View File

@ -1,33 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 96.
// Dedup prints only one instance of each line; duplicates are removed.
package main
import (
"bufio"
"fmt"
"os"
)
//!+
func main() {
seen := make(map[string]bool) // a set of strings
input := bufio.NewScanner(os.Stdin)
for input.Scan() {
line := input.Text()
if !seen[line] {
seen[line] = true
fmt.Println(line)
}
}
if err := input.Err(); err != nil {
fmt.Fprintf(os.Stderr, "dedup: %v\n", err)
os.Exit(1)
}
}
//!-

46
vendor/gopl.io/ch4/embed/main.go generated vendored
View File

@ -1,46 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 106.
// Embed demonstrates basic struct embedding.
package main
import "fmt"
type Point struct{ X, Y int }
type Circle struct {
Point
Radius int
}
type Wheel struct {
Circle
Spokes int
}
func main() {
var w Wheel
//!+
w = Wheel{Circle{Point{8, 8}, 5}, 20}
w = Wheel{
Circle: Circle{
Point: Point{X: 8, Y: 8},
Radius: 5,
},
Spokes: 20, // NOTE: trailing comma necessary here (and at Radius)
}
fmt.Printf("%#v\n", w)
// Output:
// Wheel{Circle:Circle{Point:Point{X:8, Y:8}, Radius:5}, Spokes:20}
w.X = 42
fmt.Printf("%#v\n", w)
// Output:
// Wheel{Circle:Circle{Point:Point{X:42, Y:8}, Radius:5}, Spokes:20}
//!-
}

35
vendor/gopl.io/ch4/github/github.go generated vendored
View File

@ -1,35 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 110.
//!+
// Package github provides a Go API for the GitHub issue tracker.
// See https://developer.github.com/v3/search/#search-issues.
package github
import "time"
const IssuesURL = "https://api.github.com/search/issues"
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
}
type User struct {
Login string
HTMLURL string `json:"html_url"`
}
//!-

53
vendor/gopl.io/ch4/github/search.go generated vendored
View File

@ -1,53 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//!+
package github
import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"strings"
)
// 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
}
//!-
// For long-term stability, instead of http.Get, use the
// variant below which adds an HTTP request header indicating
// that only version 3 of the GitHub API is acceptable.
//
// req, err := http.NewRequest("GET", IssuesURL+"?q="+q, nil)
// if err != nil {
// return nil, err
// }
// req.Header.Set(
// "Accept", "application/vnd.github.v3.text-match+json")
// resp, err := http.DefaultClient.Do(req)
//!+
// 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
}
//!-

43
vendor/gopl.io/ch4/graph/main.go generated vendored
View File

@ -1,43 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 99.
// Graph shows how to use a map of maps to represent a directed graph.
package main
import "fmt"
//!+
var graph = make(map[string]map[string]bool)
func addEdge(from, to string) {
edges := graph[from]
if edges == nil {
edges = make(map[string]bool)
graph[from] = edges
}
edges[to] = true
}
func hasEdge(from, to string) bool {
return graph[from][to]
}
//!-
func main() {
addEdge("a", "b")
addEdge("c", "d")
addEdge("a", "d")
addEdge("d", "a")
fmt.Println(hasEdge("a", "b"))
fmt.Println(hasEdge("c", "d"))
fmt.Println(hasEdge("a", "d"))
fmt.Println(hasEdge("d", "a"))
fmt.Println(hasEdge("x", "b"))
fmt.Println(hasEdge("c", "d"))
fmt.Println(hasEdge("x", "d"))
fmt.Println(hasEdge("d", "x"))
}

52
vendor/gopl.io/ch4/issues/main.go generated vendored
View File

@ -1,52 +0,0 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 112.
//!+
// Issues prints a table of GitHub issues matching the search terms.
package main
import (
"fmt"
"log"
"os"
"gopl.io/ch4/github"
)
//!+
func main() {
result, err := github.SearchIssues(os.Args[1:])
if err != nil {
log.Fatal(err)
}
fmt.Printf("%d issues:\n", result.TotalCount)
for _, item := range result.Items {
fmt.Printf("#%-5d %9.9s %.55s\n",
item.Number, item.User.Login, item.Title)
}
}
//!-
/*
//!+textoutput
$ go build gopl.io/ch4/issues
$ ./issues repo:golang/go is:open json decoder
13 issues:
#5680 eaigner encoding/json: set key converter on en/decoder
#6050 gopherbot encoding/json: provide tokenizer
#8658 gopherbot encoding/json: use bufio
#8462 kortschak encoding/json: UnmarshalText confuses json.Unmarshal
#5901 rsc encoding/json: allow override type marshaling
#9812 klauspost encoding/json: string tag not symmetric
#7872 extempora encoding/json: Encoder internally buffers full output
#9650 cespare encoding/json: Decoding gives errPhase when unmarshalin
#6716 gopherbot encoding/json: include field name in unmarshal error me
#6901 lukescott encoding/json, encoding/xml: option to treat unknown fi
#6384 joeshaw encoding/json: encode precise floating point integers u
#6647 btracey x/tools/cmd/godoc: display type kind of each named type
#4237 gjemiller encoding/base64: URLEncoding padding is optional
//!-textoutput
*/

Some files were not shown because too many files have changed in this diff Show More