Golang-01-基础

仅记录 Golang 学习过程中一些容易记错的地方。

数组赋值问题

1
2
3
4
5
var arr = [5]int{1, 2, 3, 4, 5}
var arr1 [5]int = arr
var arr2 [6]int = arrr

// error message: cannot use arr (type [5]int) as type [6]int in assignment

arr 可以赋值给 arr1,但是不能赋值给 arr2,只有同样类型(长度一样、并且每个元素类型一样)才可以相互赋值

Map与Json的互转

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
res := make(map[string]interface{})
res["code"] = 200
res["message"] = "success"
res["data"] = map[string]interface{}{
	"username": "张三",
	"age":      18,
	"like":     []string{"读书", "编程"},
}
fmt.Println("res map data :", res)
// res map data : map[code:200 data:map[age:18 like:[读书 编程] username:张三] message:success]

// 序列化
jsons, err := json.Marshal(res)
if err != nil {
	fmt.Println("序列化错误", err)
}

fmt.Println("jsons data :", string(jsons))
// jsons data : {"code":200,"data":{"age":18,"like":["读书","编程"],"username":"张三"},"message":"success"}

// 反序列化
res2 := make(map[string]interface{})
err = json.Unmarshal([]byte(jsons), &res2)

if err != nil {
	fmt.Println("反序列化失败", err)
}

fmt.Println("map data", res2)
// map data map[code:200 data:map[age:18 like:[读书 编程] username:张三] message:success]

关于并发和并行

golang协程是并发机制

  • 并发是不同代码块交替执行,也就是交替可以做不同的事情。例如:你正在做饭,突然来个电话,你去接电话了,接完电话后继续回来做饭。(交替做)
  • 并行是不同代码块同时执行,也就是同时可以做不同的事情。例如:你正在做饭,突然来个电话,你边接电话,边做饭。(同时做)

关于 chan

  • 不带缓冲的通道,进和出都会阻塞。带缓冲的通道,进一次长度+1,出一次长度-1,如果长度等于缓冲长度时,再进会阻塞。
  • 通道 close 后不能再写入,写入会 panic。
  • 通道 close 后还可以读取数据。
  • 重复 close 会 panic。
  • 只读的 chan 不能 close。

关于 defer

  • 当os.Exit()方法退出程序时,defer不会被执行。
  • defer 只对当前协程有效。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
func calc(index string, a, b int) int {
	ret := a + b
	fmt.Println(index, a, b, ret)
	return ret
}

func main() {
	x := 1
	y := 2
	defer calc("A", x, calc("B", x, y))
	x = 3
	defer calc("C", x, calc("D", x, y))
	y = 4
}

输出结果:

1
2
3
4
B 1 2 3
D 3 2 5
C 3 5 8
A 1 3 4
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
func main() {
	a := 1
	b := 2

	defer func(a, b int) {
		fmt.Println("带参数的:", a+b)
	}(a, b)
	defer func() {
		fmt.Println("不带参数的:", a+b)
	}()

	a = 3
}
// 输出:golang 传参一定是传值的,而闭包获取变量相当于引用。
// 不带参数的: 5
// 带参数的: 3

关于 Write 和 Reader 的理解

io.Write 规则:

  1. 向底层数据写入 len(p) 字节的切片 p
  2. 返回被写入的字节数 n
  3. 如果 n < len(p),则必须返回非 nil 的 err
  4. 如果中途出现错误,必须返回非 nil 的 err
  5. 切片 p 不允许修改

io.Reader 规则:

  1. 最多读取 len(p) 字节的数据
  2. 返回读取的字节数以及任何发送的错误信息
  3. 当 n < len(p) 表示读取的数据不足以填满p,此时会立刻返回
  4. 读取遇到错误,会返回读取到的字节数n,以及相应的err
  5. 底层输入流结束时,方法会返回字节数n,但 err 可能是 EOF,也可能是nil,再次调用 read 方法的时候,肯定会返回 n = 0, err = EOF
  6. 如果 n > 0,优先处理读入的数据,再处理 err
doodo
Built with Hugo
主题 StackJimmy 设计
本站总访问量  |  本站访客数