1、命令行输入
os.Args是一个字符串切片,是半开区间,通过os.Args[i]来访问元素;如果变量未在声明的时候初始化,将隐式的初始化为这个类型的空值;
操作符 += 是个赋值操作符;
i++ 是一个语句不是表达式;
for是go唯一的循环:
for initialization; condition; post {
//零个或多个语句
}
三个部分都是可以省略的
//传统的while循环
for condition {
// ...
}
//传统的无限循环
for {
// ...
}
//for range循环
for key, value := range os.Args[1:] {
// ...
}
循环可以通过break或者return结束;
空标识符 _ 表示丢弃临时变量;
//变量的声明方式
s := ""
var s string
var s = ""
var s string = ""
strings.Join( s []string, " " )
2、找出重复的行
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
counts := make(map[string]int)
input := bufio.NewScanner(os.Stdin)
for input.Scan() {
if input.Text() != "EOF" {
counts[input.Text()]++
} else {
break
}
}
for line, n := range counts {
if n > 1 {
fmt.Printf("%d\t%s\n", n, line)
}
}
}
map存储一个键值对组合,键可以是一个进行==比较的任意类型,值可以是任意类型,内置函数make可以用来新建map;
printf转义字符verb
verb | 描述 |
%d %x %o %b | 十、十六、八、二进制整数 |
%f %g %e | 浮点数 |
%t | 布尔型 |
%c %s %q %v %T %% | 字符、字符串、带引号的字符串、任何值、值类型、百分号本身 |
以f结尾的函数,使用和printf相同的格式化规则,以ln结尾的函数,使用%v来格式化参数
输入输出函数bufio.Scanner, ioutil.Readfile,ioutil.WriteFile使用*os.File中的Read和write方法
3、gif动画
package main
import (
"image"
"image/color"
"image/gif"
"io"
"log"
"math"
"math/rand"
"net/http"
"os"
"time"
)
var palette = []color.Color{color.White, color.Black}
const (
whiteIdex = 0
blackIdex = 1
)
func main() {
rand.Seed(time.Now().UTC().UnixNano())
if len(os.Args) > 1 && os.Args[1] == "web" {
handler := func(w http.ResponseWriter, r *http.Request) {
lissajous(w)
}
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe("localhost:8000", nil))
return
}
lissajous(os.Stdout)
}
func lissajous(out io.Writer) {
const (
cycles = 5
res = 0.001
size = 100
nframes = 64
delay = 8
)
freq := rand.Float64() * 3.0
anim := gif.GIF{LoopCount: nframes}
phase := 0.0
for i := 0; i < nframes; i++ {
rect := image.Rect(0, 0, 2*size+1, 2*size+1)
img := image.NewPaletted(rect, palette)
for t := 0.0; t < cycles*2*math.Pi; t += res {
x := math.Sin(t)
y := math.Sin(t*freq + phase)
img.SetColorIndex(size+int(x*size+0.5), size+int(y*size+0.5), blackIdex)
}
phase += 0.1
anim.Delay = append(anim.Delay, delay)
anim.Image = append(anim.Image, img)
}
gif.EncodeAll(out, &anim)
}
package main
import (
"image"
"image/color"
"image/gif"
"io"
"log"
"math"
"math/rand"
"net/http"
"os"
"time"
)
var palette = []color.Color{color.White, color.Black}
const (
whiteIdex = 0
blackIdex = 1
)
func main() {
rand.Seed(time.Now().UTC().UnixNano())
if len(os.Args) > 1 && os.Args[1] == "web" {
handler := func(w http.ResponseWriter, r *http.Request) {
lissajous(w)
}
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe("localhost:8000", nil))
return
}
lissajous(os.Stdout)
}
func lissajous(out io.Writer) {
const (
cycles = 5
res = 0.001
size = 100
nframes = 64
delay = 8
)
freq := rand.Float64() * 3.0
anim := gif.GIF{LoopCount: nframes}
phase := 0.0
for i := 0; i < nframes; i++ {
rect := image.Rect(0, 0, 2*size+1, 2*size+1)
img := image.NewPaletted(rect, palette)
for t := 0.0; t < cycles*2*math.Pi; t += res {
x := math.Sin(t)
y := math.Sin(t*freq + phase)
img.SetColorIndex(size+int(x*size+0.5), size+int(y*size+0.5), blackIdex)
}
phase += 0.1
anim.Delay = append(anim.Delay, delay)
anim.Image = append(anim.Image, img)
}
gif.EncodeAll(out, &anim)
}
[]color.Color{...} gif.GIF{...}是复合字面量,用一系列元素的值初始化go的复合类型的紧凑表达式
结构体的字段可以使用点标记法来访问
4、获取一个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)
}
bytes, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
fmt.Fprintf(os.Stderr, "reading: %v\n", err)
os.Exit(1)
}
fmt.Printf("%s", string(bytes))
}
}
resp.body.close()关闭body数据流来避免资源泄露
5、并发获取多个url
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)
}
for range os.Args[1:] {
fmt.Println(<-ch) //从通道ch接收值
}
fmt.Printf("%.2fs elapsed\n", time.Since(start).Seconds())
}
func fetch(url string, ch chan<- string) {
start := time.Now()
resp, err := http.Get(url)
if err != nil {
ch <- fmt.Sprint(err)
return
}
nbytes, err := io.Copy(ioutil.Discard, resp.Body)
resp.Body.Close()
if err != nil {
ch <- fmt.Sprintf("while reading %s : %v\n", url, err)
return
}
secs := time.Since(start).Seconds()
ch <- fmt.Sprintf("%.2fs %7d %s", secs, nbytes, url)
}
io.copy读取响应的内容,并写入ioutil.discard输出流进行丢弃;当一个goroutie在一个通道上进行发送或接受操作时,会阻塞,直到另个goroutie进行对通道接受或发送值
6、一个web服务器
package main
import (
"fmt"
"log"
"net/http"
)
func main() {
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe("localhost:80", nil))
}
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "URL.PATH = %q\n", r.URL.Path)
}
匿名函数
package main
import (
"fmt"
"log"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request){
fmt.Fprintf(w, "URL.PATH = %q\n", r.URL.Path)
}
log.Fatal(http.ListenAndServe("localhost:80", nil))
}
fetch将程序响应os.stdout,fetchall将程序响应复制到ioutil.discard进行丢弃,web服务器使用fprintf写入http.responsWriter让浏览器显示,三者都满足接口io.Writer,按需将使用任何一种输出流;
7、其他
switch第一个匹配的case执行,否则执行default,fallthrough是个例外。也可以没有操作数,每条case都是布尔表达式等价于switch true。
**breake可以打断for, switch, select 最内层调用,开始执行下面语句。
**continue可以让for循环开始新的迭代
命名类型、指针也称引用。
方法和接口
包
所以,开始go的旅程吧。