Go学习笔记之一
运行项目
1mkdir hello
2cd hello
3go mod init hello
4coding
5go run .
获取执行目录并安装执行
1cd main
2go list -f '{{.Target}}'
3=========================
4/Users/$USER/go/bin/main
/Users/$USER/go/bin/ 既是执行目录 把执行目录加入环境变量 export PATH=$PATH:/Users/$USER/go/bin/
1vim ~/.zshrc
2. ~/.zshrc
3cd main
4go install
5main
6=========================
7hello: empty name
8
9
10ls /Users/$USER/go/bin/
11=========================
12main
如果需要卸载,直接删除上面路径的程序即可
牛顿法平方根
1package main
2
3import (
4 "fmt"
5 "math"
6)
7
8//go不允许默认参数值
9//牛顿法平方根
10func Sqrt(x float64, salt float64) float64 {
11 zhi := 1.0
12 zz := 0.0
13 for z := 1.0; z <= x; z += salt {
14 tmp := (z * z - x) / 2 * z
15 if tmp < math.Abs(zhi) {
16 zhi = tmp
17 } else {
18 //fmt.Println(z, zhi, math.Sqrt(x))
19 zz = z
20 break;
21 }
22 }
23 return zz
24}
25
26func main() {
27 fmt.Println(Sqrt(2, 0.001))
28 fmt.Println(math.Sqrt(2))
29}
函数没有默认参数值
1type Vertex struct {
2 X int
3 Y int
4}
5
6func defaultValue(x int) {
7 v := Vertex{3, 4}
8 if x > 0 {
9 v.X = x
10 }
11 fmt.Println(v)
12}
13
14func main() {
15 v := Vertex{1, 2}
16 v.X = 4
17 defaultValue(1)
18 fmt.Println(v.X)
19}
但是结构体有
1v2 = Vertex{X: 1} // Y:0 被隐式地赋予
2v3 = Vertex{} // X:0 Y:0
defer 语句的用处
函数执行后的清理任务,多个defer的顺序是先进后出,如果defer函数,可以修改相应参数 https://blog.go-zh.org/defer-panic-and-recover
Go 拥有指针
数组不能改变大小,切片可以,切片就像数组的引用
nil 切片的长度和容量为 0 且没有底层数组。
井字板
https://tour.go-zh.org/moretypes/14
1package main
2
3import (
4 "fmt"
5 "strings"
6)
7
8func boards(w int, h int) []string {
9 //row := make([]string, w, w)
10 board := []string{}
11 return board
12}
13
14func main() {
15 // 创建一个井字板(经典游戏)
16 row := make([]string, 10, 10)
17
18 board := [][]string{}
19 for i := 0; i < 10; i++ {
20 board = append(board, row)
21 }
22 for i := 0; i < len(board); i++ {
23 for j := 0; j < len(board[i]); j++ {
24 board[i][j] = "_"
25 //fmt.Printf("%s %d %d\n", board[i][j], i, j)
26 }
27 }
28
29 // 两个玩家轮流打上 X 和 O
30 board[0][0] = "X"
31 board[2][2] = "O"
32 board[1][2] = "X"
33 board[1][0] = "O"
34 board[0][2] = "X"
35
36 for i := 0; i < len(board); i++ {
37 fmt.Printf("%s\n", strings.Join(board[i], " "))
38 }
39}
图片处理
https://tour.go-zh.org/moretypes/18
1package main
2
3import (
4//"fmt"
5"math"
6"golang.org/x/tour/pic"
7)
8
9func Pic(dx, dy int) [][]uint8 {
10 xx := make([]uint8, dx, dx)
11 board := [][]uint8{}
12 for i := 0; i < dy; i++ {
13 board = append(board, xx)
14 }
15 for i := 0; i < dy; i++ {
16 for j := 0; j < dx; j++ {
17 //board[i][j] = uint8((i+j)/2)
18 //board[i][j] = uint8(i^j)
19 board[i][j] = uint8(float64(i)*math.Log(float64(j)))
20 //board[i][j] = uint8(i%(j+1))
21 //fmt.Printf("%d %d %d\n", board[i][j], i, j)
22 }
23 }
24 return board
25}
26
27func main() {
28 pic.Show(Pic)
29 //Pic(3,3)
30}
31
映射需要make才能被调用
1//这个语法有点难看
2var m map[string]Vertex
3m = make(map[string]Vertex)
4
5或者
6
7var m map[string]Vertex{...}
若顶级类型只是一个类型名,你可以在文法的元素中省略它。 获取键值:elem, ok := m[key]
1package main
2
3import (
4 //"fmt"
5 "strings"
6 "golang.org/x/tour/wc"
7)
8
9func WordCount(s string) map[string]int {
10 //fmt.Printf("%s\n",strings.Fields(s.split(" ")))
11 arr := strings.Fields(" "+s+" ")
12 //fmt.Printf("Fields are: %q", arr)
13 var m map[string]int
14 m = make(map[string]int)
15 for i := 0; i < len(arr); i++ {
16 _,ok := m[arr[i]]
17 if ok {
18 m[arr[i]]+=1
19 } else {
20 m[arr[i]]=1
21 }
22 }
23 //fmt.Printf("m are: %q", m)
24 return m
25}
26
27func main() {
28 wc.Test(WordCount)
29 //WordCount("ss ss cc")
30}
31
函数值
函数值可以用作函数的参数或返回值。
1func compute(fn func(float64, float64) float64, x float64, y float64) float64 {
2 return fn(x, y)
3}
闭包:函数作为返回值,该函数被这些变量“绑定”在一起。
1func adder() func(int) int {
2 sum := 0
3 return func(x int) int {
4 sum += x
5 return sum
6 }
7}
斐波纳契
1package main
2
3import "fmt"
4
5// 返回一个“返回int的函数”
6func fibonacci() func() int {
7 n := 0
8 a := 0
9 b := 0
10 sum := 1
11 return func() int {
12 n++
13 if n == 1 {
14 a = 0
15 return b
16 } else if n == 2 {
17 b = 1
18 a = 1
19 return b
20 } else if n == 3 {
21 b = 1
22 a = 1
23 return b
24 } else {
25 a = b
26 b = sum
27 sum = a + b
28 //fmt.Printf("%d, %d", int(a), int(b))
29 return sum
30 }
31 }
32}
33
34func main() {
35 f := fibonacci()
36 for i := 0; i < 20; i++ {
37 fmt.Println(f())
38 }
39}
40
Go 没有类。方法接收者在它自己的参数列表内,位于 func 关键字和方法名之间。
1type Vertex struct {
2 X, Y float64
3}
4
5func (v Vertex) Abs() float64 {
6 if v == nil {
7 fmt.Println("<nil>")
8 return
9 }
10 return math.Sqrt(v.X*v.X + v.Y*v.Y)
11}
就是接收者的类型定义和方法声明必须在同一包内;不能为内建类型声明方法
1type MyFloat float64
2func (f MyFloat) Abs() float64 {
3 if f < 0 {
4 return float64(-f)
5 }
6 return float64(f)
7}
8
接口类型
接口类型的变量可以保存任何实现了这些方法的值。
1type Abser interface {
2 Abs() float64
3}
4func describe(i I) {
5 fmt.Printf("(%v, %T)\n", i, i)
6}
7var a Abser
8f := MyFloat(-math.Sqrt2)
9v := Vertex{3, 4}
10var i Abser = Vertex{1,2}
11a = f // a MyFloat 实现了 Abser
12a.Abs()
13a = &v // a *Vertex 实现了 Abser
14a.Abs()
15describe(a)
16i.Abs()
17describe(i)
18
19var j interface{}
20describe(j)
21s, ok := j.(string)
22fmt.Println(s, ok)
23
接口值可以看做包含值和具体类型的元组 空接口可保存任何类型的值。
类型断言
1var i interface{} = "hello"
2s, ok := i.(string)
3
4//类型选择
5switch v := i.(type) {
6case T:
7 // v 的类型为 T
8case S:
9 // v 的类型为 S
10default:
11 // 没有匹配,v 与 i 的类型相同
12}
String()/Error() 是最普遍的接口方法之一。
1type IPAddr [4]byte
2func (p IPAddr) String() string {
3 return fmt.Sprintf("%d.%d.%d.%d", p[0], p[1], p[2], p[3])
4}
5func (p IPAddr) Error() string {
6 return fmt.Sprintf("error IPAddr:")
7}
实现一个 Reader 类型,它产生一个 ASCII 字符 'A' 的无限流。
1package main
2
3import "fmt"
4import "golang.org/x/tour/reader"
5
6type MyReader struct{}
7type MyError struct {
8 What string
9}
10
11// TODO: 给 MyReader 添加一个 Read([]byte) (int, error) 方法
12func (r MyReader) Read(b []byte)(int, error) {
13 if b == nil {
14 fmt.Println("<nil>")
15 return 0, &MyError{"无效"}
16 }
17 //fmt.Printf("%s", string(b[0]))
18 //fmt.Sprintf('A')
19 return int(b[0]), nil
20}
21
22func (e *MyError) Error() string {
23 return fmt.Sprintf("%s",e.What)
24}
25
26func main() {
27 reader.Validate(MyReader{})
28}
29
ROT13编码
https://tour.go-zh.org/methods/23
1package main
2
3import (
4 "fmt"
5 "io"
6 "os"
7 "strings"
8 "bytes"
9)
10
11var ascii_uppercase = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
12var ascii_lowercase = []byte("abcdefghijklmnopqrstuvwxyz")
13var ascii_uppercase_len = len(ascii_uppercase)
14var ascii_lowercase_len = len(ascii_lowercase)
15
16type rot13Reader struct {
17 r io.Reader
18}
19type MyError struct {
20 What string
21}
22
23func (e *MyError) Error() string {
24 return fmt.Sprintf("%s",e.What)
25}
26
27func rot13(b byte) byte {
28 pos := bytes.IndexByte(ascii_uppercase, b)
29 if pos != -1 {
30 return ascii_uppercase[(pos+13) % ascii_uppercase_len]
31 }
32 pos = bytes.IndexByte(ascii_lowercase, b)
33 if pos != -1 {
34 return ascii_lowercase[(pos+13) % ascii_lowercase_len]
35 }
36 return b
37}
38
39func (r rot13Reader) Read(b []byte)(int, error) {
40 n, err := r.r.Read(b)
41 if b == nil {
42 //fmt.Println("<nil>")
43 return 0, &MyError{"无效"}
44 }
45 //fmt.Printf("bb = %v \n", n)
46 for i := 0; i < n; i++ {
47 b[i] = rot13(b[i])
48 }
49 return n, err
50}
51
52func main() {
53 s := strings.NewReader("Lbh penpxrq gur pbqr!")
54 fmt.Printf("s = %v \n", s)
55 r := rot13Reader{s}
56 fmt.Printf("r = %v \n", &r)
57 io.Copy(os.Stdout, &r)
58}
59
图片生成器
https://tour.go-zh.org/methods/25
1package main
2
3import "golang.org/x/tour/pic"
4import "image"
5import "image/color"
6
7type Image struct{
8 width int
9 height int
10}
11
12func (img Image) ColorModel() color.Model {
13 board := color.RGBAModel
14 return board
15}
16
17func (img Image) Bounds() image.Rectangle {
18 board := image.Rect(0, 0, img.width, img.height)
19 return board
20}
21
22func (img Image) At(x, y int) color.Color {
23 v := uint8(x^y)
24 board := color.RGBA{v, v, 255, 255}
25 return board
26}
27
28func main() {
29 m := Image{100, 100}
30 pic.ShowImage(m)
31}
32
参考
https://tour.go-zh.org/