├── .idea
├── .gitignore
├── learn_go.iml
├── modules.xml
└── vcs.xml
├── LICENSE
├── README.md
├── ebook
├── 1.md
├── 2.md
├── 3.md
├── 4.md
├── 5.md
├── 640.png
└── qrcode.png
├── lesson01
└── main.go
├── lesson02
└── main.go
├── lesson03
└── main.go
├── lesson04
└── main.go
├── lesson05
└── main.go
├── lesson06
└── main.go
├── lesson07
└── main.go
├── lesson08
└── main.go
├── lesson09
└── main.go
├── lesson10
└── main.go
├── lesson11
└── main.go
├── lesson12
└── main.go
├── lesson13
└── main.go
├── lesson14
└── main.go
├── lesson15
└── main.go
├── lesson16
└── main.go
├── lesson17
└── main.go
├── lesson18
└── main.go
├── lesson19
└── main.go
├── lesson20
└── main.go
├── lesson27
├── cpu.out
├── func.cover
├── func.go
├── func_cover.html
├── func_test.go
└── go.mod
├── lesson29
└── main.go
├── lesson30
├── go.mod
├── go.sum
└── main.go
├── lesson31
└── test
│ ├── anonymous_test.go
│ ├── closures_test.go
│ ├── higherOrder_test.go
│ └── recursion_test.go
├── lesson32
├── go.mod
├── go.sum
├── interface_test.go
└── struct_test.go
├── lesson33
└── main.go
├── lesson34
└── main.go
├── lesson35
└── main.go
├── lesson36
└── main.go
├── lesson37
└── main.go
├── lesson40
└── main.go
├── lesson41
├── app
│ └── main.go
├── domain
│ └── user.go
├── go.mod
├── go.sum
└── user
│ ├── delivery
│ └── http
│ │ └── user.go
│ ├── repository
│ └── mysql
│ │ └── user.go
│ └── usecase
│ └── user.go
├── lesson42
├── go.mod
├── go.sum
└── main.go
├── lesson43
├── go.mod
└── main.go
├── lesson44
├── go.mod
└── main.go
├── lesson45
└── main.go
├── lesson46
└── main.go
├── lesson47
├── go.mod
├── go.sum
└── main.go
├── lesson48
├── go.mod
└── main.go
├── lesson49
├── go.mod
└── main.go
├── lesson50
└── main.go
├── lesson51
├── go.mod
├── go.sum
└── main.go
├── lesson52
└── main.go
├── lesson53
└── main.go
├── lesson54
├── go.mod
└── main.go
├── lesson55
└── workspace
│ ├── .idea
│ ├── .gitignore
│ ├── modules.xml
│ └── vcs.xml
│ ├── go.work
│ ├── go.work.sum
│ └── hello
│ ├── example
│ ├── LICENSE
│ ├── README.md
│ ├── appengine-hello
│ │ ├── README.md
│ │ ├── app.go
│ │ ├── app.yaml
│ │ └── static
│ │ │ ├── favicon.ico
│ │ │ ├── index.html
│ │ │ ├── script.js
│ │ │ └── style.css
│ ├── go.mod
│ ├── go.sum
│ ├── gotypes
│ │ ├── Makefile
│ │ ├── README.md
│ │ ├── defsuses
│ │ │ └── main.go
│ │ ├── doc
│ │ │ └── main.go
│ │ ├── go-types.md
│ │ ├── hello
│ │ │ └── hello.go
│ │ ├── hugeparam
│ │ │ └── main.go
│ │ ├── implements
│ │ │ └── main.go
│ │ ├── lookup
│ │ │ └── lookup.go
│ │ ├── nilfunc
│ │ │ └── main.go
│ │ ├── pkginfo
│ │ │ └── main.go
│ │ ├── skeleton
│ │ │ └── main.go
│ │ ├── typeandvalue
│ │ │ └── main.go
│ │ └── weave.go
│ ├── hello
│ │ └── hello.go
│ ├── outyet
│ │ ├── Dockerfile
│ │ ├── containers.yaml
│ │ ├── main.go
│ │ └── main_test.go
│ ├── stringutil
│ │ ├── reverse.go
│ │ └── reverse_test.go
│ └── template
│ │ ├── image.tmpl
│ │ ├── index.tmpl
│ │ └── main.go
│ ├── go.mod
│ ├── go.sum
│ └── main.go
├── lesson56
├── go.mod
├── reverse.go
├── reverse_test.go
└── testdata
│ └── fuzz
│ └── FuzzReverse
│ └── 5d9cdd0e9f28de1a8961208a454ad8b2b2982f5554f43fba7000318303416ead
├── lesson57
└── main.go
├── lesson58
├── go.mod
├── go.sum
└── main.go
├── lesson59
├── go.mod
├── go.sum
└── main.go
├── lesson60
├── go.mod
└── main.go
├── lesson61
├── go.mod
└── main.go
├── lesson62
├── go.mod
└── main.go
├── lesson63
├── go.mod
└── main.go
├── lesson64
├── go.mod
├── go.sum
├── main.go
├── middleware
│ └── metrics.go
└── prom
│ └── metrics.go
├── lesson65
├── gin_middleware
│ └── metrics.go
├── go.mod
├── go.sum
├── main.go
└── prometheus_metrics
│ └── metrics.go
├── lesson67
├── go.mod
└── main.go
├── lesson68
├── go.mod
└── main.go
├── lesson69
├── go.mod
└── main.go
├── lesson70
├── go.mod
└── main.go
├── lesson71
├── go.mod
└── main.go
├── lesson72
├── go.mod
└── main.go
├── lesson73
├── go.mod
└── main.go
└── lesson74
├── go.mod
└── main.go
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Editor-based HTTP Client requests
5 | /httpRequests/
6 | # Datasource local storage ignored files
7 | /dataSources/
8 | /dataSources.local.xml
9 |
--------------------------------------------------------------------------------
/.idea/learn_go.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2020, frank
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | 2. Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | 3. Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Go 语言学习
2 | ### 基础知识
3 | 1. 变量
4 | 2. 基础数据类型
5 | 3. 常量
6 | 4. 运算符
7 | 5. 流程控制
8 | 6. 数组
9 | 7. slice
10 | 8. map
11 | 9. struct
12 | 10. 函数
13 | 11. 错误处理
14 | 12. panic 和 recover
15 | 13. 方法
16 | 14. 接口
17 | 15. goroutine 和 channel
18 | 16. 并发
19 | 17. 测试
20 | 18. 包
21 | 19. go tool
22 | 20. 反射
23 |
24 | ### 加餐
25 | 21. [Go Modules 介绍与基本操作](https://mp.weixin.qq.com/s/Ce56XkzkYhLu-T0zOEjkzw)
26 | 22. [GOPATH 模式怎么迁移至 Modules 模式?](https://mp.weixin.qq.com/s/89Ijd_nghmoXi4ZzXe605A)
27 | 23. [怎么发布 Go Modules v1 版本?](https://mp.weixin.qq.com/s/kj5i2SCN2SCCVexHJLtoBw)
28 | 24. [Go Modules 如何创建和发布 v2 及更高版本?](https://mp.weixin.qq.com/s/Jppyj3YLSrJbDxpJwC8B0w)
29 | 25. [保持 Modules 的兼容性](https://mp.weixin.qq.com/s/Q6hO_tc7RCOWABRwK9hrrA)
30 | 26. [Golang 1.16 中 Module 有什么变化?](https://mp.weixin.qq.com/s/MfEQ-JL-gJEgb6Sc3sr2Lw)
31 |
32 | ### 番外
33 | 27. [Golang 语言怎么编写测试代码?](https://mp.weixin.qq.com/s/P4elvWrbA8qcDcGLBcy-0Q)
34 | 28. [Golang 语言怎么高效拼接字符串?](https://mp.weixin.qq.com/s/zwVVeLdclj8qPaj189ygNg)
35 | 29. [Golang 语言怎么高效排序数据?](https://mp.weixin.qq.com/s/8gzmVFzsQowA31Tc_4nQNQ)
36 | 30. [Golang 语言极简类型转换库 cast](https://mp.weixin.qq.com/s/EBmQSE1L7PzS-Ghw-AYZ6Q)
37 | 31. [Golang 语言函数的高级使用方式](https://mp.weixin.qq.com/s/UNm-wYXudiOuWAWQHWB3TQ)
38 | 32. [Golang 语言编程使用接口有哪些好处?](https://mp.weixin.qq.com/s/VANSVcLtCLC0gWmEsa8sFw)
39 | 33. [Golang 语言怎么避免引发 panic?](https://mp.weixin.qq.com/s/D4en3Ozfp7Vf8kjPrLFbSg)
40 | 34. [Golang 语言该用命名返回值吗?](https://mp.weixin.qq.com/s/NbTzlvubUVUBakwKKNbcVw)
41 | 35. [Golang 语言 for 和 for-range 的区别](https://mp.weixin.qq.com/s/z-0Sff8r3n5TPjVXG_MIeQ)
42 | 36. [Golang 语言怎么避免空指针引发的 panic](https://mp.weixin.qq.com/s/9s6YXJsZcXyfgWDYG-WZOQ)
43 | 37. [Golang 语言怎么打印结构体指针类型字段的值?](https://mp.weixin.qq.com/s/5B-sPyk4qgFsplsJ9mMD_Q)
44 | 38. [Golang 语言 vendor 在 GOPATH 和 Modules 中的区别](https://mp.weixin.qq.com/s/1rlC-0akmgpmlmHjO-WxUA)
45 | 39. [Golang 语言的多种变量声明方式和使用场景](https://mp.weixin.qq.com/s/croxWsCnjsaPJy9zigx4Gg)
46 | 40. [Go 语言的函数是“一等公民”?](https://mp.weixin.qq.com/s/42m-EQnRqdv6_Mmt8wDn0Q)
47 | 41. [Go 语言错误处理为什么更推荐使用 pkg/errors 三方库?](https://mp.weixin.qq.com/s/nL5uIGCXYON5doGGeHchAQ)
48 | 42. [Go 语言怎么使用变长参数函数?](https://mp.weixin.qq.com/s/fhqtRTGgVu6aSC581luvCg)
49 | 43. [Go 语言逃逸分析](https://mp.weixin.qq.com/s/34cmyuPOjlhAQm6zYhBIsg)
50 | 44. [Go 语言内存逃逸案例](https://mp.weixin.qq.com/s/iACaQ8vsxEvUVsDJ5QO6UA)
51 | 45. [Go 语言短变量声明的“坑”](https://mp.weixin.qq.com/s/JnWgc0GuM_3FHPoXUlMSCg)
52 | 46. [Go 语言使用 goroutine 运行闭包的“坑”](https://mp.weixin.qq.com/s/h__5zKCKUkxUTmBjbKsA2w)
53 | 47. [Go 语言怎么处理三方接口返回数据?](https://mp.weixin.qq.com/s/QyWuOsPUFq7XqvIbnBJP_A)
54 | 48. [Go 语言怎么解决编译器错误“err is shadowed during return”?](https://mp.weixin.qq.com/s/kGC1X5DQ7eQAdn70ZhElNw)
55 | 49. [Go 语言为什么建议 append 追加新元素使用原切片变量接收返回值?](https://mp.weixin.qq.com/s/jGTslWJF4bDXmynISI9btA)
56 | 50. [Go 语言一次性定时器使用方式和实现原理](https://mp.weixin.qq.com/s/NXbYTX96hFfwYuh6gACAHg)
57 | 51. [Go 语言 errgroup 库的使用方式和实现原理](https://mp.weixin.qq.com/s/R8f_-cl98th7ZiSVxaeUAQ)
58 | 52. [Go 语言 context 最佳实践](https://mp.weixin.qq.com/s/DxEeLUS8hotYh8Js5FyR5w)
59 | 53. [Go 语言开源项目使用的函数选项模式](https://mp.weixin.qq.com/s/2jzg2PIK_esjTxSFMkp02A)
60 | 54. [Go 1.18 新增三大功能之一“泛型”怎么使用?](https://mp.weixin.qq.com/s/0JKH-Bo8n9I9zT683ZA-iw)
61 | 55. [Go 1.18 新增三大功能之一“工作区模式”介绍](https://mp.weixin.qq.com/s/C_Pnr22HIpS9SKdXRHbJ1A)
62 | 56. [Go 1.18 新增三大功能之一“模糊测试”使用方式](https://mp.weixin.qq.com/s/S2InTxuwg0G-wPSy1Q34PQ)
63 | 57. [Go 语言 15 个内置函数详解](https://mp.weixin.qq.com/s/FKp1nAX2FOeBMgchJOe4ag)
64 | 58. [Go 语言类型转换的陷阱](https://mp.weixin.qq.com/s/p1n6EAid5o_knT0i0NWX_Q)
65 | 59. [Go 语言使用 XORM 操作 MySQL 的陷阱](https://mp.weixin.qq.com/s/zbvUzoa1K7AIQK-p3v-WQQ)
66 | 60. [Go 语言怎么使用类型转换和类型断言?](https://mp.weixin.qq.com/s/aMHqASVyAidHOYvUtxCuRg)
67 | 61. [Go 1.21.0 新增 3 个内置函数详解](https://mp.weixin.qq.com/s/b-WXPjUYA4UZp8dMXFr1og)
68 | 62. [Go 1.21.0 新增标准库 slices 和 maps 详解](https://mp.weixin.qq.com/s/hXp2wbZh94o4pVDdkRhUwQ)
69 | 63. [Go 1.21.0 中新增的结构化日志记录标准库 log/slog 详解](https://mp.weixin.qq.com/s/oSwxxQaqI5Z2bTVUqUY54w)
70 | 64. [Go 语言开发的基于指标的监控系统 Prometheus](https://mp.weixin.qq.com/s/ObQAL5OlJbBbncyGYSKAfw)
71 | 65. [Prometheus Go client library 详解](https://mp.weixin.qq.com/s/RFkyPG4qWrr6USjPKTXE4g)
72 | 66. [Prometheus 的查询语言 PromQL 详解](https://mp.weixin.qq.com/s/qAl2e-v3wu8Hk5n9D1pLUQ)
73 | 67. [Go 语言字符串使用方式与技巧](https://mp.weixin.qq.com/s/gL2hDOjuD7subD-MxTQRdQ)
74 | 68. [Go 语言为什么很少使用数组?](https://mp.weixin.qq.com/s/bhR9vTr3n3wthfkbHHD0_A)
75 | 69. [Go 语言为什么建议多使用切片,少使用数组?](https://mp.weixin.qq.com/s/QCf07_UmxBNyIyCMRkONhw)
76 | 70. [Go 语言为什么不支持并发读写 map?](https://mp.weixin.qq.com/s/n6K6tbDRdS5c0hMtmHxdFg)
77 | 71. [Go 语言中 defer 使用时有哪些陷阱?](https://mp.weixin.qq.com/s/g6ohhBBQd0u4PzD1KhnKCA)
78 | 72. [Go 1.22 对 “for” 循环进行了两项更改](https://mp.weixin.qq.com/s/Cj2pAHXRBovbQdcpTCu_bA)
79 | 73. [Go 1.22 对 net/http.ServeMux 多路复用器新增两个增强功能](https://mp.weixin.qq.com/s/7tb2IzjvvsIAsNaReTCd7g)
80 | 74. [Go 1.22 标准库 slices 新增函数和一些旧函数增加新特性](https://mp.weixin.qq.com/s/HPEvCCxLSokywi76-reI6g)
81 | 75. [Go 语言中怎么使用依赖注入?](https://mp.weixin.qq.com/s/R9G9dHMFMYwMiKIiTOetYg)
82 | ***
83 | 
84 |
85 |
86 |
--------------------------------------------------------------------------------
/ebook/1.md:
--------------------------------------------------------------------------------
1 | [目录](https://github.com/weirubo/learn_go)
2 | # 01 命名规则
3 |
4 | Go 中命名规则是,名称以字母或下划线开头,后面可跟任意数量的字符、数字和下划线,字符区分大小写,名称本身没有长度限制,但是 Go 的编程风格倾向于使用短名称,特别是局部变量,Go 中有 25 个关键字,这些关键字不可用来命名。
5 |
6 | Go 语言 25 个关键字:
7 | | break | default | func |interface | select |
8 | | :-----:| :----: | :----: | :----: | :----: |
9 | | case | defer | go |map | struct |
10 | | chan | else | goto |package | switch |
11 | | const | fallthrough | if |range | type |
12 | | continue | for | import |return | var |
13 |
14 | # 02 声明变量
15 |
16 | * 声明变量的通用形式
17 | ```
18 | var name type = expression
19 | ```
20 | 使用 var 关键字,后面跟变量的名称、类型和表达式。
21 | * 声明变量的省略形式
22 | ```
23 | var totalScore int
24 | var totalScore2 = 678
25 | ```
26 | 省略形式声明变量,类型和表达式可以省略其一,但是不能都省略。省略表达式,它的初始值是类型的零值,省略类型,它的初始化表达式决定变量的类型。
27 | * 声明变量列表
28 | ```
29 | var a, b, c int
30 | var d, e, f int = 1, 2, 3
31 | var g, h, i = 3.14, "hello", true
32 | ```
33 | 声明变量列表,省略类型,以初始化表达式决定变量的类型,允许声明多个不同类型的变量。
34 | * 调用有返回值函数的形式声明变量
35 | ```
36 | var myname = name("lucy")
37 | func name(name string) string {
38 | var str string = "My name is " + name
39 | return str
40 | }
41 | ```
42 |
43 | # 03 声明短变量
44 |
45 | 在函数中,短变量声明用来声明和初始化局部变量。
46 |
47 | 声明一个整数类型的局部变量:
48 | ```
49 | totalScore := 123
50 | ```
51 | 声明一个短变量列表:
52 | ```
53 | x, y := 1, 2
54 | ```
55 | 注意:短变量声明,左侧必须至少声明一个新变量。
56 |
57 | # 04 指针
58 |
59 | 指针的值是一个变量的地址。一个指针代表一个变量的值所保存的位置。指针可以在不知道变量名的情况下,读取和更新变量的值。
60 | ```
61 | var x int
62 | ```
63 | 声明一个整型的变量 x,&x 获取一个指向变量 x 的指针,它的类型是整型的指针类型(*int)
64 | ```
65 | z := 3
66 | p := &z
67 | fmt.Printf("z=%d\n", z)
68 | fmt.Printf("p=%p\n", p)
69 | *p = 4
70 | fmt.Printf("z=%d\n", z)
71 | fmt.Printf("p=%p\n", p)
72 | ```
73 | p 是指向 z 的指针,是 z 的地址,它的类型是整型的指针类型(*int),*p 是变量 z 的值,是变量 z 的别名,可以读取和更新变量 z。
74 |
75 | 指针类型的零值是 nil,指针是可比较的,两个指针只有指向同一个变量,或者都是 nil 的情况下才相等。
76 |
77 | ***
78 | [Go语言基础知识](https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzA4Mjc1NTMyOQ==&action=getalbum&album_id=1439829562619445249&subscene=0&scenenote=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzA4Mjc1NTMyOQ%3D%3D%26mid%3D2247483736%26idx%3D1%26sn%3Dffb28bc5f79c93b04ce139ca)
--------------------------------------------------------------------------------
/ebook/2.md:
--------------------------------------------------------------------------------
1 | [目录](https://github.com/weirubo/learn_go)
2 | # 01 整数类型
3 | 整数类型按照有/无符号划分,可分为有符号整数和无符号整数,二者按照大小划分,有 8 位、16 位、32 位和 64 位:
4 | | 大小 | 8 位 | 16 位 |32 位 | 64 位 |
5 | | :-----:| :----: | :----: |:----: | :----: |
6 | | 有符号 | int8 | int16 |int32 | int64 |
7 | | 无符号 | uint8 | uint16 |uint32 | uint64 |
8 |
9 | 此外,还有两种整数类型,分别是 int 和 uint,其大小与原生的有/无符号整数类型相同,都是 32 位或 64 位。
10 |
11 | 其中,int32 和 uint8 分别有类型别名是 rune 和 byte,二者可互换使用。需要注意的是,int 和 uint 都有别于大小明确的类型,也就是说,int 和 int32 是两种不同的类型,必须显示转换。
12 |
13 | ```
14 | var a int
15 | var b int32
16 | var c rune
17 | var d byte
18 | var e uint8
19 |
20 | func main() {
21 | fmt.Printf("a=%d type:%T\n", a, a)
22 | fmt.Printf("b=%d type:%T\n", b, b)
23 | fmt.Printf("c=%d type:%T\n", c, c)
24 | fmt.Printf("d=%d type:%T\n", d, d)
25 | fmt.Printf("e=%d type:%T\n", e, e)
26 |
27 | if c == b {
28 | fmt.Println("rune 类型是 int32 的类型别名,二者可以互换使用")
29 | }
30 |
31 | if d == e {
32 | fmt.Println("byte 类型是 uint8 的类型别名,二者可以互换使用")
33 | }
34 | }
35 | ```
36 | # 02 浮点数类型
37 | 浮点数类型有两种,分别是 float32 和 float64,大多数情况下,建议优先使用 float64,因为 float32 的运算容易产生误差。
38 |
39 | ```
40 | var f float32
41 | var g float64
42 |
43 | func main() {
44 | fmt.Printf("f=%g type:%T\n", f, f)
45 | fmt.Printf("g=%g type:%T\n", g, g)
46 | }
47 | ```
48 | # 03 布尔类型
49 |
50 | bool 型的值只有两种可能,true 和 false,在 Go 语言中,bool 型的零值是 false,布尔值无法隐式转换成数值 0 或 1,反之亦然。
51 |
52 | ```
53 | var h bool
54 |
55 | func main() {
56 | fmt.Printf("h=%t type:%T\n", h, h)
57 | }
58 | ```
59 | # 04 字符串类型
60 | 字符串是不可变的带双引号的字节序列,它可以包含任意数据,包括 0 值字节,不可变意味着多个字符串可以共享一块内存空间。
61 |
62 |
63 | 
64 | 如图所示,同一块内存空间,包含字符串 s 、字符串 hello 和字符串 world。
65 |
66 |
67 | 字符串操作:
68 | * len 函数
69 |
70 | 内置的 len 函数返回字符串的字节数,并非字符的个数,UTF-8 的简体中文,一个字符占三个字节。
71 | * 下标访问字符
72 |
73 | 通过下标访问字符串,可以得到第 i 个字符。
74 | * 子串生成
75 |
76 | 子串生成操作 s[i:j] 产生一个新字符串,内容取自原字符串的字节,下标从 i (含边界值)开始,直到 j(不含边界值)。新字符串的大小是 j-i 个字节。
77 |
78 | 需要注意的是,如果下标越界,或者 j 的值小于 i,将触发宕机异常。
79 |
80 | 操作数 i 和 j 的默认值分别是 0 [字符串的起始位置]和 len(s) [字符串的终止位置],如果省略 i 或 j,或两者都省略,则取默认值。
81 | * 字符串连接
82 |
83 | 加号(+)运算符连接两个字符串而生成一个新字符串。
84 |
85 | ```
86 | var i string
87 |
88 | func main() {
89 | fmt.Printf("i=%s type:%T\n", i, i)
90 |
91 | i = "hello golang"
92 | fmt.Printf("字符串 i 的长度:%d\n", len(i))
93 | fmt.Printf("字符串 i 的第一个字符:%c\n", i[0])
94 | j := i[0:5]
95 | fmt.Printf("子字符串 j 的值:%s\n", j)
96 | k := i[5:]
97 | fmt.Printf("子字符串 k 的值:%s\n", k)
98 | l := i[:5]
99 | fmt.Printf("子字符串 l 的值:%s\n", l)
100 | m := i[:]
101 | fmt.Printf("子字符串 m 的值:%s\n", m)
102 | n := "hello "
103 | o := "world"
104 | p := n + o
105 | fmt.Printf("连接字符串 p 的值:%s\n", p)
106 | }
107 | ```
108 | ***
109 | [Go语言基础知识](https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzA4Mjc1NTMyOQ==&action=getalbum&album_id=1439829562619445249&subscene=0&scenenote=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzA4Mjc1NTMyOQ%3D%3D%26mid%3D2247483736%26idx%3D1%26sn%3Dffb28bc5f79c93b04ce139ca)
--------------------------------------------------------------------------------
/ebook/3.md:
--------------------------------------------------------------------------------
1 | [目录](https://github.com/weirubo/learn_go)
2 | # 01 概念
3 | 常量是一种表达式,常量的计算可以在编译时完成,如果有错误,在编译时就会报错,常量的值不可以修改。
4 | # 02 声明常量
5 | 常量声明可以同时指定类型和值,如果没有显示指定类型,则类型根据右边的表达式推断。需要特别注意的是,声明常量不同于声明变量可以不赋值,声明常量必须赋值。
6 | ```
7 | const name string = "golang"
8 | const PI = 3.14
9 |
10 | func main() {
11 | fmt.Printf("name = %s type:%T\n", name, name)
12 | fmt.Printf("PI = %g type:%T\n", PI, PI)
13 | }
14 | ```
15 | 声明一组常量,每个常量类型可以不同。
16 | ```
17 | const (
18 | x = 1
19 | y = "hello"
20 | z = true
21 | )
22 |
23 | func main() {
24 | fmt.Printf("x = %d type:%T\n", x, x)
25 | fmt.Printf("y = %s type:%T\n", y, y)
26 | fmt.Printf("z = %t type:%T\n", z, z)
27 | }
28 | ```
29 | 声明一组常量,除了第一个常量之外,其他常量都可以省略表达式,其他常量会复用其前面一个常量的类型和表达式。
30 | ```
31 | const (
32 | a = 1
33 | b
34 | c = 2
35 | d
36 | )
37 |
38 | func main() {
39 | fmt.Printf("a = %d type:%T\n", a, a)
40 | fmt.Printf("b = %d type:%T\n", b, b)
41 | fmt.Printf("c = %d type:%T\n", c, c)
42 | fmt.Printf("d = %d type:%T\n", d, d)
43 | }
44 | ```
45 | # 03 常量生成器 iota
46 | 声明一组常量,可以使用常量生成器 iota,它可以不用逐个常量显示指定类型和赋值表达式,常量声明中,iota 从 0 开始取值,后续常量如果没有显示指定类型和赋值表达式,其值是其前面一个常量的值加 1。直到遇到赋值常量停止加 1,后续如果再遇到赋值 iota 的常量,则继续逐个加 1。
47 | ```
48 | const (
49 | Sunday int = iota
50 | Monday
51 | Tuesday
52 | Wednesday
53 | Thursday
54 | Friday
55 | Saturday
56 | )
57 |
58 | const (
59 | aa int = iota
60 | bb
61 | cc
62 | dd = 10
63 | ee
64 | ff = iota
65 | gg
66 | hh
67 | )
68 |
69 | func main() {
70 | fmt.Printf("Sunday = %d type:%T\n", Sunday, Sunday)
71 | fmt.Printf("Monday = %d type:%T\n", Monday, Monday)
72 | fmt.Printf("Tuesday = %d type:%T\n", Tuesday, Tuesday)
73 | fmt.Printf("Wednesday = %d type:%T\n", Wednesday, Wednesday)
74 | fmt.Printf("Thursday = %d type:%T\n", Thursday, Tuesday)
75 | fmt.Printf("Friday = %d type:%T\n", Friday, Friday)
76 | fmt.Printf("Saturday = %d type:%T\n", Saturday, Saturday)
77 | fmt.Printf("aa = %d type:%T\n", aa, aa)
78 | fmt.Printf("bb = %d type:%T\n", bb, bb)
79 | fmt.Printf("cc = %d type:%T\n", cc, cc)
80 | fmt.Printf("dd = %d type:%T\n", dd, dd)
81 | fmt.Printf("ee = %d type:%T\n", ee, ee)
82 | fmt.Printf("ff= %d type:%T\n", ff, ff)
83 | fmt.Printf("gg = %d type:%T\n", gg, gg)
84 | fmt.Printf("hh = %d type:%T\n", hh, hh)
85 | }
86 | ```
87 | # 04 无类型常量
88 | 无类型常量,可以直接赋值给其他常量,显示指定类型的常量,赋值给其他常量时,会做强类型检查。
89 | ```
90 | const username, age = "lucy", 17
91 | const user = username
92 |
93 | func main() {
94 | fmt.Printf("username = %s, age = %d\n", username, age)
95 | fmt.Printf("user = %s\n", user)
96 | }
97 | ```
98 | ***
99 | [Go语言基础知识](https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzA4Mjc1NTMyOQ==&action=getalbum&album_id=1439829562619445249&subscene=0&scenenote=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzA4Mjc1NTMyOQ%3D%3D%26mid%3D2247483736%26idx%3D1%26sn%3Dffb28bc5f79c93b04ce139ca)
--------------------------------------------------------------------------------
/ebook/4.md:
--------------------------------------------------------------------------------
1 | [目录](https://github.com/weirubo/learn_go)
2 | # 01 算术运算符
3 | 算术运算符有加号(+)、减号(-)、乘号(*)、除号(/)、取余(%),我们声明两个变量 a 和 b,并分别赋值 10 和 5,通过代码,我们演示算术运算符的用法。
4 | ```
5 | func main() {
6 | a := 10
7 | b := 5
8 | fmt.Println("a + b = ", a+b)
9 | fmt.Println("a - b = ", a-b)
10 | fmt.Println("a * b = ", a*b)
11 | fmt.Println("a / b = ", a/b)
12 | fmt.Println("a % b = ", a%b)
13 | }
14 | ```
15 | # 02 ++ 和 --
16 | 自增和自减不是运算符,只能作为独立语句使用,不能用于表达式,不能放在变量名前面使用。通过代码,我们演示 ++ 和 -- 的用法。
17 | ```
18 | func main() {
19 | a := 10
20 | b := 5
21 | a++
22 | b--
23 | fmt.Println("a++:", a)
24 | fmt.Println("b--:", b)
25 | }
26 | ```
27 | # 03 赋值运算符
28 | 为了简化表达式,与大多数语言相同,Go 语言也提供了一些赋值运算符,有等号(=)、加等(+=)、减等(-=)、乘等(*=)、除等(/*)、取余等(%=),通过代码,我们演示赋值运算符的用法。
29 | ```
30 | func main() {
31 | aa := 50
32 | aa += 10
33 | fmt.Println("aa = ", aa)
34 |
35 | bb := 50
36 | bb -= 10
37 | fmt.Println("bb = ", bb)
38 |
39 | cc := 50
40 | cc *= 10
41 | fmt.Println("cc = ", cc)
42 |
43 | dd := 50
44 | dd /= 10
45 | fmt.Println("dd = ", dd)
46 |
47 | ff := 50
48 | ff %= 10
49 | fmt.Println("ff = ", ff)
50 | }
51 | ```
52 | # 04 关系运算符
53 | 关系运算符主要用于流程控制语句中,在 Go 语言中,关系运算符有大于(>)、小于(<)、大于等于(>=)、小于等于(<=)、等于等于(==)和不等于(!=),通过代码,我们演示关系运算符的用法。
54 | ```
55 | func main() {
56 | if a > 5 && b > 5 {
57 | fmt.Println("a > 5 且 b > 5")
58 | }
59 |
60 | if a > 5 || b > 5 {
61 | fmt.Println("a > 5 或 b > 5")
62 | }
63 |
64 | if a > 5 && b >= 5 {
65 | fmt.Println("a > 5 且 b >= 5")
66 | }
67 |
68 | if a == b {
69 | fmt.Println("a == b")
70 | }
71 |
72 | if a != b {
73 | fmt.Println("a != b")
74 | }
75 |
76 | boolean := false
77 | if !boolean {
78 | fmt.Println("非假既真")
79 | }
80 | }
81 | ```
82 | # 05 逻辑运算符
83 | 逻辑运算符,同样主要用于流程控制语句中,在 Go 语言中,逻辑运算符有且(&&)、或(||)、非(!),代码演示同上面的关系运算符代码。
84 |
85 | # 06 & 和 *
86 | 取地址符(&)和指针运算符(*),不是所有对象都能进行取地址操作,但是变量总是能正确返回地址。指针运算符在等号左边时,可以更新目标对象,在等号右边时,可以获取目标对象。通过代码,我们演示取地址符和指针运算符的用法。
87 | ```
88 | func main() {
89 | x := 50
90 | y := &x
91 | *y++
92 | z := *y
93 | fmt.Println("y = ", y)
94 | fmt.Println("x = ", x)
95 | fmt.Println("z = ", z)
96 | }
97 | ```
98 | # 07 位运算符
99 | 位运算符是对整数在内存中的二进制位进行操作。因为篇幅原因,本文我们不对位运算符做过多的介绍,在工作中,个人建议尽量少用或不用位运算符,原因是代码可读性不好。如果你对位运算符感兴趣,可自行查阅相关资料。
100 |
101 | # 08 优先级
102 | 最后,我们来介绍一下运算符的优先级,一元运算符的优先级最高,二元运算符的优先级分五个级别,从高往低分别是:
103 |
104 | | * | / | % |<< | >> | & |&^ |
105 | | :-----:| :----: | :----: |-----:| :----: | :----: |:----: |
106 | | + | - | \| |^ | | | |
107 | | == | != | <= |< | > | >= | |
108 | | && | | | | | | |
109 | | \|\| | | | | | | |
110 |
111 | 相同优先级的二元运算符,从左往右依次计算。此外,我们还可以使用小括号提升某个表达式中运算符的优先级。
112 |
113 | ***
114 | [Go语言基础知识](https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzA4Mjc1NTMyOQ==&action=getalbum&album_id=1439829562619445249&subscene=0&scenenote=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzA4Mjc1NTMyOQ%3D%3D%26mid%3D2247483736%26idx%3D1%26sn%3Dffb28bc5f79c93b04ce139ca)
--------------------------------------------------------------------------------
/ebook/5.md:
--------------------------------------------------------------------------------
1 | [目录](https://github.com/weirubo/learn_go)
2 | # 01 if...else... 标准使用
3 | 在 Go 语言中,if...else... 语句的条件表达式必须是布尔类型,可以省略小括号,并且左大括号不能另起一行。通过代码,我们演示 if...else... 的标准使用方法。
4 | ```
5 | func main() {
6 | x := 1
7 | if x >= 5 {
8 | fmt.Println("x >= 5")
9 | } else if x < 5 && x > 0 {
10 | fmt.Println("x < 5 && x > 0")
11 | } else {
12 | fmt.Println("x <= 0")
13 | }
14 | }
15 | ```
16 | # 02 if...else... 特殊使用
17 | if...else... 语句区别于其它语言,它在条件表达式中,支持初始化语句,可以定义局部变量(一个或多个)或执行初始化函数。其中,局部变量的有效范围包含整个 if...else... 块。通过代码,我们演示 if...else... 在条件表达式中初始化语句的使用方法。
18 | ```
19 | func main() {
20 | if a, b := x+1, x+10; a < b {
21 | fmt.Println("a < b")
22 | } else {
23 | fmt.Println("a >= b")
24 | }
25 | }
26 | ```
27 | if...else... 语句需要注意的是,条件的匹配顺序要想好,避免出现死代码,即永远不会执行的代码;尽量减少代码块嵌套,保持代码块功能的单一性,让正常逻辑处于相同层次,针对复杂的组合条件,可以将其封装为函数,提升代码的可维护性。
28 | # 03 switch 标准使用
29 | switch 语句和 if 语句类似,也用于选择执行,在 Go 语言中,switch 语句不同于其他语言中的 switch 语句,匹配到 case 块后,不需要显式执行 break 语句,程序自动不会继续执行下个 case 块,如果需要程序继续执行匹配 case 块的下一个 case 块,可以在 case 块的结尾执行 fallthrough,但是不会再匹配 case 块的条件表达式。如果想要阻止 fallthrough,可以显式执行 break 语句。在一个 case 块存在多个匹配条件时,命中其中一个条件即可,类似逻辑运算符“或”,通过代码,我们演示 switch 在 Go 语言中的使用方法。
30 | ```
31 | func main() {
32 | a, b, c, x := 2, 3, 4, 2
33 | switch x {
34 | case a, b:
35 | println("x == a || x == b")
36 | fallthrough
37 | case c:
38 | println("x == c")
39 | case 3:
40 | println("x == 3")
41 | default:
42 | println("x 不符合任何 case 条件")
43 | }
44 | }
45 | ```
46 | # 04 switch 特殊使用
47 | switch 语句同 if 语句类似,同样支持初始化语句,按从上到下,从左到有的顺序匹配 case 执行,只有全部 case 块匹配失败时,才会执行 default 块。通过代码,我们演示 switch 语句特殊使用方法。
48 | ```
49 | func main() {
50 | switch y := 5; {
51 | case y > 5:
52 | fmt.Println("y > 5")
53 | case y > 0 && y <= 5:
54 | println("y > 0 && y <= 5")
55 | default:
56 | println("y = ", y)
57 | }
58 | }
59 | ```
60 | 关于 Switch 语句,在 Go 语言中还有两点需要注意的,一是相邻的空 case 不构成多条件匹配,二是不能出现重复的 case 常量值。
61 | # 05 for 标准使用
62 | 在 Go 语言中,仅有 for 一种循环语句,但是可以模拟 while (condition) {} 和 while (true) {},需要注意的是,初始化语句仅被执行一次。通过代码,我们演示在 Go 语言中,for 循环的使用方法。
63 | ```
64 | func main() {
65 | for i := 0; i < 5; i++ {
66 | println("i = ", i)
67 | }
68 | }
69 | ```
70 | # 06 for 模拟 while (condition) {}
71 | ```
72 | func main() {
73 | j := 0
74 | for j < 5 {
75 | j++
76 | fmt.Println("j = ", j)
77 | }
78 | }
79 | ```
80 | # 07 for 模拟 while (true) {}
81 | ```
82 | func main() {
83 | for {
84 | k++
85 | if k == 2 {
86 | continue
87 | }
88 | if k > 5 {
89 | break
90 | }
91 | fmt.Println("k = ", k)
92 | }
93 | }
94 | ```
95 | # 08 for range遍历
96 | 在 Go 语言中,遍历数据除了使用 for 标准使用形式之外,还可以使用 for...range 遍历数据,支持的数据类型有字符串、数组、数组指针、slice、map、channel,返回索引、键值数据。目前为止,上述类型中,我们仅介绍过字符串类型,关于其他几种类型,我们后续再介绍。通过代码,我们演示使用 for...range 遍历字符串返回 unicode 的用法。
97 | ```
98 | func main() {
99 | str := "hello"
100 | for index := range str {
101 | fmt.Println(str[index])
102 | }
103 | }
104 | ```
105 | # 09 continue 和 break
106 | 在 for 循环中,continue 和 break 分别可以用来跳出本次循环和结束循环,其中,continue 只用于 for 循环,而 break 还可以用于 03 介绍的 switch 语句中,和后续我们会介绍的 select 语句。continue 和 break 的使用方法,同第 07 的 for 语句模拟 while(true) 代码演示。
107 | # 10 goto
108 | 在 Go 语言中,使用 goto 实现定点跳转,虽然行业中对于 goto 的褒贬不一,但实际上,有些场景使用 goto,可以让代码更优雅。使用 goto 前,我们需要先定义标签,标签区分大小写,并且如果未使用定义的标签会引发编译错误。需要注意的是,goto 不能跳转到其他函数或内层代码块中。通过代码,我们演示 goto 的用法。
109 | ```
110 | func main() {
111 | l := 0
112 | for l < 10 {
113 | start:
114 | l++
115 | if l < 5 {
116 | goto start
117 | }
118 | fmt.Println("l = ", l)
119 | }
120 | }
121 | ```
122 | ***
123 | [Go语言基础知识](https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzA4Mjc1NTMyOQ==&action=getalbum&album_id=1439829562619445249&subscene=0&scenenote=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzA4Mjc1NTMyOQ%3D%3D%26mid%3D2247483736%26idx%3D1%26sn%3Dffb28bc5f79c93b04ce139ca)
--------------------------------------------------------------------------------
/ebook/640.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weirubo/learn_go/22a2ade9f18c9205cb088b4415228f4c4864fc7d/ebook/640.png
--------------------------------------------------------------------------------
/ebook/qrcode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weirubo/learn_go/22a2ade9f18c9205cb088b4415228f4c4864fc7d/ebook/qrcode.png
--------------------------------------------------------------------------------
/lesson01/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | // 变量
4 |
5 | import "fmt"
6 |
7 | // 定义变量
8 | var totalScore int = 678
9 | var totalScore2 int
10 | var totalScore3 = 345
11 | var a, b, c int
12 | var d, e, f int = 1, 2, 3
13 | var g, h, i = 3.14, "hello", true
14 | var myname = name("lucy")
15 |
16 | func main() {
17 | fmt.Printf("totalScore=%d\n", totalScore)
18 | fmt.Printf("totalScore2=%d\n", totalScore2)
19 | fmt.Printf("totalScore3=%d\n", totalScore3)
20 |
21 | fmt.Printf("a=%d b=%d c=%d\n", a, b, c)
22 | fmt.Printf("d=%d e=%d f=%d\n", d, e, f)
23 | fmt.Printf("g=%g h=%s i=%t\n", g, h, i)
24 |
25 | fmt.Println(myname)
26 |
27 | totalScore4 := 123
28 | fmt.Printf("totalScore4=%d\n", totalScore4)
29 |
30 | x, y := 1, 2
31 | fmt.Printf("x=%d y=%d\n", x, y)
32 |
33 | z := 3
34 | p := &z
35 | fmt.Printf("z=%d\n", z)
36 | fmt.Printf("p=%p\n", p)
37 | *p = 4
38 | fmt.Printf("z=%d\n", z)
39 | fmt.Printf("p=%p\n", p)
40 |
41 | abc := 1
42 | a1 := &abc
43 | a2 := &abc
44 | if a1 == a2 {
45 | fmt.Println("a1 和 a2 相等,a1 和 a2 指向同一变量")
46 | }
47 |
48 | aa := 2
49 | bb := 2
50 | aa1 := &aa
51 | aa2 := &bb
52 | if aa1 == aa2 {
53 | fmt.Println("aa1 和 aa2 相等")
54 | } else {
55 | fmt.Println("aa1 和 aa2 不相等")
56 | }
57 | }
58 |
59 | func name(name string) string {
60 | var str string = "My name is " + name
61 | return str
62 | }
63 |
--------------------------------------------------------------------------------
/lesson02/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | // 基础数据类型
4 |
5 | import "fmt"
6 |
7 | var a int
8 | var b int32
9 | var c rune
10 | var d byte
11 | var e uint8
12 | var f float32
13 | var g float64
14 | var h bool
15 | var i string
16 |
17 | func main() {
18 | fmt.Printf("a=%d type:%T\n", a, a)
19 | fmt.Printf("b=%d type:%T\n", b, b)
20 | fmt.Printf("c=%d type:%T\n", c, c)
21 | fmt.Printf("d=%d type:%T\n", d, d)
22 | fmt.Printf("e=%d type:%T\n", e, e)
23 | fmt.Printf("f=%g type:%T\n", f, f)
24 | fmt.Printf("g=%g type:%T\n", g, g)
25 | fmt.Printf("h=%t type:%T\n", h, h)
26 | fmt.Printf("i=%s type:%T\n", i, i)
27 |
28 | if c == b {
29 | fmt.Println("rune 类型是 int32 的类型别名,二者可以互换使用")
30 | }
31 |
32 | if d == e {
33 | fmt.Println("byte 类型是 uint8 的类型别名,二者可以互换使用")
34 | }
35 |
36 | i = "hello golang"
37 | fmt.Printf("字符串 i 的长度:%d\n", len(i))
38 | fmt.Printf("字符串 i 的第一个字符:%c\n", i[0])
39 | j := i[0:5]
40 | fmt.Printf("子字符串 j 的值:%s\n", j)
41 | k := i[5:]
42 | fmt.Printf("子字符串 k 的值:%s\n", k)
43 | l := i[:5]
44 | fmt.Printf("子字符串 l 的值:%s\n", l)
45 | m := i[:]
46 | fmt.Printf("子字符串 m 的值:%s\n", m)
47 | n := "hello "
48 | o := "world"
49 | p := n + o
50 | fmt.Printf("连接字符串 p 的值:%s\n", p)
51 | }
52 |
--------------------------------------------------------------------------------
/lesson03/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | // 常量
4 |
5 | import "fmt"
6 |
7 | const name string = "golang"
8 |
9 | // PI π
10 | const PI = 3.14
11 |
12 | const (
13 | x = 1
14 | y = "hello"
15 | z = true
16 | )
17 |
18 | const (
19 | a = 1
20 | b
21 | c = 2
22 | d
23 | )
24 |
25 | // Weekday
26 | const (
27 | Sunday int = iota
28 | Monday
29 | Tuesday
30 | Wednesday
31 | Thursday
32 | Friday
33 | Saturday
34 | )
35 |
36 | const (
37 | aa int = iota
38 | bb
39 | cc
40 | dd = 10
41 | ee
42 | ff = iota
43 | gg
44 | hh
45 | )
46 |
47 | const username, age = "lucy", 17
48 | const user = username
49 |
50 | func main() {
51 | fmt.Printf("name = %s type:%T\n", name, name)
52 | fmt.Printf("PI = %g type:%T\n", PI, PI)
53 | fmt.Printf("x = %d type:%T\n", x, x)
54 | fmt.Printf("y = %s type:%T\n", y, y)
55 | fmt.Printf("z = %t type:%T\n", z, z)
56 | fmt.Printf("a = %d type:%T\n", a, a)
57 | fmt.Printf("b = %d type:%T\n", b, b)
58 | fmt.Printf("c = %d type:%T\n", c, c)
59 | fmt.Printf("d = %d type:%T\n", d, d)
60 | fmt.Printf("Sunday = %d type:%T\n", Sunday, Sunday)
61 | fmt.Printf("Monday = %d type:%T\n", Monday, Monday)
62 | fmt.Printf("Tuesday = %d type:%T\n", Tuesday, Tuesday)
63 | fmt.Printf("Wednesday = %d type:%T\n", Wednesday, Wednesday)
64 | fmt.Printf("Thursday = %d type:%T\n", Thursday, Tuesday)
65 | fmt.Printf("Friday = %d type:%T\n", Friday, Friday)
66 | fmt.Printf("Saturday = %d type:%T\n", Saturday, Saturday)
67 | fmt.Printf("aa = %d type:%T\n", aa, aa)
68 | fmt.Printf("bb = %d type:%T\n", bb, bb)
69 | fmt.Printf("cc = %d type:%T\n", cc, cc)
70 | fmt.Printf("dd = %d type:%T\n", dd, dd)
71 | fmt.Printf("ee = %d type:%T\n", ee, ee)
72 | fmt.Printf("ff= %d type:%T\n", ff, ff)
73 | fmt.Printf("gg = %d type:%T\n", gg, gg)
74 | fmt.Printf("hh = %d type:%T\n", hh, hh)
75 | fmt.Printf("username = %s, age = %d\n", username, age)
76 | fmt.Printf("user = %s\n", user)
77 | }
78 |
--------------------------------------------------------------------------------
/lesson04/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | // 运算符
4 |
5 | import "fmt"
6 |
7 | // + - * / %
8 |
9 | // ++ --
10 |
11 | // = += -= *= /= %=
12 |
13 | // > >= < <= == !=
14 |
15 | // && || !
16 |
17 | // & *
18 |
19 | func main() {
20 | a := 10
21 | b := 5
22 | fmt.Println("a + b = ", a+b)
23 | fmt.Println("a - b = ", a-b)
24 | fmt.Println("a * b = ", a*b)
25 | fmt.Println("a / b = ", a/b)
26 | fmt.Println("a % b = ", a%b)
27 |
28 | a++
29 | b--
30 | fmt.Println("a++:", a)
31 | fmt.Println("b--:", b)
32 |
33 | aa := 50
34 | aa += 10
35 | fmt.Println("aa = ", aa)
36 |
37 | bb := 50
38 | bb -= 10
39 | fmt.Println("bb = ", bb)
40 |
41 | cc := 50
42 | cc *= 10
43 | fmt.Println("cc = ", cc)
44 |
45 | dd := 50
46 | dd /= 10
47 | fmt.Println("dd = ", dd)
48 |
49 | ff := 50
50 | ff %= 10
51 | fmt.Println("ff = ", ff)
52 |
53 | if a > 5 && b > 5 {
54 | fmt.Println("a > 5 且 b > 5")
55 | }
56 |
57 | if a > 5 || b > 5 {
58 | fmt.Println("a > 5 或 b > 5")
59 | }
60 |
61 | if a > 5 && b >= 5 {
62 | fmt.Println("a > 5 且 b >= 5")
63 | }
64 |
65 | if a == b {
66 | fmt.Println("a == b")
67 | }
68 |
69 | if a != b {
70 | fmt.Println("a != b")
71 | }
72 |
73 | boolean := false
74 | if !boolean {
75 | fmt.Println("非假既真")
76 | }
77 |
78 | x := 50
79 | y := &x
80 | *y++
81 | z := *y
82 | fmt.Println("y = ", y)
83 | fmt.Println("x = ", x)
84 | fmt.Println("z = ", z)
85 | }
86 |
--------------------------------------------------------------------------------
/lesson05/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | // 流程控制
4 |
5 | import "fmt"
6 |
7 | func main() {
8 | x := 1
9 | if x >= 5 {
10 | fmt.Println("x >= 5")
11 | } else if x < 5 && x > 0 {
12 | fmt.Println("x < 5 && x > 0")
13 | } else {
14 | fmt.Println("x <= 0")
15 | }
16 |
17 | if a, b := x+1, x+10; a < b {
18 | fmt.Println("a < b")
19 | } else {
20 | fmt.Println("a >= b")
21 | }
22 |
23 | a, b, c, x := 2, 3, 4, 2
24 | switch x {
25 | case a, b:
26 | println("x == a || x == b")
27 | fallthrough
28 | case c:
29 | println("x == c")
30 | case 3:
31 | println("x == 3")
32 | default:
33 | println("x 不符合任何 case 条件")
34 | }
35 |
36 | switch y := 5; {
37 | case y > 5:
38 | fmt.Println("y > 5")
39 | case y > 0 && y <= 5:
40 | println("y > 0 && y <= 5")
41 | default:
42 | println("y = ", y)
43 | }
44 |
45 | for i := 0; i < 5; i++ {
46 | println("i = ", i)
47 | }
48 |
49 | j := 0
50 | for j < 5 {
51 | j++
52 | fmt.Println("j = ", j)
53 | }
54 |
55 | k := 0
56 | for {
57 | k++
58 | if k == 2 {
59 | continue
60 | }
61 | if k > 5 {
62 | break
63 | }
64 | fmt.Println("k = ", k)
65 | }
66 |
67 | str := "hello"
68 | for index := range str {
69 | fmt.Println(str[index])
70 | }
71 |
72 | l := 0
73 | for l < 10 {
74 | start:
75 | l++
76 | if l < 5 {
77 | goto start
78 | }
79 | fmt.Println("l = ", l)
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/lesson06/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | // 数组
4 |
5 | import "fmt"
6 |
7 | func main() {
8 | var arr [3]int
9 | fmt.Println("arr 数组的第一个元素是:", arr[0])
10 | fmt.Println("arr:", arr)
11 |
12 | var arr2 = [4]int{1, 2, 3, 4}
13 | fmt.Println("arr2:", arr2)
14 |
15 | var arr3 = [...]int{1, 2, 3, 4, 5}
16 | fmt.Println("arr3 的长度:", len(arr3))
17 |
18 | const (
19 | name int = iota
20 | email
21 | )
22 | var arr4 = [...]string{name: "lucy", email: "lucy@gmail.com"}
23 | fmt.Println(name, arr4[name])
24 | fmt.Println("arr4:", arr4[0])
25 |
26 | var arr5 = [...]int{99: 100}
27 | fmt.Println(arr5[0], arr5[1], arr5[99])
28 |
29 | var arrS = [2][3]int{{1, 2, 3}, {10, 20, 30}}
30 | fmt.Println("二维数组 arrS:", arrS)
31 |
32 | var arrS2 = [...][2][3]int{
33 | {
34 | {1, 2, 3},
35 | {4, 5, 6},
36 | },
37 | {
38 | {11, 12, 13},
39 | {14, 15, 16},
40 | },
41 | }
42 | fmt.Println("arrS2:", arrS2)
43 |
44 | var arr6 = [5]int{1, 2, 3, 4, 5}
45 | var arr7 = [...]int{1, 2, 3, 4, 5}
46 | var arr8 = [5]int{2, 3, 4, 5, 6}
47 | if arr6 == arr7 {
48 | fmt.Println("arr6 与 arr7 相等")
49 | } else if arr6 == arr8 {
50 | fmt.Println("arr6 与 arr8 相等")
51 | }
52 |
53 | for index, value := range arr6 {
54 | fmt.Printf("arr6[%d]=%d\n", index, value)
55 | }
56 |
57 | for _, value := range arr6 {
58 | fmt.Println("arr6=", value)
59 | }
60 |
61 | x, y := 1, 2
62 | a := [2]*int{&x, &y}
63 | p := &a
64 | fmt.Println("数组的元素为指针类型的指针数组:", a)
65 | fmt.Println("存储数组的内存地址的数组指针:", p)
66 |
67 | var arr9 = [3]int{1, 2, 3}
68 | var arr10 [3]int
69 | arr10 = arr9
70 | fmt.Println("arr9:", arr9)
71 | fmt.Println("arr10:", arr10)
72 | arr9[0] = 10
73 | fmt.Println("arr9:", arr9)
74 | fmt.Println("arr10:", arr10)
75 | }
76 |
--------------------------------------------------------------------------------
/lesson07/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | // slice
6 |
7 | func main() {
8 | arr := [...]int{10, 11, 12, 13, 14}
9 | slice := arr[1:4]
10 | fmt.Printf("slice 的长度:%d,slice 的容量:%d\n", len(slice), cap(slice))
11 | fmt.Println("slice = ", slice)
12 | fmt.Printf("slice 的内存地址:%p\n", slice)
13 | fmt.Printf("arr[1] 的内存地址:%p\n", slice)
14 |
15 | s1 := make([]int, 2, 4)
16 | fmt.Printf("s1 的长度:%d,容量:%d\n", len(s1), cap(s1))
17 | s2 := make([]int, 2)
18 | fmt.Printf("s2 的长度:%d,容量:%d\n", len(s2), cap(s2))
19 |
20 | s3 := []int{0, 1, 2, 3}
21 | fmt.Printf("s3 的长度:%d,容量:%d\n", len(s3), cap(s3))
22 | s4 := []int{9: 9}
23 | fmt.Printf("s4 的长度:%d,容量:%d\n", len(s4), cap(s4))
24 |
25 | var sliceNil []int
26 | fmt.Printf("sliceNil 的长度:%d,容量:%d,类型:%T\n", len(sliceNil), cap(sliceNil), sliceNil)
27 | fmt.Println("sliceNil = ", sliceNil)
28 |
29 | s5 := make([]int, 0)
30 | fmt.Printf("s5 的长度:%d,容量:%d\n", len(s5), cap(s5))
31 |
32 | s6 := []int{}
33 | fmt.Printf("s6 的长度:%d,容量:%d\n", len(s6), cap(s6))
34 |
35 | s7 := []int{10, 11, 12, 13, 14, 15, 16, 17, 18, 19}
36 | s8 := s7[1:3]
37 | fmt.Printf("s7 的长度:%d,容量:%d\n", len(s7), cap(s7))
38 | fmt.Printf("s8 的长度:%d,容量:%d\n", len(s8), cap(s8))
39 | s8[0] = 21
40 | fmt.Println("s8 = ", s8)
41 | fmt.Println("s7 = ", s7)
42 |
43 | s9 := [][]int{{1, 2, 3}, {11, 12, 13, 14}}
44 | fmt.Printf("s9 的长度:%d,容量:%d\n", len(s9), cap(s9))
45 | fmt.Printf("s9[0] 的长度:%d,容量:%d\n", len(s9[0]), cap(s9[0]))
46 | fmt.Printf("s9[1] 的长度:%d,容量:%d\n", len(s9[1]), cap(s9[1]))
47 | fmt.Println(s9)
48 |
49 | s10 := []int{0, 1, 2, 3, 4, 5}
50 | for index, value := range s10 {
51 | fmt.Printf("s10[%d] = %d\n", index, value)
52 | }
53 |
54 | s11 := []int{10, 11, 12, 13, 14}
55 | s12 := s11[1:3]
56 | fmt.Printf("s12 的长度:%d,容量:%d,地址:%p\n", len(s12), cap(s12), s12)
57 | fmt.Println("s12 = ", s12)
58 | s12 = append(s12, 21, 22, 23)
59 | fmt.Printf("s12 的长度:%d,容量:%d,地址:%p\n", len(s12), cap(s12), s12)
60 | fmt.Println("s12 = ", s12)
61 |
62 | s13 := []int{10, 11, 12}
63 | s14 := []int{20, 21, 22}
64 | fmt.Printf("s14 的长度:%d,容量:%d,地址:%p\n", len(s14), cap(s14), s14)
65 | fmt.Println("s14 = ", s14)
66 | s14 = append(s14, s13...)
67 | fmt.Printf("s14 的长度:%d,容量:%d,地址:%p\n", len(s14), cap(s14), s14)
68 | fmt.Println("s14 = ", s14)
69 |
70 | s15 := []int{10, 11, 12, 13, 14, 15, 16, 17, 18, 19}
71 | s16 := s15[4:]
72 | newSlice := copy(s15[:4], s16)
73 | fmt.Printf("newSlice = %d,s15 = %v", newSlice, s15)
74 | }
75 |
--------------------------------------------------------------------------------
/lesson08/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | // map
6 |
7 | func main() {
8 | map1 := make(map[string]int)
9 | fmt.Println("map1 = ", map1)
10 | fmt.Printf("map1 的长度:%d,类型:%T,地址:%p\n", len(map1), map1, map1)
11 |
12 | map2 := map[string]int{}
13 | fmt.Println("map2 = ", map2)
14 | fmt.Printf("map2 的长度:%d,类型:%T,地址:%p\n", len(map2), map2, map2)
15 |
16 | var map3 map[string]int
17 | fmt.Println("map3 = ", map3)
18 | fmt.Printf("map3 的长度:%d,类型:%T,地址:%p\n", len(map3), map1, map3)
19 |
20 | if map1 == nil {
21 | fmt.Println("map1 是 nil")
22 | } else if map2 == nil {
23 | fmt.Println("map2 是 nil")
24 | } else if map3 == nil {
25 | fmt.Println("map3 是 nil")
26 | } else {
27 | fmt.Println("都不是 nil")
28 | }
29 |
30 | map2["One"] = 1
31 | map2["Two"] = 2
32 | map2["Three"] = 3
33 | map2["Four"] = 4
34 | map2["Five"] = 5
35 | fmt.Println("map2 = ", map2)
36 | fmt.Printf("map2 的长度:%d,类型:%T,地址:%p\n", len(map2), map2, map2)
37 | fmt.Println("=====分割线=====")
38 |
39 | if value, ok := map2["Two"]; !ok {
40 | fmt.Println("map2 中不存在键值为 Two 的元素")
41 | } else {
42 | fmt.Printf("value = %d,ok = %T\n", value, ok)
43 | }
44 | fmt.Println("=====分割线=====")
45 |
46 | for key, value := range map2 {
47 | fmt.Printf("第一次遍历:key = %s,value = %d\n", key, value)
48 | }
49 | fmt.Println("=====分割线=====")
50 | for key, value := range map2 {
51 | fmt.Printf("第二次遍历:key = %s,value = %d\n", key, value)
52 | }
53 | fmt.Println("=====分割线=====")
54 |
55 | delete(map2, "Three")
56 | for key, value := range map2 {
57 | fmt.Printf("删除键值为 Three 的 map2遍历:key = %s,value = %d\n", key, value)
58 | }
59 | fmt.Println("=====分割线=====")
60 |
61 | map2["One"] = 11
62 | fmt.Printf("map2 的键值为 One 的元素:%d\n", map2["One"])
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/lesson09/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | // struct
6 |
7 | // Admin sturct
8 | type Admin struct {
9 | person User
10 | level string
11 | }
12 |
13 | // User struct
14 | type User struct {
15 | ID int
16 | Name string
17 | age int
18 | }
19 |
20 | func main() {
21 | var bob User
22 | fmt.Println("bob = ", bob)
23 | lucy := User{
24 | ID: 1,
25 | Name: "lucy",
26 | age: 18,
27 | }
28 | fmt.Println("lucy = ", lucy)
29 |
30 | lily := User{2, "lily", 17}
31 | fmt.Println("lily = ", lily)
32 |
33 | joy := Admin{
34 | person: User{
35 | ID: 10001,
36 | Name: "joy",
37 | age: 28,
38 | },
39 | level: "senior",
40 | }
41 | fmt.Println("joy = ", joy)
42 | }
43 |
--------------------------------------------------------------------------------
/lesson10/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | // func
6 |
7 | func f1(string, string) string {
8 | return ""
9 | }
10 |
11 | func f2(name string, _ string) string {
12 | return name
13 | }
14 |
15 | func f3(name string, job string) string {
16 | return name + job
17 | }
18 |
19 | func f4(name, job string) (info string) {
20 | info = name + job
21 | return
22 | }
23 |
24 | // 声明函数,多返回值
25 |
26 | // 变长函数,形参数量任意
27 | func sum(vals ...int) int {
28 | return 0
29 | }
30 |
31 | // 闭包
32 |
33 | // defer 延迟调用
34 |
35 | // 函数变量(基础数据类型,复合数据类型)
36 |
37 | func main() {
38 | // 匿名函数
39 | func(str string) {
40 | fmt.Println(str)
41 | }("hello, golang")
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/lesson11/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | // 错误处理
4 |
--------------------------------------------------------------------------------
/lesson12/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | // panic recover
6 |
7 | func main() {
8 | defer func() {
9 | if err := recover(); err != nil {
10 | fmt.Println("err = ", err)
11 | }
12 | }()
13 | panic("exit...")
14 | fmt.Println("game over!")
15 |
16 | /* defer func() {
17 | if err := recover(); err != nil {
18 | fmt.Println("err = ", err)
19 | }
20 | }()
21 |
22 | defer func() {
23 | panic("exit2...")
24 | }()
25 |
26 | panic("exit...") */
27 | }
28 |
--------------------------------------------------------------------------------
/lesson13/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | )
6 |
7 | // method
8 |
9 | type user struct {
10 | uid int
11 | uname string
12 | age uint16
13 | }
14 |
15 | func (u user) info() string {
16 | str := fmt.Sprintf("I am %s, My id is %d, and my age is %d.\n", u.uname, u.uid, u.age)
17 | return str
18 | }
19 |
20 | func (u *user) eat() string {
21 | str := fmt.Sprintf("I am %s, I am eating now.\n", u.uname)
22 | return str
23 | }
24 |
25 | func main() {
26 | u := user{
27 | uid: 1,
28 | uname: "lucy",
29 | age: 20,
30 | }
31 | userInfo := u.info()
32 | fmt.Println(userInfo)
33 | fmt.Println(u)
34 |
35 | u1 := &user{
36 | uid: 2,
37 | uname: "lily",
38 | age: 19,
39 | }
40 | eater := u1.eat()
41 | fmt.Println(eater)
42 | fmt.Println(*u1)
43 | fmt.Println(u1)
44 | }
45 |
--------------------------------------------------------------------------------
/lesson14/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | )
6 |
7 | // interface
8 |
9 | type person struct {
10 | name string
11 | age uint16
12 | }
13 |
14 | type animal struct {
15 | name string
16 | age uint16
17 | }
18 |
19 | type skiller interface {
20 | run() string
21 | eat() string
22 | }
23 |
24 | func (p *person) run() string {
25 | str := fmt.Sprintf("My name is %s, I am %d years old. Now I am running.\n", p.name, p.age)
26 | return str
27 | }
28 |
29 | func (p *person) eat() string {
30 | str := fmt.Sprintf("My name is %s, I am %d years old. Now I am eating.\n", p.name, p.age)
31 | return str
32 | }
33 |
34 | func (a *animal) run() string {
35 | str := fmt.Sprintf("My name is %s, I am %d years old. Now I am running.\n", a.name, a.age)
36 | return str
37 | }
38 |
39 | func (a *animal) eat() string {
40 | str := fmt.Sprintf("My name is %s, I am %d years old. Now I am eating.\n", a.name, a.age)
41 | return str
42 | }
43 |
44 | func do(s skiller) string {
45 | str := s.run()
46 | str = s.eat()
47 | return str
48 | }
49 |
50 | func main() {
51 | p1 := new(person)
52 | p1.name = "lucy"
53 | p1.age = 18
54 | str1 := do(p1)
55 | fmt.Println(str1)
56 |
57 | a1 := new(animal)
58 | a1.name = "kity"
59 | a1.age = 2
60 | str2 := do(a1)
61 | fmt.Println(str2)
62 | }
63 |
--------------------------------------------------------------------------------
/lesson15/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "time"
6 | )
7 |
8 | // goroutine 和 channel
9 |
10 | func main() {
11 | go func() {
12 | for i := 0; i < 50; i++ {
13 | fmt.Println("number:", i)
14 | }
15 | }()
16 |
17 | go func() {
18 | str := "hello,world"
19 | for index := range str {
20 | fmt.Println("byte:", string(str[index]))
21 | }
22 | }()
23 |
24 | ch := make(chan string, 11)
25 | go func() {
26 | str := "hello,world"
27 | for index := range str {
28 | ch <- string(str[index])
29 | }
30 | }()
31 |
32 | go func() {
33 | for ch != nil {
34 | select {
35 | case byte := <-ch:
36 | str := byte
37 | fmt.Println("str:", str)
38 | fmt.Printf("ch 的容量是%d,长度是%d。\n", cap(ch), len(ch))
39 | default:
40 |
41 | }
42 | }
43 | }()
44 | time.Sleep(100 * time.Millisecond)
45 | fmt.Println("main.go func over")
46 | }
47 |
--------------------------------------------------------------------------------
/lesson16/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | // 并发
4 |
--------------------------------------------------------------------------------
/lesson17/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | // test
4 |
--------------------------------------------------------------------------------
/lesson18/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | // 包
4 |
--------------------------------------------------------------------------------
/lesson19/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | // go tool
4 |
--------------------------------------------------------------------------------
/lesson20/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "reflect"
6 | )
7 |
8 | // reflect
9 | // type A int
10 | /* var a A = 1
11 | t := reflect.TypeOf(a)
12 | fmt.Println(t.Name(), t.Kind()) */
13 |
14 | /* b := 2
15 | t1, t2 := reflect.TypeOf(b), reflect.TypeOf(&b)
16 | fmt.Println(t1, t2, t1 == t2, t2.Elem())
17 | fmt.Println(t1.Kind(), t2.Kind())
18 | fmt.Println(t1 == t2.Elem()) */
19 |
20 | /* type student struct {
21 | name string
22 | score int
23 | } */
24 |
25 | /* var s student
26 | t := reflect.TypeOf(&s)
27 | if t.Kind() == reflect.Ptr {
28 | t = t.Elem()
29 | }
30 |
31 | fmt.Println(t.NumField())
32 |
33 | for i := 0; i < t.NumField(); i++ {
34 | structField := t.Field(i)
35 | fmt.Println(structField.Name, structField.Type)
36 | } */
37 |
38 | /* type user struct {
39 | name string `form:"user_name"`
40 | age int `form:"user_age"`
41 | } */
42 |
43 | /* var user1 user
44 | t := reflect.TypeOf(user1)
45 | for i := 0; i < t.NumField(); i++ {
46 | structField := t.Field(i)
47 | fmt.Println(structField.Name, structField.Tag.Get("form"))
48 | } */
49 |
50 | /* type member struct {
51 | }
52 |
53 | func (m member) MemberInfo(name string, score int) string {
54 | mInfo := fmt.Sprintf("姓名:%s 积分:%d\n", name, score)
55 | return mInfo
56 | } */
57 |
58 | /* var m1 member
59 | v := reflect.ValueOf(&m1)
60 | m := v.MethodByName("MemberInfo")
61 |
62 | param := []reflect.Value{
63 | reflect.ValueOf("frank"),
64 | reflect.ValueOf(88),
65 | }
66 |
67 | result := m.Call(param)
68 | for _, v := range result {
69 | fmt.Println(v)
70 | } */
71 |
72 | /* type person struct{}
73 |
74 | func (p person) Hobby(name string, hobby ...interface{}) string {
75 | myHobby := fmt.Sprintf("I am %v, My hobby is %v", name, hobby)
76 | return myHobby
77 | } */
78 |
79 | /* var p1 person
80 | v := reflect.ValueOf(&p1)
81 | m := v.MethodByName("Hobby")
82 |
83 | param := []reflect.Value{
84 | reflect.ValueOf("lucy"),
85 | reflect.ValueOf("singing"),
86 | reflect.ValueOf("dancing"),
87 | }
88 |
89 | result := m.Call(param)
90 | fmt.Println(result)
91 |
92 | param = []reflect.Value{
93 | reflect.ValueOf("lucy"),
94 | reflect.ValueOf([]interface{}{"singing", "dancing"}),
95 | }
96 | result = m.CallSlice(param)
97 | fmt.Println(result) */
98 |
99 | type animal struct {
100 | Name string
101 | age int
102 | }
103 |
104 | func main() {
105 | var cat animal
106 | v := reflect.ValueOf(&cat).Elem()
107 | fmt.Printf("v:%v type:%v kind:%v\n", v, v.Type(), v.Kind())
108 | v.FieldByName("Name").SetString("kity")
109 | fmt.Printf("v:%v type:%v kind:%v\n", v, v.Type(), v.Kind())
110 | }
111 |
--------------------------------------------------------------------------------
/lesson27/cpu.out:
--------------------------------------------------------------------------------
1 | mode: set
2 | learn_go/lesson27/func.go:3.15,5.2 0 0
3 | learn_go/lesson27/func.go:7.24,9.2 1 1
4 |
--------------------------------------------------------------------------------
/lesson27/func.cover:
--------------------------------------------------------------------------------
1 | mode: set
2 | learn_go/lesson27/func.go:3.24,5.2 1 1
3 | learn_go/lesson27/func.go:7.30,9.32 2 1
4 | learn_go/lesson27/func.go:12.2,12.32 1 1
5 | learn_go/lesson27/func.go:9.32,11.3 1 1
6 |
--------------------------------------------------------------------------------
/lesson27/func.go:
--------------------------------------------------------------------------------
1 | package lesson27
2 |
3 | func Sum(a, b int) int {
4 | return a + b
5 | }
6 |
7 | func Avg(arg ...int) float64 {
8 | sum := 0
9 | for i := 0; i < len(arg); i++ {
10 | sum += arg[i]
11 | }
12 | return float64(sum / len(arg))
13 | }
14 |
--------------------------------------------------------------------------------
/lesson27/func_cover.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | lesson27: Go Coverage Report
7 |
52 |
53 |
54 |
55 |
56 |
61 |
62 |
63 | not tracked
64 |
65 | not covered
66 | covered
67 |
68 |
69 |
70 |
71 |
72 |
package lesson27
73 |
74 | func Sum(a, b int) int {
75 | return a+b
76 | }
77 |
78 | func Avg(arg ...int) float64 {
79 | sum := 0
80 | for i := 0; i < len(arg); i++ {
81 | sum += arg[i]
82 | }
83 | return float64(sum / len(arg))
84 | }
85 |
86 |
87 |
88 |
115 |
116 |
--------------------------------------------------------------------------------
/lesson27/func_test.go:
--------------------------------------------------------------------------------
1 | package lesson27
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | func TestSum(t *testing.T) {
8 | a, b := 1, 2
9 | rst := Sum(a, b)
10 | if rst == 3 {
11 | t.Logf("expected=%d, actual=%d", 3, rst)
12 | } else {
13 | // t.Errorf("expected=%d, actual=%d", 3, rst)
14 | t.Fatalf("expected=%d, actual=%d", 3, rst)
15 | }
16 | t.Log("done")
17 | }
18 |
19 | func TestAvg(t *testing.T) {
20 | rst := Avg(1, 2, 3)
21 | if rst == 2 {
22 | t.Log("success")
23 | return
24 | }
25 | t.Log("fail")
26 | }
27 |
28 | func BenchmarkSum(b *testing.B) {
29 | for i := 0; i < b.N; i++ {
30 | Sum(1, 2)
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/lesson27/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/weirubo/learn_go/lesson27
2 |
3 | go 1.17
4 |
--------------------------------------------------------------------------------
/lesson29/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "sort"
6 | )
7 |
8 | type IntSlice []int
9 |
10 | func (s IntSlice) Len() int {
11 | return len(s)
12 | }
13 |
14 | func (s IntSlice) Less(i, j int) bool {
15 | return s[i] < s[j]
16 | }
17 |
18 | func (s IntSlice) Swap(i, j int) {
19 | s[i], s[j] = s[j], s[i]
20 | }
21 |
22 | func main() {
23 | intSlice := IntSlice([]int{9, 7, 5, 3, 1})
24 | fmt.Println(intSlice) // 排序前
25 | // sort.Sort(intSlice)
26 | // fmt.Println(intSlice) // 排序后
27 | sort.Ints(intSlice)
28 | fmt.Println(intSlice) // 使用 sort.Ints() 排序数据
29 |
30 | people := []struct {
31 | Name string
32 | Age int
33 | }{
34 | {"Gopher", 7},
35 | {"Alice", 55},
36 | {"Vera", 24},
37 | {"Bob", 75},
38 | }
39 | sort.Slice(people, func(i, j int) bool { return people[i].Name < people[j].Name })
40 | fmt.Println("By name:", people)
41 |
42 | sort.Slice(people, func(i, j int) bool { return people[i].Age < people[j].Age })
43 | fmt.Println("By age:", people)
44 | }
45 |
--------------------------------------------------------------------------------
/lesson30/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/weirubo/learn_go/lesson30
2 |
3 | go 1.17
4 |
5 | require github.com/spf13/cast v1.4.1 // indirect
6 |
--------------------------------------------------------------------------------
/lesson30/go.sum:
--------------------------------------------------------------------------------
1 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
2 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
3 | github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA=
4 | github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
5 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
6 |
--------------------------------------------------------------------------------
/lesson30/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "github.com/spf13/cast"
6 | )
7 |
8 | func main() {
9 | // ToString
10 | val1 := 1
11 | fmt.Printf("Before val=%v type=%T\n", val1, val1)
12 | fmt.Printf("After val=%v type=%T\n", cast.ToString(val1), cast.ToString(val1))
13 |
14 | val2 := []int{1, 2, 3}
15 | fmt.Printf("Before val=%v type=%T\n", val2, val2)
16 | fmt.Printf("After val=%v type=%T\n", cast.ToStringSlice(val2), cast.ToStringSlice(val2))
17 |
18 | // ToInt
19 | // 如果不是数值字符串,转换后的值是类型零值
20 | val3 := "1"
21 | fmt.Printf("Before val=%v type=%T\n", val3, val3)
22 | fmt.Printf("After val=%v type=%T\n", cast.ToInt(val3), cast.ToInt(val3))
23 |
24 | // 如果切片元素不是数值字符串,转换后的值是类型零值
25 | val4 := []string{"1", "2", "3"}
26 | fmt.Printf("Before val=%v type=%T\n", val4, val4)
27 | fmt.Printf("After val=%v type=%T\n", cast.ToIntSlice(val4), cast.ToIntSlice(val4))
28 |
29 | // ToBool
30 | // 非零整型都是 true,非整型和零都是 false
31 | val5 := 1
32 | fmt.Printf("Before val=%v type=%T\n", val5, val5)
33 | fmt.Printf("After val=%v type=%T\n", cast.ToBool(val5), cast.ToBool(val5))
34 |
35 | // 切片元素必须是 int 类型
36 | val6 := []int{-1, 0, 1}
37 | fmt.Printf("Before val=%v type=%T\n", val6, val6)
38 | fmt.Printf("After val=%v type=%T\n", cast.ToBoolSlice(val6), cast.ToBoolSlice(val6))
39 |
40 | // 参数值必须是整型,或字符串数值
41 | val7 := 1636811715
42 | fmt.Printf("Before val=%v type=%T\n", val7, val7)
43 | fmt.Printf("After val=%v type=%T\n", cast.ToTime(val7), cast.ToTime(val7))
44 |
45 | a := 1
46 | fmt.Printf("val=%v type=%T\n", cast.ToString(a), cast.ToString(a))
47 | b := 3.14
48 | fmt.Printf("val=%v type=%T\n", cast.ToString(b), cast.ToString(b))
49 | c := "hello"
50 | fmt.Printf("val=%v type=%T\n", cast.ToString(c), cast.ToString(c))
51 | d := []byte("golang")
52 | fmt.Printf("val=%v type=%T\n", cast.ToString(d), cast.ToString(d))
53 | var e interface{} = "frank"
54 | fmt.Printf("val=%v type=%T\n", cast.ToString(e), cast.ToString(e))
55 | f := []int{1, 2, 3}
56 | fmt.Printf("val=%v type=%T\n", f, f)
57 | fmt.Printf("val=%v type=%T\n", cast.ToString(nil), cast.ToString(nil))
58 |
59 | v, err := cast.ToStringE([]int{1, 2, 3})
60 | if err != nil {
61 | fmt.Println(err)
62 | return
63 | }
64 | fmt.Printf("val=%v type=%T\n", v, v)
65 | }
66 |
--------------------------------------------------------------------------------
/lesson31/test/anonymous_test.go:
--------------------------------------------------------------------------------
1 | package test
2 |
3 | import "testing"
4 |
5 | func TestAnonymous(t *testing.T) {
6 | // func () {
7 | // t.Log("Hello World")
8 | // }()
9 | // func (a, b int) int {
10 | // return a + b
11 | // }(1,2)
12 | sum := func(a, b int) int {
13 | return a + b
14 | }
15 | t.Log(sum(1, 2))
16 | }
17 |
--------------------------------------------------------------------------------
/lesson31/test/closures_test.go:
--------------------------------------------------------------------------------
1 | package test
2 |
3 | import (
4 | "testing"
5 | "time"
6 | )
7 |
8 | func TestClosures(t *testing.T) {
9 | // x, y := 1, 2
10 | // func (a, b int) {
11 | // t.Log(a + b)
12 | // }(x, y)
13 |
14 | // for i := 0; i < 10; i++ {
15 | // sum := func () int {
16 | // return i + 1
17 | // }()
18 | // t.Logf("i = %d sum = %d \n", i, sum)
19 | // }
20 |
21 | // values := []int{1,2,3,4,5}
22 | // for _, val := range values {
23 | // go func() {
24 | // t.Logf("%p %d\n", &val, val)
25 | // }()
26 | // }
27 |
28 | values := []int{1, 2, 3, 4, 5}
29 | for _, val := range values {
30 | go func(val int) {
31 | t.Logf("%p %d\n", &val, val)
32 | }(val)
33 | }
34 | time.Sleep(time.Second)
35 | }
36 |
--------------------------------------------------------------------------------
/lesson31/test/higherOrder_test.go:
--------------------------------------------------------------------------------
1 | package test
2 |
3 | import "testing"
4 |
5 | func TestHigherOrder(t *testing.T) {
6 | t.Log(operation(1, 2, func(x, y int) int {
7 | return x + y
8 | }))
9 |
10 | sum := operation1()
11 | t.Log(sum(2, 3))
12 | }
13 |
14 | func operation(x, y int, operaFuc func(int, int) int) int {
15 | rst := operaFuc(x, y)
16 | return rst
17 | }
18 |
19 | func operation1() func(x, y int) int {
20 | sum := func(x, y int) int {
21 | return x + y
22 | }
23 | return sum
24 | }
25 |
--------------------------------------------------------------------------------
/lesson31/test/recursion_test.go:
--------------------------------------------------------------------------------
1 | package test
2 |
3 | import "testing"
4 |
5 | func TestRecursion(t *testing.T) {
6 | var fib func(n int) int
7 | fib = func(n int) int {
8 | if n < 2 {
9 | return n
10 | }
11 | return fib(n-1) + fib(n-2)
12 | }
13 | t.Log(fib(7))
14 | }
15 |
--------------------------------------------------------------------------------
/lesson32/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/weirubo/learn_go/lesson32
2 |
3 | go 1.17
4 |
5 | require (
6 | github.com/jinzhu/now v1.1.3 // indirect
7 | gorm.io/gorm v1.22.3 // indirect
8 | xorm.io/xorm v1.2.5 // indirect
9 | )
10 |
--------------------------------------------------------------------------------
/lesson32/interface_test.go:
--------------------------------------------------------------------------------
1 | package lesson32
2 |
3 | import (
4 | "log"
5 | "testing"
6 | "xorm.io/xorm"
7 | )
8 |
9 | type DBOrm interface {
10 | Insert(param ...interface{})
11 | }
12 |
13 | type XormDB struct {
14 | db *xorm.Session
15 | }
16 |
17 | func (x *XormDB) Insert(param ...interface{}) {
18 | _, err := x.db.Insert(param)
19 | if err != nil {
20 | log.Println(err)
21 | }
22 | }
23 |
24 | // type GormDB struct {
25 | // db *gorm.DB
26 | // }
27 | //
28 | // func (g *GormDB) Insert(param ...interface{}) {
29 | // g.db.Create(param)
30 | // }
31 |
32 | type User struct {
33 | orm DBOrm
34 | Id int64
35 | Name string
36 | }
37 |
38 | func (u *User) DB() DBOrm {
39 | u.orm = new(XormDB) // 数据库实例注入接口
40 | // u.orm = new(GormDB)
41 | return u.orm
42 | }
43 |
44 | func TestOrm(t *testing.T) {
45 | user1 := new(User)
46 | user1.Name = "lucy"
47 | user1.DB().Insert(user1)
48 | }
49 |
--------------------------------------------------------------------------------
/lesson32/struct_test.go:
--------------------------------------------------------------------------------
1 | package lesson32
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | type Sayer interface {
8 | Say() string
9 | }
10 |
11 | type Cat struct {
12 | }
13 |
14 | func (c Cat) Say() string {
15 | return "miaow"
16 | }
17 |
18 | type Dog struct {
19 | }
20 |
21 | func (d Dog) Say() string {
22 | return "woof woof"
23 | }
24 |
25 | type Horse struct {
26 | }
27 |
28 | func (h Horse) Say() string {
29 | return "neigh"
30 | }
31 |
32 | func TestSay(t *testing.T) {
33 | c := Cat{}
34 | // t.Log("Cat say:", c.Say())
35 | //
36 | d := Dog{}
37 | // t.Log("Dog say:", d.Say())
38 |
39 | h := Horse{}
40 |
41 | animals := []Sayer{c, d, h}
42 | for _, a := range animals {
43 | t.Log("say:", a.Say())
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/lesson33/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | )
6 |
7 | func main() {
8 | // defer func() {
9 | // if err := recover(); err != nil {
10 | // fmt.Println("err = ", err)
11 | // }
12 | // }()
13 | user := new(User)
14 | // user := &User{}
15 | userInfo := user.GetInfo()
16 | fmt.Println(userInfo)
17 | if userInfo.Age >= 18 {
18 | fmt.Println("this is a man")
19 | }
20 |
21 | // code := []string{"php", "golang"}
22 | // fmt.Printf("len:%d cap:%d val:%s \n", len(code), cap(code), code)
23 | // fmt.Println(code[2])
24 |
25 | // var ch chan int
26 | // close(ch)
27 | // ch = make(chan int, 1)
28 | // ch <- 1
29 | // close(ch)
30 | // close(ch)
31 | // ch <- 2
32 |
33 | // var m map[string]int
34 | // m = make(map[string]int)
35 | // go func(map[string]int) {
36 | // for {
37 | // m["php"] = 80
38 | // }
39 | // }(m)
40 | //
41 | // go func(map[string]int) {
42 | // for {
43 | // _ = m["php"]
44 | // }
45 | // }(m)
46 | //
47 | // time.Sleep(time.Second)
48 |
49 | var name interface{} = "frank"
50 | // a, ok := name.(int)
51 | // fmt.Println(a, ok)
52 | a := name.(int)
53 | fmt.Println(a)
54 | }
55 |
56 | type User struct {
57 | Name string
58 | Age int
59 | }
60 |
61 | func (u *User) GetInfo() (data *User) {
62 | data = &User{
63 | Name: "frank",
64 | Age: 18,
65 | }
66 | return data
67 | }
68 |
--------------------------------------------------------------------------------
/lesson34/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | f := fmt.Println
7 | f(a())
8 | f(b())
9 | }
10 |
11 | func a() int {
12 | i := 0
13 | defer func() {
14 | i += 1
15 | fmt.Println("a defer:", i)
16 | }()
17 | return i
18 | }
19 |
20 | func b() (i int) {
21 | i = 0
22 | defer func() {
23 | i += 1
24 | fmt.Println("b defer:", i)
25 | }()
26 | return i
27 | }
28 |
29 | func c() *int {
30 | i := 0
31 | return &i
32 | }
33 |
34 | func d() (i *int) {
35 | return
36 | }
37 |
--------------------------------------------------------------------------------
/lesson35/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | s := []int{0, 1}
7 | for _, v := range s {
8 | s = append(s, v)
9 | }
10 | fmt.Printf("s=%v\n", s)
11 |
12 | // s := []int{0, 1}
13 | // for i := 0; i < len(s); i++ {
14 | // s = append(s, s[i])
15 | // }
16 | // fmt.Printf("s=%v\n", s)
17 | }
18 |
--------------------------------------------------------------------------------
/lesson36/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "io"
6 | "log"
7 | "net/http"
8 | )
9 |
10 | func main() {
11 | res, err := http.Get("http://www.baidu2022.com/robots.txt")
12 | // fmt.Println(res)
13 | if err != nil {
14 | log.Fatal(err)
15 | }
16 | defer res.Body.Close()
17 | // if err != nil {
18 | // log.Fatal(err)
19 | // }
20 | body, err := io.ReadAll(res.Body)
21 | // res.Body.Close()
22 | // if res.StatusCode > 299 {
23 | // log.Fatalf("Response failed with status code: %d and\nbody: %s\n", res.StatusCode, body)
24 | // }
25 | if err != nil {
26 | log.Fatal(err)
27 | }
28 | fmt.Printf("%s", body)
29 | user := GetUser()
30 | // fmt.Println(user)
31 | // if user != nil {
32 | // fmt.Println(user.Id)
33 | // }
34 | user.Login()
35 |
36 | var userData map[int]*User
37 | // fmt.Println(userData[1].Name)
38 | if val, ok := userData[1]; ok {
39 | fmt.Println(val.Name)
40 | }
41 |
42 | }
43 |
44 | func GetUser() (user *User) {
45 | user = new(User)
46 | // user = &User{}
47 | return
48 | }
49 |
50 | type User struct {
51 | Id int
52 | Name string
53 | }
54 |
55 | // func (u User) Login() {
56 | //
57 | // }
58 |
59 | func (u *User) Login() {
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/lesson37/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | name := "frank"
7 | user := &User{
8 | Id: 1,
9 | Name: &name,
10 | }
11 | fmt.Println(user)
12 | }
13 |
14 | type User struct {
15 | Id int
16 | Name *string
17 | }
18 |
19 | func (u *User) String() string {
20 | return fmt.Sprintf("{Id: %v, Name: %v}", u.Id, *u.Name)
21 | }
22 |
--------------------------------------------------------------------------------
/lesson40/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "math"
6 | )
7 |
8 | func main() {
9 | // var hello = func(name string) { fmt.Printf("hello %s\n", name) }
10 | // hello("gopher")
11 |
12 | // area := Circle(5, areaOfCircle)
13 | // fmt.Printf("area:%.2f\n", area)
14 | //
15 | // perimeter := Circle(5, perimeterOfCircle)
16 | // fmt.Printf("perimeter:%.2f\n", perimeter)
17 |
18 | calcArea := CircleCalc("area")
19 | fmt.Println(calcArea(5))
20 | calcPerimeter := CircleCalc("perimeter")
21 | fmt.Println(calcPerimeter(5))
22 | }
23 |
24 | // func Circle(r float64, op func(float64) float64) float64 {
25 | // return op(r)
26 | // }
27 | //
28 | // func areaOfCircle(r float64) float64 {
29 | // return math.Pi * r * r
30 | // }
31 | //
32 | // func perimeterOfCircle(r float64) float64 {
33 | // return 2 * math.Pi * r
34 | // }
35 |
36 | func CircleCalc(s string) func(float64) float64 {
37 | switch s {
38 | case "area":
39 | return func(r float64) float64 {
40 | return math.Pi * r * r
41 | }
42 | case "perimeter":
43 | return func(r float64) float64 {
44 | return 2 * math.Pi * r
45 | }
46 | default:
47 | return nil
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/lesson41/app/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | _ "github.com/go-sql-driver/mysql"
6 | "github.com/labstack/echo/v4"
7 | _userHttpDelivery "github.com/weirubo/learn_go/lesson41/user/delivery/http"
8 | _userRepo "github.com/weirubo/learn_go/lesson41/user/repository/mysql"
9 | _userUsecase "github.com/weirubo/learn_go/lesson41/user/usecase"
10 | "xorm.io/xorm"
11 | )
12 |
13 | func main() {
14 | db, err := xorm.NewEngine("mysql", "root:mysqlpw123@tcp(127.0.0.1:55000)/test")
15 | if err != nil {
16 | fmt.Printf("main || xorm || err=%v\n", err)
17 | return
18 | }
19 | defer func() {
20 | err := db.Close()
21 | if err != nil {
22 | return
23 | }
24 | }()
25 | e := echo.New()
26 | userRepo := _userRepo.NewMysqlUserRepository(db)
27 | userUsecase := _userUsecase.NewUserUsecase(userRepo)
28 | _userHttpDelivery.NewUserHandler(e, userUsecase)
29 | err = e.Start(":1323")
30 | if err != nil {
31 | fmt.Printf("main || echo start || err=%v\n", err)
32 | return
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/lesson41/domain/user.go:
--------------------------------------------------------------------------------
1 | package domain
2 |
3 | import "context"
4 |
5 | type User struct {
6 | Id int64 `json:"id"`
7 | Name string `json:"name"`
8 | Created int `json:"created"`
9 | Updated int `json:"updated"`
10 | }
11 |
12 | type UserUsecase interface {
13 | GetUserById(ctx context.Context, user *User) error
14 | }
15 |
16 | type UserRepository interface {
17 | GetUserById(ctx context.Context, user *User) error
18 | }
19 |
--------------------------------------------------------------------------------
/lesson41/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/weirubo/learn_go/lesson41
2 |
3 | go 1.18
4 |
5 | require (
6 | github.com/go-sql-driver/mysql v1.6.0
7 | github.com/labstack/echo/v4 v4.9.0
8 | github.com/pkg/errors v0.9.1
9 | xorm.io/xorm v1.3.1
10 | )
11 |
12 | require (
13 | github.com/mattn/go-colorable v0.1.12 // indirect
14 | github.com/stretchr/testify v1.7.2 // indirect
15 | golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
16 | golang.org/x/net v0.0.0-20220621193019-9d032be2e588 // indirect
17 | golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c // indirect
18 | )
19 |
--------------------------------------------------------------------------------
/lesson41/user/delivery/http/user.go:
--------------------------------------------------------------------------------
1 | package http
2 |
3 | import (
4 | // "errors"
5 | "fmt"
6 | "github.com/labstack/echo/v4"
7 | "github.com/pkg/errors"
8 | "github.com/weirubo/learn_go/lesson41/domain"
9 | "net/http"
10 | "strconv"
11 | )
12 |
13 | type UserHandler struct {
14 | UserUsecase domain.UserUsecase
15 | }
16 |
17 | func NewUserHandler(echo *echo.Echo, userUsecase domain.UserUsecase) {
18 | handler := &UserHandler{
19 | UserUsecase: userUsecase,
20 | }
21 | echo.GET("/user/:id", handler.GetUserById)
22 | }
23 |
24 | func (u *UserHandler) GetUserById(c echo.Context) error {
25 | idP, err := strconv.Atoi(c.Param("id"))
26 | if err != nil {
27 | return c.JSON(http.StatusNotFound, err)
28 | }
29 | id := int64(idP)
30 | ctx := c.Request().Context()
31 | user := &domain.User{
32 | Id: id,
33 | }
34 | err = u.UserUsecase.GetUserById(ctx, user)
35 | if err != nil {
36 | // err = errors.New("UserUsecase error")
37 | err = errors.Wrap(err, "UserUsecase error")
38 | fmt.Printf("UserHandler || GetUserById() || uid=%v || err=%+v\n", id, err)
39 | return c.JSON(http.StatusInternalServerError, err)
40 | }
41 | return c.JSON(http.StatusOK, user)
42 | }
43 |
--------------------------------------------------------------------------------
/lesson41/user/repository/mysql/user.go:
--------------------------------------------------------------------------------
1 | package mysql
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "github.com/weirubo/learn_go/lesson41/domain"
7 | "xorm.io/xorm"
8 | )
9 |
10 | type mysqlUserRepository struct {
11 | DB *xorm.Engine
12 | }
13 |
14 | func NewMysqlUserRepository(db *xorm.Engine) domain.UserRepository {
15 | return &mysqlUserRepository{
16 | DB: db,
17 | }
18 | }
19 |
20 | func (m *mysqlUserRepository) GetUserById(ctx context.Context, user *domain.User) (err error) {
21 | _, err = m.DB.Get(user)
22 | fmt.Printf("mysqlUserRepository || GetUserById() || uid=%v || err=%v\n", user.Id, err)
23 | return
24 | }
25 |
--------------------------------------------------------------------------------
/lesson41/user/usecase/user.go:
--------------------------------------------------------------------------------
1 | package usecase
2 |
3 | import (
4 | "context"
5 | // "errors"
6 | "fmt"
7 | "github.com/pkg/errors"
8 | "github.com/weirubo/learn_go/lesson41/domain"
9 | )
10 |
11 | type userUsecase struct {
12 | userRepo domain.UserRepository
13 | }
14 |
15 | func NewUserUsecase(userRepo domain.UserRepository) domain.UserUsecase {
16 | return &userUsecase{
17 | userRepo: userRepo,
18 | }
19 | }
20 |
21 | func (u *userUsecase) GetUserById(ctx context.Context, user *domain.User) (err error) {
22 | if user.Id == 0 {
23 | err = errors.New("invalid request parameter")
24 | }
25 | err = u.userRepo.GetUserById(ctx, user)
26 | fmt.Printf("userUsecase || GetUserById() || uid=%v || err=%v\n", user.Id, err)
27 | return
28 | }
29 |
--------------------------------------------------------------------------------
/lesson42/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/weirubo/learn_go/lesson42
2 |
3 | go 1.18
4 |
5 | require github.com/pkg/errors v0.9.1
6 |
--------------------------------------------------------------------------------
/lesson42/go.sum:
--------------------------------------------------------------------------------
1 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
2 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
3 |
--------------------------------------------------------------------------------
/lesson42/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "github.com/pkg/errors"
6 | )
7 |
8 | func main() {
9 | name := "frank"
10 | age := 18
11 | gender := "male"
12 | detail, err := CallUserCenter(name, age, gender)
13 | if err != nil {
14 | fmt.Printf("err=%v\n", err)
15 | return
16 | }
17 | fmt.Printf("name:%s\nage:%d\ngender:%s\n", detail.name, detail.age, detail.gender)
18 | fmt.Printf("%s\n", "********************")
19 | name2 := "lucy"
20 | age2 := 17
21 | gender2 := "female"
22 | salary2 := 5000
23 |
24 | detail2, err := CallUserCenter(name2, age2, gender2, salary2)
25 | if err != nil {
26 | fmt.Printf("err=%v\n", err)
27 | return
28 | }
29 | fmt.Printf("name:%s\nage:%d\ngender:%s\nsalary:%d\n", detail2.name, detail2.age, detail2.gender, detail2.salary)
30 | }
31 |
32 | func CallUserCenter(name string, age int, gender string, args ...interface{}) (detail *User, err error) {
33 | if len(args) == 0 {
34 | detail, err = NewUserUsecase().Create(name, age, gender)
35 | } else {
36 | detail, err = NewUserUsecase().Create(name, age, gender, args[0])
37 | }
38 | if err != nil {
39 | return
40 | }
41 | return
42 | }
43 |
44 | type User struct {
45 | name string
46 | age int
47 | gender string
48 | salary int
49 | }
50 |
51 | type UserUsecase interface {
52 | Create(name string, age int, gender string, args ...interface{}) (*User, error)
53 | }
54 |
55 | type userUsecase struct {
56 | }
57 |
58 | func NewUserUsecase() UserUsecase {
59 | return &userUsecase{}
60 | }
61 |
62 | func (u *userUsecase) Create(name string, age int, gender string, args ...interface{}) (detail *User, err error) {
63 | if name == "" || age < 0 || gender == "" {
64 | err = errors.New("param illegal")
65 | }
66 | if len(args) == 0 {
67 | detail = &User{
68 | name: name,
69 | age: age,
70 | gender: gender,
71 | }
72 | } else {
73 | detail = &User{
74 | name: name,
75 | age: age,
76 | gender: gender,
77 | salary: args[0].(int),
78 | }
79 | }
80 | return
81 | }
82 |
--------------------------------------------------------------------------------
/lesson43/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/weirubo/learn_go/lesson43
2 |
3 | go 1.18
4 |
--------------------------------------------------------------------------------
/lesson43/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | var r *int
4 |
5 | func main() {
6 | sum(1, 2)
7 | }
8 |
9 | func sum(a, b int) *int {
10 | res := a + b
11 | return &res
12 | }
13 |
--------------------------------------------------------------------------------
/lesson44/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/weirubo/learn_go/lesson44
2 |
3 | go 1.13
4 |
--------------------------------------------------------------------------------
/lesson44/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | fmt.Println("hello world")
7 | // pointerEscape(1, 2)
8 | }
9 |
10 | // pointerEscape
11 | // func pointerEscape(a, b int) *int {
12 | // sum := a + b
13 | // return &sum
14 | // }
15 |
--------------------------------------------------------------------------------
/lesson45/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | var name string = "frank"
7 | fmt.Printf("val:%s || ptr:%p\n", name, &name)
8 | name, age := "lucy", 18
9 | fmt.Printf("val:%s || ptr:%p\n", name, &name)
10 | fmt.Println(age)
11 | if name != "lily" {
12 | name := "lily"
13 | fmt.Printf("val:%s || ptr:%p\n", name, &name)
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/lesson46/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | )
6 |
7 | func main() {
8 | done := make(chan bool)
9 |
10 | values := []string{"a", "b", "c"}
11 | for _, v := range values {
12 | // go func(param string) {
13 | // // fmt.Println(v)
14 | // fmt.Printf("val=%s pointer=%p\n", param, ¶m)
15 | // done <- true
16 | // }(v)
17 |
18 | param := v
19 | go func() {
20 | // fmt.Println(v)
21 | fmt.Printf("val=%s pointer=%p\n", param, ¶m)
22 | done <- true
23 | }()
24 | }
25 |
26 | // wait for all goroutines to complete before exiting
27 | for _ = range values {
28 | <-done
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/lesson47/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/weirubo/learn_go/lesson47
2 |
3 | go 1.13
4 |
5 | require github.com/mitchellh/mapstructure v1.5.0 // indirect
6 |
--------------------------------------------------------------------------------
/lesson47/go.sum:
--------------------------------------------------------------------------------
1 | github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
2 | github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
3 |
--------------------------------------------------------------------------------
/lesson47/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 | "github.com/mitchellh/mapstructure"
7 | "log"
8 | )
9 |
10 | func main() {
11 | // 三方返回普通 json 字符串
12 | // jsonRes := `{
13 | // "Id": 1001,
14 | // "Name": "frank"
15 | // }`
16 | // data := new(User)
17 | // err := json.Unmarshal([]byte(jsonRes), &data)
18 | // if err != nil {
19 | // log.Printf("json Unmarshal err:%v\n", err)
20 | // return
21 | // }
22 | // fmt.Printf("data=%+v", data)
23 |
24 | // data2 := make(map[string]interface{})
25 | // err := json.Unmarshal([]byte(jsonRes), &data2)
26 | // if err != nil {
27 | // log.Printf("json Unmarshal err:%v\n", err)
28 | // return
29 | // }
30 | // fmt.Printf("data2=%+v", data2)
31 |
32 | // 三方返回嵌套 json 字符串
33 | jsonRes := `{
34 | "Id": 1001,
35 | "Name": "frank",
36 | "Details": {
37 | "Gender": "man",
38 | "Age": 18,
39 | "Phone": "13800138000",
40 | "address": "Beijing"
41 | }
42 | }`
43 | // data := new(User)
44 | // err := json.Unmarshal([]byte(jsonRes), &data)
45 | // if err != nil {
46 | // log.Printf("json Unmarshal err:%v\n", err)
47 | // return
48 | // }
49 | // fmt.Printf("data=%+v\n", data)
50 |
51 | // data := make(map[string]interface{})
52 | // err := json.Unmarshal([]byte(jsonRes), &data)
53 | // if err != nil {
54 | // log.Printf("json Unmarshal err:%v\n", err)
55 | // return
56 | // }
57 | // fmt.Printf("data=%+v\n", data)
58 | // fmt.Printf("age=%v\n", data["Details"]["Age"])
59 |
60 | tmpData := make(map[string]interface{})
61 | err := json.Unmarshal([]byte(jsonRes), &tmpData)
62 | if err != nil {
63 | log.Printf("json Unmarshal err:%v\n", err)
64 | return
65 | }
66 | data2 := new(User)
67 | err = mapstructure.Decode(tmpData, data2)
68 | if err != nil {
69 | log.Printf("decode err:%v\n", err)
70 | return
71 | }
72 | fmt.Printf("data2=%+v\n", data2)
73 | fmt.Printf("age=%v\n", data2.Details.Age)
74 | }
75 |
76 | type User struct {
77 | Id int
78 | Name string
79 | Details Details
80 | }
81 |
82 | type Details struct {
83 | Gender string
84 | Age interface{}
85 | Phone string
86 | Address string
87 | }
88 |
--------------------------------------------------------------------------------
/lesson48/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/weirubo/learn_go/lesson48
2 |
3 | go 1.13
4 |
--------------------------------------------------------------------------------
/lesson48/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "errors"
5 | "log"
6 | )
7 |
8 | func main() {
9 | err := foo()
10 | if err != nil {
11 | log.Printf("err=%v\n", err)
12 | return
13 | }
14 | }
15 |
16 | func foo() (err error) {
17 | var code int
18 | if code, err = bar(); err != nil {
19 | log.Printf("code=%v err=%v\n", code, err)
20 | return // Compiler reports: err is shadowed during return
21 | }
22 | return nil
23 | }
24 |
25 | func bar() (int, error) {
26 | err := errors.New("this is bar's err")
27 | return 200, err
28 | }
29 |
--------------------------------------------------------------------------------
/lesson49/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/weirubo/learn_go/lesson49
2 |
3 | go 1.13
4 |
--------------------------------------------------------------------------------
/lesson49/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | a := make([]int, 0, 5)
7 | a = append(a, 1)
8 | b := append(a, 2)
9 | c := append(a, 3)
10 | fmt.Printf("v=%v || p=%p\n", a, &a)
11 | fmt.Printf("v=%v || p=%p\n", b, &b)
12 | fmt.Printf("v=%v || p=%p\n", c, &c)
13 | }
14 |
--------------------------------------------------------------------------------
/lesson50/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "time"
6 | )
7 |
8 | func main() {
9 | nowTime := time.Now().Unix()
10 | fmt.Println(nowTime)
11 | // NewTimerDemo()
12 | AfterFuncDemo()
13 | }
14 |
15 | func NewTimerDemo() {
16 | timer := time.NewTimer(2 * time.Second)
17 | select {
18 | case <-timer.C:
19 | currentTime := time.Now().Unix()
20 | fmt.Println(currentTime, "do something")
21 | }
22 | }
23 |
24 | func AfterFuncDemo() {
25 | time.AfterFunc(2*time.Second, func() {
26 | currentTime := time.Now().Unix()
27 | fmt.Println(currentTime, "do something")
28 | })
29 | time.Sleep(3 * time.Second)
30 | }
31 |
--------------------------------------------------------------------------------
/lesson51/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/weirubo/learn_go/lesson51
2 |
3 | go 1.13
4 |
5 | require (
6 | github.com/pkg/errors v0.9.1
7 | golang.org/x/sync v0.1.0
8 | )
9 |
--------------------------------------------------------------------------------
/lesson51/go.sum:
--------------------------------------------------------------------------------
1 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
2 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
3 | golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
4 | golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
5 |
--------------------------------------------------------------------------------
/lesson51/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "errors"
5 | "fmt"
6 | "golang.org/x/sync/errgroup"
7 | )
8 |
9 | func main() {
10 | // eg := errgroup.Group{}
11 | // eg.Go(func() error {
12 | // fmt.Println("go1")
13 | // return nil
14 | // })
15 | // eg.Go(func() error {
16 | // fmt.Println("go2")
17 | // err := errors.New("go2 err")
18 | // return err
19 | // })
20 | // err := eg.Wait()
21 | // if err != nil {
22 | // fmt.Println("err =", err)
23 | // }
24 |
25 | // eg, ctx := errgroup.WithContext(context.Background())
26 | // eg.Go(func() error {
27 | // time.Sleep(1 * time.Second)
28 | // select {
29 | // case <-ctx.Done():
30 | // fmt.Println("go1 cancel, err = ", ctx.Err())
31 | // default:
32 | // fmt.Println("go1 run")
33 | // }
34 | // return nil
35 | // })
36 | // eg.Go(func() error {
37 | // err := errors.New("go2 err")
38 | // return err
39 | // })
40 | // err := eg.Wait()
41 | // if err != nil {
42 | // fmt.Println("err =", err)
43 | // }
44 |
45 | eg := errgroup.Group{}
46 | eg.SetLimit(2)
47 | eg.TryGo(func() error {
48 | fmt.Println("go1 run")
49 | return nil
50 | })
51 | eg.TryGo(func() error {
52 | err := errors.New("go2 err")
53 | return err
54 | })
55 | eg.TryGo(func() error {
56 | fmt.Println("go3 run")
57 | return nil
58 | })
59 | err := eg.Wait()
60 | if err != nil {
61 | fmt.Println("err =", err)
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/lesson52/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | )
7 |
8 | func main() {
9 | // ctx := context.WithValue(context.Background(), "ctxKey1", "ctxVal")
10 | // ctx = context.WithValue(ctx, "ctxKey2", "ctxVal2")
11 | // ctx = context.WithValue(ctx, "ctxKey3", "ctxVal3")
12 | // go func(ctx context.Context) {
13 | // // 读取 ctx 的 value
14 | // data, ok := ctx.Value("ctxKey1").(string)
15 | // if ok {
16 | // fmt.Printf("sub goroutine get value from parent goroutine, val=%s\n", data)
17 | // }
18 | // data, ok = ctx.Value("ctxKey2").(string)
19 | // if ok {
20 | // fmt.Printf("sub goroutine get value from parent goroutine, val=%s\n", data)
21 | // }
22 | // data, ok = ctx.Value("ctxKey3").(string)
23 | // if ok {
24 | // fmt.Printf("sub goroutine get value from parent goroutine, val=%s\n", data)
25 | // }
26 | // }(ctx)
27 |
28 | // ctxVal := make(map[string]string)
29 | // ctxVal["k1"] = "v1"
30 | // ctxVal["k2"] = "v2"
31 | // ctx := context.WithValue(context.Background(), "ctxKey1", ctxVal)
32 | // go func(ctx context.Context) {
33 | // // 读取 ctx 的 value
34 | // data, ok := ctx.Value("ctxKey1").(map[string]string)
35 | // if ok {
36 | // fmt.Printf("sub goroutine get value from parent goroutine, val=%+v\n", data)
37 | // }
38 | // }(ctx)
39 |
40 | // ctxVal := make(map[string]string)
41 | // ctxVal["k1"] = "v1"
42 | // ctxVal["k2"] = "v2"
43 | // ctx := context.WithValue(context.Background(), "ctxKey1", ctxVal)
44 | // go func(ctx context.Context) {
45 | // // 读取 ctx 的 value
46 | // data, ok := ctx.Value("ctxKey1").(map[string]string)
47 | // if ok {
48 | // ctxVal := make(map[string]string)
49 | // for k, v := range data {
50 | // ctxVal[k] = v
51 | // }
52 | // ctxVal["k3"] = "v3"
53 | // ctx = context.WithValue(ctx, "ctxKey1", ctxVal)
54 | // data, ok := ctx.Value("ctxKey1").(map[string]string)
55 | // if !ok {
56 | // fmt.Printf("sub goroutine get value from parent goroutine, val=%+v\n", nil)
57 | // }
58 | // fmt.Printf("sub goroutine get value from parent goroutine, val=%+v\n", data)
59 | // }
60 | // }(ctx)
61 |
62 | // time.Sleep(1 * time.Second)
63 |
64 | // ctx, cancel := context.WithTimeout(context.Background(), 1*time.Millisecond)
65 | // defer cancel()
66 | // select {
67 | // case <-time.After(1 * time.Second):
68 | // fmt.Println("overslept")
69 | // case <-ctx.Done():
70 | // fmt.Println(ctx.Err())
71 | // }
72 |
73 | // gen := func() <-chan int {
74 | // dst := make(chan int)
75 | // go func() {
76 | // var n int
77 | // for {
78 | // dst <- n
79 | // n++
80 | // }
81 | // }()
82 | // return dst
83 | // }
84 | // for n := range gen() {
85 | // fmt.Println(n)
86 | // if n == 5 {
87 | // break
88 | // }
89 | // }
90 |
91 | gen := func(ctx context.Context) <-chan int {
92 | dst := make(chan int)
93 | go func() {
94 | var n int
95 | for {
96 | select {
97 | case <-ctx.Done():
98 | return
99 | case dst <- n:
100 | n++
101 | }
102 | }
103 | }()
104 | return dst
105 | }
106 | ctx, cancel := context.WithCancel(context.Background())
107 | defer cancel()
108 | for n := range gen(ctx) {
109 | fmt.Println(n)
110 | if n == 5 {
111 | cancel()
112 | break
113 | }
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/lesson53/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | // type User struct {
6 | // Id int
7 | // Name string
8 | // }
9 | //
10 | // type option func(*User)
11 | //
12 | // func (u *User) Option(opts ...option) {
13 | // for _, opt := range opts {
14 | // opt(u)
15 | // }
16 | // }
17 | //
18 | // func WithId(id int) option {
19 | // return func(u *User) {
20 | // u.Id = id
21 | // }
22 | // }
23 | //
24 | // func WithName(name string) option {
25 | // return func(u *User) {
26 | // u.Name = name
27 | // }
28 | // }
29 | //
30 | // func main() {
31 | // u1 := &User{}
32 | // u1.Option(WithId(1))
33 | // fmt.Printf("%+v\n", u1)
34 | //
35 | // u2 := &User{}
36 | // u2.Option(WithId(1), WithName("frank"))
37 | // fmt.Printf("%+v\n", u2)
38 | // }
39 |
40 | // type User struct {
41 | // Id int
42 | // Name string
43 | // }
44 | //
45 | // type option func(*User) interface{}
46 | //
47 | // func (u *User) Option(opts ...option) (id interface{}) {
48 | // for _, opt := range opts {
49 | // id = opt(u)
50 | // }
51 | // return id
52 | // }
53 | //
54 | // func WithId(id int) option {
55 | // return func(u *User) interface{} {
56 | // prevId := u.Id
57 | // u.Id = id
58 | // return prevId
59 | // }
60 | // }
61 | //
62 | // func main() {
63 | // u1 := &User{Id: 1}
64 | // id := u1.Option(WithId(2))
65 | // fmt.Println(id.(int))
66 | // fmt.Printf("%+v\n", u1)
67 | // }
68 |
69 | // type User struct {
70 | // Id int
71 | // Name string
72 | // }
73 | //
74 | // type option func(*User) option
75 | //
76 | // func (u *User) Option(opts ...option) (prev option) {
77 | // for _, opt := range opts {
78 | // prev = opt(u)
79 | // }
80 | // return prev
81 | // }
82 | //
83 | // func WithId(id int) option {
84 | // return func(u *User) option {
85 | // prevId := u.Id
86 | // u.Id = id
87 | // return WithId(prevId)
88 | // }
89 | // }
90 | //
91 | // func main() {
92 | // u1 := &User{Id: 1}
93 | // prev := u1.Option(WithId(2))
94 | // fmt.Printf("%+v\n", u1)
95 | // u1.Option(prev)
96 | // fmt.Printf("%+v\n", u1)
97 | // }
98 |
99 | type User struct {
100 | Id int
101 | Name string
102 | Email string
103 | }
104 |
105 | type option func(*User)
106 |
107 | func WithId(id int) option {
108 | return func(u *User) {
109 | u.Id = id
110 | }
111 | }
112 |
113 | func WithName(name string) option {
114 | return func(u *User) {
115 | u.Name = name
116 | }
117 | }
118 |
119 | func WithEmail(email string) option {
120 | return func(u *User) {
121 | u.Email = email
122 | }
123 | }
124 |
125 | func NewUser(opts ...option) *User {
126 | const (
127 | defaultId = -1
128 | defaultName = "guest"
129 | defaultEmail = "undefined"
130 | )
131 | u := &User{
132 | Id: defaultId,
133 | Name: defaultName,
134 | Email: defaultEmail,
135 | }
136 |
137 | for _, opt := range opts {
138 | opt(u)
139 | }
140 | return u
141 | }
142 |
143 | func main() {
144 | u1 := NewUser(WithName("frank"), WithId(1000000001))
145 | fmt.Printf("%+v\n", u1)
146 | u2 := NewUser(WithEmail("gopher@88.com"))
147 | fmt.Printf("%+v\n", u2)
148 | u3 := NewUser()
149 | fmt.Printf("%+v\n", u3)
150 | }
151 |
--------------------------------------------------------------------------------
/lesson54/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/weirubo/learn_go/lesson54
2 |
3 | go 1.19
4 |
--------------------------------------------------------------------------------
/lesson54/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | //fmt.Println(Min(2, 3))
7 | //fmt.Println(Min(2.2, 3.3))
8 | //fmt.Println(MinFloat64(2.2, 3.3))
9 | //fmt.Println(GMin(2, 3))
10 | //fmt.Println(GMin(2.2, 3.3))
11 | //fmt.Println(GMin[int](2, 3))
12 | //fmt.Println(GMin[float64](2.2, 3.3))
13 |
14 | //x, y := 11, 2
15 | //x, y := 2.2, 3.3
16 | //res := MinAny(x, y)
17 | //fmt.Println(res)
18 |
19 | //salary := &MinSalary[int]{
20 | // salary: 1000,
21 | //}
22 | //salary := &MinSalary[float64]{
23 | // salary: 1000.88,
24 | //}
25 | //salary := &MinSalary{
26 | // salary: 1000,
27 | //}
28 | //fmt.Printf("%+v\n", salary)
29 |
30 | s := &Salary[int]{}
31 | x, y := 2, 3
32 | fmt.Println(s.Min(x, y))
33 | }
34 |
35 | func Min(x, y int) int {
36 | if x < y {
37 | return x
38 | }
39 | return y
40 | }
41 |
42 | func MinFloat64(x, y float64) float64 {
43 | if x < y {
44 | return x
45 | }
46 | return y
47 | }
48 |
49 | func GMin[T int | float64](x, y T) T {
50 | if x < y {
51 | return x
52 | }
53 | return y
54 | }
55 |
56 | // 泛型函数
57 | //func GMin[T Ordered](x, y T) T {
58 | // if x < y {
59 | // return x
60 | // }
61 | // return y
62 | //}
63 |
64 | // 泛型类型
65 | type Ordered interface {
66 | ~int | ~float64
67 | }
68 |
69 | func MinAny(x, y interface{}) interface{} {
70 | if x, ok := x.(int); ok {
71 | if y, ok := y.(int); ok {
72 | if x < y {
73 | return x
74 | }
75 | }
76 | }
77 | if x, ok := x.(float64); ok {
78 | if y, ok := y.(float64); ok {
79 | if x < y {
80 | return x
81 | }
82 | }
83 | }
84 | return y
85 | }
86 |
87 | type MinSalary[T int | float64] struct {
88 | salary T
89 | }
90 |
91 | type Salary[T int | float64] struct {
92 | money T
93 | }
94 |
95 | func (s *Salary[T]) Min(x, y T) T {
96 | if x < y {
97 | return x
98 | }
99 | return y
100 | }
101 |
102 | //func (s *Salary[T]) Min[T1 int](x, y T) T {
103 | // if x < y {
104 | // return x
105 | // }
106 | // return y
107 | //}
108 |
--------------------------------------------------------------------------------
/lesson55/workspace/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # 默认忽略的文件
2 | /shelf/
3 | /workspace.xml
4 | # 基于编辑器的 HTTP 客户端请求
5 | /httpRequests/
6 | # Datasource local storage ignored files
7 | /dataSources/
8 | /dataSources.local.xml
9 |
--------------------------------------------------------------------------------
/lesson55/workspace/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/lesson55/workspace/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/lesson55/workspace/go.work:
--------------------------------------------------------------------------------
1 | go 1.19
2 |
3 | use (
4 | ./hello
5 | ./hello/example
6 | )
7 |
--------------------------------------------------------------------------------
/lesson55/workspace/go.work.sum:
--------------------------------------------------------------------------------
1 | github.com/yuin/goldmark v1.2.1 h1:ruQGxdhGHe7FWOJPT0mKs5+pD2Xs1Bm/kdGlHO04FmM=
2 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
3 | golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI=
4 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck=
5 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
6 | golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
7 |
--------------------------------------------------------------------------------
/lesson55/workspace/hello/example/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/lesson55/workspace/hello/example/README.md:
--------------------------------------------------------------------------------
1 | # Go example projects
2 |
3 | [](https://pkg.go.dev/golang.org/x/example)
4 |
5 | This repository contains a collection of Go programs and libraries that
6 | demonstrate the language, standard libraries, and tools.
7 |
8 | ## Clone the project
9 |
10 | ```
11 | $ git clone https://go.googlesource.com/example
12 | $ cd example
13 | ```
14 | https://go.googlesource.com/example is the canonical Git repository.
15 | It is mirrored at https://github.com/golang/example.
16 | ## [hello](hello/) and [stringutil](stringutil/)
17 |
18 | ```
19 | $ cd hello
20 | $ go build
21 | ```
22 | A trivial "Hello, world" program that uses a stringutil package.
23 |
24 | Command [hello](hello/) covers:
25 |
26 | * The basic form of an executable command
27 | * Importing packages (from the standard library and the local repository)
28 | * Printing strings ([fmt](//golang.org/pkg/fmt/))
29 |
30 | Library [stringutil](stringutil/) covers:
31 |
32 | * The basic form of a library
33 | * Conversion between string and []rune
34 | * Table-driven unit tests ([testing](//golang.org/pkg/testing/))
35 |
36 | ## [outyet](outyet/)
37 |
38 | ```
39 | $ cd outyet
40 | $ go build
41 | ```
42 | A web server that answers the question: "Is Go 1.x out yet?"
43 |
44 | Topics covered:
45 |
46 | * Command-line flags ([flag](//golang.org/pkg/flag/))
47 | * Web servers ([net/http](//golang.org/pkg/net/http/))
48 | * HTML Templates ([html/template](//golang.org/pkg/html/template/))
49 | * Logging ([log](//golang.org/pkg/log/))
50 | * Long-running background processes
51 | * Synchronizing data access between goroutines ([sync](//golang.org/pkg/sync/))
52 | * Exporting server state for monitoring ([expvar](//golang.org/pkg/expvar/))
53 | * Unit and integration tests ([testing](//golang.org/pkg/testing/))
54 | * Dependency injection
55 | * Time ([time](//golang.org/pkg/time/))
56 |
57 | ## [appengine-hello](appengine-hello/)
58 |
59 | A trivial "Hello, world" App Engine application intended to be used as the
60 | starting point for your own code. Please see
61 | [Google App Engine SDK for Go](https://cloud.google.com/appengine/downloads#Google_App_Engine_SDK_for_Go)
62 | and [Quickstart for Go in the App Engine Standard Environment](https://cloud.google.com/appengine/docs/standard/go/quickstart).
63 |
64 | ## [gotypes](gotypes/)
65 |
66 | The `go/types` package is a type-checker for Go programs. It is one of the most
67 | complex packages in Go's standard library, so we have provided this tutorial to
68 | help you find your bearings. It comes with several example programs that you
69 | can obtain using `go get` and play with as you learn to build tools that analyze
70 | or manipulate Go programs.
71 |
72 | ## [template](template/)
73 |
74 | A trivial web server that demonstrates the use of the
75 | [`template` package](https://golang.org/pkg/text/template/)'s `block` feature.
76 |
--------------------------------------------------------------------------------
/lesson55/workspace/hello/example/appengine-hello/README.md:
--------------------------------------------------------------------------------
1 | This code is a starting point for your Google App Engine application in
2 | Go.
3 |
4 | To run the application locally you need the install the [Go Cloud
5 | SDK](https://cloud.google.com/appengine/docs/go/#Go_tools) and execute the next
6 | command from the directory containing this file:
7 |
8 | $ goapp serve app.yaml
9 |
10 | To deploy the application you have to first create an App Engine project
11 | and use it as the application file in all the yaml files.
12 |
--------------------------------------------------------------------------------
/lesson55/workspace/hello/example/appengine-hello/app.go:
--------------------------------------------------------------------------------
1 | // Copyright 2015 Google Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | // Package hello is a simple App Engine application that replies to requests
16 | // on /hello with a welcoming message.
17 | package hello
18 |
19 | import (
20 | "fmt"
21 | "net/http"
22 | )
23 |
24 | // init is run before the application starts serving.
25 | func init() {
26 | // Handle all requests with path /hello with the helloHandler function.
27 | http.HandleFunc("/hello", helloHandler)
28 | }
29 |
30 | func helloHandler(w http.ResponseWriter, r *http.Request) {
31 | fmt.Fprintln(w, "Hello from the Go app")
32 | }
33 |
--------------------------------------------------------------------------------
/lesson55/workspace/hello/example/appengine-hello/app.yaml:
--------------------------------------------------------------------------------
1 | # Copyright 2015 Google Inc. All rights reserved.
2 | # Licensed under the Apache License, Version 2.0 (the "License");
3 | # you may not use this file except in compliance with the License.
4 | # You may obtain a copy of the License at
5 | # http:#www.apache.org/licenses/LICENSE-2.0
6 |
7 | # Unless required by applicable law or agreed to writing, software distributed
8 | # under the License is distributed on a "AS IS" BASIS, WITHOUT WARRANTIES OR
9 | # CONDITIONS OF ANY KIND, either express or implied.
10 |
11 | # See the License for the specific language governing permissions and
12 | # limitations under the License.
13 |
14 | application: you-application-id
15 | version: 1
16 | runtime: go
17 | api_version: go1
18 |
19 | handlers:
20 | - url: /hello
21 | script: _go_app
22 |
23 | - url: /favicon.ico
24 | static_files: static/favicon.ico
25 | upload: static/favicon.ico
26 |
27 | - url: /
28 | static_files: static/index.html
29 | upload: static/index.html
30 |
31 | - url: /
32 | static_dir: static
33 |
--------------------------------------------------------------------------------
/lesson55/workspace/hello/example/appengine-hello/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weirubo/learn_go/22a2ade9f18c9205cb088b4415228f4c4864fc7d/lesson55/workspace/hello/example/appengine-hello/static/favicon.ico
--------------------------------------------------------------------------------
/lesson55/workspace/hello/example/appengine-hello/static/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
20 |
21 |
22 | Hello, world
23 |
24 |
25 |
26 |
27 |
28 | Hello, world
29 |
30 |
31 | Click on the button to fetch the message.
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/lesson55/workspace/hello/example/appengine-hello/static/script.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2015 Google Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | "use strict";
18 |
19 | function fetchMessage() {
20 | var xmlHttp = new XMLHttpRequest();
21 | xmlHttp.open("GET", "/hello", false);
22 | xmlHttp.send(null);
23 | document.getElementById("message").innerHTML = xmlHttp.responseText;
24 | }
--------------------------------------------------------------------------------
/lesson55/workspace/hello/example/appengine-hello/static/style.css:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2015 Google Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | h1 {
18 | text-align: center;
19 | }
--------------------------------------------------------------------------------
/lesson55/workspace/hello/example/go.mod:
--------------------------------------------------------------------------------
1 | module golang.org/x/example
2 |
3 | go 1.15
4 |
5 | require golang.org/x/tools v0.0.0-20210112183307-1e6ecd4bf1b0
6 |
--------------------------------------------------------------------------------
/lesson55/workspace/hello/example/go.sum:
--------------------------------------------------------------------------------
1 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
2 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
3 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
4 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
5 | golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
6 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
7 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
8 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
9 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
10 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
11 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
12 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
13 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
14 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
15 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
16 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
17 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
18 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
19 | golang.org/x/tools v0.0.0-20210112183307-1e6ecd4bf1b0 h1:iZhiQWrjyEuXG495d9MXkcmhrlxbQyGp0uNBY+YBZDk=
20 | golang.org/x/tools v0.0.0-20210112183307-1e6ecd4bf1b0/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
21 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
22 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
23 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
24 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
25 |
--------------------------------------------------------------------------------
/lesson55/workspace/hello/example/gotypes/Makefile:
--------------------------------------------------------------------------------
1 |
2 | all: README.md
3 | go build ./...
4 |
5 | README.md: go-types.md weave.go $(wildcard */*.go)
6 | go run weave.go go-types.md >README.md
7 |
8 | # This is for previewing using github.
9 | # $HOME/markdown must be a github client.
10 | test: README.md
11 | cp README.md $$HOME/markdown/
12 | (cd $$HOME/markdown/ && git commit -m . README.md && git push)
13 |
14 |
--------------------------------------------------------------------------------
/lesson55/workspace/hello/example/gotypes/defsuses/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "go/ast"
6 | "go/importer"
7 | "go/parser"
8 | "go/token"
9 | "go/types"
10 | "log"
11 | )
12 |
13 | const hello = `package main
14 |
15 | import "fmt"
16 |
17 | func main() {
18 | fmt.Println("Hello, world")
19 | }
20 | `
21 |
22 | // !+
23 | func PrintDefsUses(fset *token.FileSet, files ...*ast.File) error {
24 | conf := types.Config{Importer: importer.Default()}
25 | info := &types.Info{
26 | Defs: make(map[*ast.Ident]types.Object),
27 | Uses: make(map[*ast.Ident]types.Object),
28 | }
29 | _, err := conf.Check("hello", fset, files, info)
30 | if err != nil {
31 | return err // type error
32 | }
33 |
34 | for id, obj := range info.Defs {
35 | fmt.Printf("%s: %q defines %v\n",
36 | fset.Position(id.Pos()), id.Name, obj)
37 | }
38 | for id, obj := range info.Uses {
39 | fmt.Printf("%s: %q uses %v\n",
40 | fset.Position(id.Pos()), id.Name, obj)
41 | }
42 | return nil
43 | }
44 |
45 | //!-
46 |
47 | func main() {
48 | // Parse one file.
49 | fset := token.NewFileSet()
50 | f, err := parser.ParseFile(fset, "hello.go", hello, 0)
51 | if err != nil {
52 | log.Fatal(err) // parse error
53 | }
54 | if err := PrintDefsUses(fset, f); err != nil {
55 | log.Fatal(err) // type error
56 | }
57 | }
58 |
59 | /*
60 | //!+output
61 | $ go build golang.org/x/example/gotypes/defsuses
62 | $ ./defsuses
63 | hello.go:1:9: "main" defines
64 | hello.go:5:6: "main" defines func hello.main()
65 | hello.go:6:9: "fmt" uses package fmt
66 | hello.go:6:13: "Println" uses func fmt.Println(a ...interface{}) (n int, err error)
67 | //!-output
68 | */
69 |
--------------------------------------------------------------------------------
/lesson55/workspace/hello/example/gotypes/doc/main.go:
--------------------------------------------------------------------------------
1 | // The doc command prints the doc comment of a package-level object.
2 | package main
3 |
4 | import (
5 | "fmt"
6 | "go/ast"
7 | "go/parser"
8 | "log"
9 | "os"
10 |
11 | // TODO: these will use std go/types after Feb 2016
12 | "golang.org/x/tools/go/loader"
13 | "golang.org/x/tools/go/types/typeutil"
14 | )
15 |
16 | func main() {
17 | if len(os.Args) != 3 {
18 | log.Fatal("Usage: doc