APP/小程序/网站开发

APP/小程序/网站开发

Go学习笔记之一

- by zhaiduo.com - 标签: gogolang

运行项目

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/