├── .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 | ![Golang 语言开发栈](https://github.com/weirubo/learn_go/blob/master/ebook/qrcode.png) 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 | ![](https://github.com/weirubo/learn_go/blob/master/ebook/640.png) 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 | 62 |
63 | not tracked 64 | 65 | not covered 66 | covered 67 | 68 |
69 |
70 |
71 | 72 | 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 | [![Go Reference](https://pkg.go.dev/badge/golang.org/x/example.svg)](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 ") 19 | } 20 | //!+part1 21 | pkgpath, name := os.Args[1], os.Args[2] 22 | 23 | // The loader loads a complete Go program from source code. 24 | conf := loader.Config{ParserMode: parser.ParseComments} 25 | conf.Import(pkgpath) 26 | lprog, err := conf.Load() 27 | if err != nil { 28 | log.Fatal(err) // load error 29 | } 30 | 31 | // Find the package and package-level object. 32 | pkg := lprog.Package(pkgpath).Pkg 33 | obj := pkg.Scope().Lookup(name) 34 | if obj == nil { 35 | log.Fatalf("%s.%s not found", pkg.Path(), name) 36 | } 37 | //!-part1 38 | //!+part2 39 | 40 | // Print the object and its methods (incl. location of definition). 41 | fmt.Println(obj) 42 | for _, sel := range typeutil.IntuitiveMethodSet(obj.Type(), nil) { 43 | fmt.Printf("%s: %s\n", lprog.Fset.Position(sel.Obj().Pos()), sel) 44 | } 45 | 46 | // Find the path from the root of the AST to the object's position. 47 | // Walk up to the enclosing ast.Decl for the doc comment. 48 | _, path, _ := lprog.PathEnclosingInterval(obj.Pos(), obj.Pos()) 49 | for _, n := range path { 50 | switch n := n.(type) { 51 | case *ast.GenDecl: 52 | fmt.Println("\n", n.Doc.Text()) 53 | return 54 | case *ast.FuncDecl: 55 | fmt.Println("\n", n.Doc.Text()) 56 | return 57 | } 58 | } 59 | //!-part2 60 | } 61 | 62 | /* 63 | //!+output 64 | $ ./doc net/http File 65 | type net/http.File interface{Readdir(count int) ([]os.FileInfo, error); Seek(offset int64, whence int) (int64, error); Stat() (os.FileInfo, error); io.Closer; io.Reader} 66 | /go/src/io/io.go:92:2: method (net/http.File) Close() error 67 | /go/src/io/io.go:71:2: method (net/http.File) Read(p []byte) (n int, err error) 68 | /go/src/net/http/fs.go:65:2: method (net/http.File) Readdir(count int) ([]os.FileInfo, error) 69 | /go/src/net/http/fs.go:66:2: method (net/http.File) Seek(offset int64, whence int) (int64, error) 70 | /go/src/net/http/fs.go:67:2: method (net/http.File) Stat() (os.FileInfo, error) 71 | 72 | A File is returned by a FileSystem's Open method and can be 73 | served by the FileServer implementation. 74 | 75 | The methods should behave the same as those on an *os.File. 76 | //!-output 77 | */ 78 | -------------------------------------------------------------------------------- /lesson55/workspace/hello/example/gotypes/hello/hello.go: -------------------------------------------------------------------------------- 1 | // !+ 2 | package main 3 | 4 | import "fmt" 5 | 6 | func main() { 7 | fmt.Println("Hello, 世界") 8 | } 9 | 10 | //!- 11 | -------------------------------------------------------------------------------- /lesson55/workspace/hello/example/gotypes/hugeparam/main.go: -------------------------------------------------------------------------------- 1 | // The hugeparam command identifies by-value parameters that are larger than n bytes. 2 | // 3 | // Example: 4 | // 5 | // $ ./hugeparams encoding/xml 6 | package main 7 | 8 | import ( 9 | "flag" 10 | "fmt" 11 | "go/ast" 12 | "go/token" 13 | "go/types" 14 | "log" 15 | 16 | "golang.org/x/tools/go/loader" 17 | ) 18 | 19 | // !+ 20 | var bytesFlag = flag.Int("bytes", 48, "maximum parameter size in bytes") 21 | 22 | var sizeof = (&types.StdSizes{8, 8}).Sizeof // the sizeof function 23 | 24 | func PrintHugeParams(fset *token.FileSet, info *types.Info, files []*ast.File) { 25 | checkTuple := func(descr string, tuple *types.Tuple) { 26 | for i := 0; i < tuple.Len(); i++ { 27 | v := tuple.At(i) 28 | if sz := sizeof(v.Type()); sz > int64(*bytesFlag) { 29 | fmt.Printf("%s: %q %s: %s = %d bytes\n", 30 | fset.Position(v.Pos()), 31 | v.Name(), descr, v.Type(), sz) 32 | } 33 | } 34 | } 35 | checkSig := func(sig *types.Signature) { 36 | checkTuple("parameter", sig.Params()) 37 | checkTuple("result", sig.Results()) 38 | } 39 | for _, file := range files { 40 | ast.Inspect(file, func(n ast.Node) bool { 41 | switch n := n.(type) { 42 | case *ast.FuncDecl: 43 | checkSig(info.Defs[n.Name].Type().(*types.Signature)) 44 | case *ast.FuncLit: 45 | checkSig(info.Types[n.Type].Type.(*types.Signature)) 46 | } 47 | return true 48 | }) 49 | } 50 | } 51 | 52 | //!- 53 | 54 | func main() { 55 | flag.Parse() 56 | 57 | // The loader loads a complete Go program from source code. 58 | var conf loader.Config 59 | _, err := conf.FromArgs(flag.Args(), false) 60 | if err != nil { 61 | log.Fatal(err) // command syntax error 62 | } 63 | lprog, err := conf.Load() 64 | if err != nil { 65 | log.Fatal(err) // load error 66 | } 67 | 68 | for _, info := range lprog.InitialPackages() { 69 | PrintHugeParams(lprog.Fset, &info.Info, info.Files) 70 | } 71 | } 72 | 73 | /* 74 | //!+output 75 | % ./hugeparam encoding/xml 76 | /go/src/encoding/xml/marshal.go:167:50: "start" parameter: encoding/xml.StartElement = 56 bytes 77 | /go/src/encoding/xml/marshal.go:734:97: "" result: encoding/xml.StartElement = 56 bytes 78 | /go/src/encoding/xml/marshal.go:761:51: "start" parameter: encoding/xml.StartElement = 56 bytes 79 | /go/src/encoding/xml/marshal.go:781:68: "start" parameter: encoding/xml.StartElement = 56 bytes 80 | /go/src/encoding/xml/xml.go:72:30: "" result: encoding/xml.StartElement = 56 bytes 81 | //!-output 82 | */ 83 | -------------------------------------------------------------------------------- /lesson55/workspace/hello/example/gotypes/implements/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 | // !+input 14 | const input = `package main 15 | 16 | type A struct{} 17 | func (*A) f() 18 | 19 | type B int 20 | func (B) f() 21 | func (*B) g() 22 | 23 | type I interface { f() } 24 | type J interface { g() } 25 | ` 26 | 27 | //!-input 28 | 29 | func main() { 30 | // Parse one file. 31 | fset := token.NewFileSet() 32 | f, err := parser.ParseFile(fset, "input.go", input, 0) 33 | if err != nil { 34 | log.Fatal(err) // parse error 35 | } 36 | conf := types.Config{Importer: importer.Default()} 37 | pkg, err := conf.Check("hello", fset, []*ast.File{f}, nil) 38 | if err != nil { 39 | log.Fatal(err) // type error 40 | } 41 | 42 | //!+implements 43 | // Find all named types at package level. 44 | var allNamed []*types.Named 45 | for _, name := range pkg.Scope().Names() { 46 | if obj, ok := pkg.Scope().Lookup(name).(*types.TypeName); ok { 47 | allNamed = append(allNamed, obj.Type().(*types.Named)) 48 | } 49 | } 50 | 51 | // Test assignability of all distinct pairs of 52 | // named types (T, U) where U is an interface. 53 | for _, T := range allNamed { 54 | for _, U := range allNamed { 55 | if T == U || !types.IsInterface(U) { 56 | continue 57 | } 58 | if types.AssignableTo(T, U) { 59 | fmt.Printf("%s satisfies %s\n", T, U) 60 | } else if !types.IsInterface(T) && 61 | types.AssignableTo(types.NewPointer(T), U) { 62 | fmt.Printf("%s satisfies %s\n", types.NewPointer(T), U) 63 | } 64 | } 65 | } 66 | //!-implements 67 | } 68 | 69 | /* 70 | //!+output 71 | $ go build golang.org/x/example/gotypes/implements 72 | $ ./implements 73 | *hello.A satisfies hello.I 74 | hello.B satisfies hello.I 75 | *hello.B satisfies hello.J 76 | //!-output 77 | */ 78 | -------------------------------------------------------------------------------- /lesson55/workspace/hello/example/gotypes/lookup/lookup.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 | "strings" 12 | ) 13 | 14 | // !+input 15 | const hello = ` 16 | package main 17 | 18 | import "fmt" 19 | 20 | // append 21 | func main() { 22 | // fmt 23 | fmt.Println("Hello, world") 24 | // main 25 | main, x := 1, 2 26 | // main 27 | print(main, x) 28 | // x 29 | } 30 | // x 31 | ` 32 | 33 | //!-input 34 | 35 | // !+main 36 | func main() { 37 | fset := token.NewFileSet() 38 | f, err := parser.ParseFile(fset, "hello.go", hello, parser.ParseComments) 39 | if err != nil { 40 | log.Fatal(err) // parse error 41 | } 42 | 43 | conf := types.Config{Importer: importer.Default()} 44 | pkg, err := conf.Check("cmd/hello", fset, []*ast.File{f}, nil) 45 | if err != nil { 46 | log.Fatal(err) // type error 47 | } 48 | 49 | // Each comment contains a name. 50 | // Look up that name in the innermost scope enclosing the comment. 51 | for _, comment := range f.Comments { 52 | pos := comment.Pos() 53 | name := strings.TrimSpace(comment.Text()) 54 | fmt.Printf("At %s,\t%q = ", fset.Position(pos), name) 55 | inner := pkg.Scope().Innermost(pos) 56 | if _, obj := inner.LookupParent(name, pos); obj != nil { 57 | fmt.Println(obj) 58 | } else { 59 | fmt.Println("not found") 60 | } 61 | } 62 | } 63 | 64 | //!-main 65 | 66 | /* 67 | //!+output 68 | $ go build golang.org/x/example/gotypes/lookup 69 | $ ./lookup 70 | At hello.go:6:1, "append" = builtin append 71 | At hello.go:8:9, "fmt" = package fmt 72 | At hello.go:10:9, "main" = func cmd/hello.main() 73 | At hello.go:12:9, "main" = var main int 74 | At hello.go:14:9, "x" = var x int 75 | At hello.go:16:1, "x" = not found 76 | //!-output 77 | */ 78 | -------------------------------------------------------------------------------- /lesson55/workspace/hello/example/gotypes/nilfunc/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 | // !+input 14 | const input = `package main 15 | 16 | import "bytes" 17 | 18 | func main() { 19 | var buf bytes.Buffer 20 | if buf.Bytes == nil && bytes.Repeat != nil && main == nil { 21 | // ... 22 | } 23 | } 24 | ` 25 | 26 | //!-input 27 | 28 | var fset = token.NewFileSet() 29 | 30 | func main() { 31 | f, err := parser.ParseFile(fset, "input.go", input, 0) 32 | if err != nil { 33 | log.Fatal(err) // parse error 34 | } 35 | conf := types.Config{Importer: importer.Default()} 36 | info := &types.Info{ 37 | Defs: make(map[*ast.Ident]types.Object), 38 | Uses: make(map[*ast.Ident]types.Object), 39 | Types: make(map[ast.Expr]types.TypeAndValue), 40 | } 41 | if _, err = conf.Check("cmd/hello", fset, []*ast.File{f}, info); err != nil { 42 | log.Fatal(err) // type error 43 | } 44 | 45 | ast.Inspect(f, func(n ast.Node) bool { 46 | if n != nil { 47 | CheckNilFuncComparison(info, n) 48 | } 49 | return true 50 | }) 51 | } 52 | 53 | // !+ 54 | // CheckNilFuncComparison reports unintended comparisons 55 | // of functions against nil, e.g., "if x.Method == nil {". 56 | func CheckNilFuncComparison(info *types.Info, n ast.Node) { 57 | e, ok := n.(*ast.BinaryExpr) 58 | if !ok { 59 | return // not a binary operation 60 | } 61 | if e.Op != token.EQL && e.Op != token.NEQ { 62 | return // not a comparison 63 | } 64 | 65 | // If this is a comparison against nil, find the other operand. 66 | var other ast.Expr 67 | if info.Types[e.X].IsNil() { 68 | other = e.Y 69 | } else if info.Types[e.Y].IsNil() { 70 | other = e.X 71 | } else { 72 | return // not a comparison against nil 73 | } 74 | 75 | // Find the object. 76 | var obj types.Object 77 | switch v := other.(type) { 78 | case *ast.Ident: 79 | obj = info.Uses[v] 80 | case *ast.SelectorExpr: 81 | obj = info.Uses[v.Sel] 82 | default: 83 | return // not an identifier or selection 84 | } 85 | 86 | if _, ok := obj.(*types.Func); !ok { 87 | return // not a function or method 88 | } 89 | 90 | fmt.Printf("%s: comparison of function %v %v nil is always %v\n", 91 | fset.Position(e.Pos()), obj.Name(), e.Op, e.Op == token.NEQ) 92 | } 93 | 94 | //!- 95 | 96 | /* 97 | //!+output 98 | $ go build golang.org/x/example/gotypes/nilfunc 99 | $ ./nilfunc 100 | input.go:7:5: comparison of function Bytes == nil is always false 101 | input.go:7:25: comparison of function Repeat != nil is always true 102 | input.go:7:48: comparison of function main == nil is always false 103 | //!-output 104 | */ 105 | -------------------------------------------------------------------------------- /lesson55/workspace/hello/example/gotypes/pkginfo/main.go: -------------------------------------------------------------------------------- 1 | // !+ 2 | package main 3 | 4 | import ( 5 | "fmt" 6 | "go/ast" 7 | "go/importer" 8 | "go/parser" 9 | "go/token" 10 | "go/types" 11 | "log" 12 | ) 13 | 14 | const hello = `package main 15 | 16 | import "fmt" 17 | 18 | func main() { 19 | fmt.Println("Hello, world") 20 | }` 21 | 22 | func main() { 23 | fset := token.NewFileSet() 24 | 25 | // Parse the input string, []byte, or io.Reader, 26 | // recording position information in fset. 27 | // ParseFile returns an *ast.File, a syntax tree. 28 | f, err := parser.ParseFile(fset, "hello.go", hello, 0) 29 | if err != nil { 30 | log.Fatal(err) // parse error 31 | } 32 | 33 | // A Config controls various options of the type checker. 34 | // The defaults work fine except for one setting: 35 | // we must specify how to deal with imports. 36 | conf := types.Config{Importer: importer.Default()} 37 | 38 | // Type-check the package containing only file f. 39 | // Check returns a *types.Package. 40 | pkg, err := conf.Check("cmd/hello", fset, []*ast.File{f}, nil) 41 | if err != nil { 42 | log.Fatal(err) // type error 43 | } 44 | 45 | fmt.Printf("Package %q\n", pkg.Path()) 46 | fmt.Printf("Name: %s\n", pkg.Name()) 47 | fmt.Printf("Imports: %s\n", pkg.Imports()) 48 | fmt.Printf("Scope: %s\n", pkg.Scope()) 49 | } 50 | 51 | //!- 52 | 53 | /* 54 | //!+output 55 | $ go build golang.org/x/example/gotypes/pkginfo 56 | $ ./pkginfo 57 | Package "cmd/hello" 58 | Name: main 59 | Imports: [package fmt ("fmt")] 60 | Scope: package "cmd/hello" scope 0x820533590 { 61 | . func cmd/hello.main() 62 | } 63 | //!-output 64 | */ 65 | -------------------------------------------------------------------------------- /lesson55/workspace/hello/example/gotypes/skeleton/main.go: -------------------------------------------------------------------------------- 1 | // The skeleton command prints the boilerplate for a concrete type 2 | // that implements the specified interface type. 3 | // 4 | // Example: 5 | // 6 | // $ ./skeleton io ReadWriteCloser buffer 7 | // // *buffer implements io.ReadWriteCloser. 8 | // type buffer struct{ /* ... */ } 9 | // func (b *buffer) Close() error { panic("unimplemented") } 10 | // func (b *buffer) Read(p []byte) (n int, err error) { panic("unimplemented") } 11 | // func (b *buffer) Write(p []byte) (n int, err error) { panic("unimplemented") } 12 | package main 13 | 14 | import ( 15 | "fmt" 16 | "go/types" 17 | "log" 18 | "os" 19 | "strings" 20 | "unicode" 21 | "unicode/utf8" 22 | 23 | "golang.org/x/tools/go/loader" 24 | ) 25 | 26 | const usage = "Usage: skeleton " 27 | 28 | // !+ 29 | func PrintSkeleton(pkg *types.Package, ifacename, concname string) error { 30 | obj := pkg.Scope().Lookup(ifacename) 31 | if obj == nil { 32 | return fmt.Errorf("%s.%s not found", pkg.Path(), ifacename) 33 | } 34 | if _, ok := obj.(*types.TypeName); !ok { 35 | return fmt.Errorf("%v is not a named type", obj) 36 | } 37 | iface, ok := obj.Type().Underlying().(*types.Interface) 38 | if !ok { 39 | return fmt.Errorf("type %v is a %T, not an interface", 40 | obj, obj.Type().Underlying()) 41 | } 42 | // Use first letter of type name as receiver parameter. 43 | if !isValidIdentifier(concname) { 44 | return fmt.Errorf("invalid concrete type name: %q", concname) 45 | } 46 | r, _ := utf8.DecodeRuneInString(concname) 47 | 48 | fmt.Printf("// *%s implements %s.%s.\n", concname, pkg.Path(), ifacename) 49 | fmt.Printf("type %s struct{}\n", concname) 50 | mset := types.NewMethodSet(iface) 51 | for i := 0; i < mset.Len(); i++ { 52 | meth := mset.At(i).Obj() 53 | sig := types.TypeString(meth.Type(), (*types.Package).Name) 54 | fmt.Printf("func (%c *%s) %s%s {\n\tpanic(\"unimplemented\")\n}\n", 55 | r, concname, meth.Name(), 56 | strings.TrimPrefix(sig, "func")) 57 | } 58 | return nil 59 | } 60 | 61 | //!- 62 | 63 | func isValidIdentifier(id string) bool { 64 | for i, r := range id { 65 | if !unicode.IsLetter(r) && 66 | !(i > 0 && unicode.IsDigit(r)) { 67 | return false 68 | } 69 | } 70 | return id != "" 71 | } 72 | 73 | func main() { 74 | if len(os.Args) != 4 { 75 | log.Fatal(usage) 76 | } 77 | pkgpath, ifacename, concname := os.Args[1], os.Args[2], os.Args[3] 78 | 79 | // The loader loads a complete Go program from source code. 80 | var conf loader.Config 81 | conf.Import(pkgpath) 82 | lprog, err := conf.Load() 83 | if err != nil { 84 | log.Fatal(err) // load error 85 | } 86 | pkg := lprog.Package(pkgpath).Pkg 87 | if err := PrintSkeleton(pkg, ifacename, concname); err != nil { 88 | log.Fatal(err) 89 | } 90 | } 91 | 92 | /* 93 | //!+output1 94 | $ ./skeleton io ReadWriteCloser buffer 95 | // *buffer implements io.ReadWriteCloser. 96 | type buffer struct{} 97 | func (b *buffer) Close() error { 98 | panic("unimplemented") 99 | } 100 | func (b *buffer) Read(p []byte) (n int, err error) { 101 | panic("unimplemented") 102 | } 103 | func (b *buffer) Write(p []byte) (n int, err error) { 104 | panic("unimplemented") 105 | } 106 | //!-output1 107 | 108 | //!+output2 109 | $ ./skeleton net/http Handler myHandler 110 | // *myHandler implements net/http.Handler. 111 | type myHandler struct{} 112 | func (m *myHandler) ServeHTTP(http.ResponseWriter, *http.Request) { 113 | panic("unimplemented") 114 | } 115 | //!-output2 116 | */ 117 | -------------------------------------------------------------------------------- /lesson55/workspace/hello/example/gotypes/typeandvalue/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "go/ast" 7 | "go/format" 8 | "go/importer" 9 | "go/parser" 10 | "go/token" 11 | "go/types" 12 | "log" 13 | ) 14 | 15 | // !+input 16 | const input = ` 17 | package main 18 | 19 | var m = make(map[string]int) 20 | 21 | func main() { 22 | v, ok := m["hello, " + "world"] 23 | print(rune(v), ok) 24 | } 25 | ` 26 | 27 | //!-input 28 | 29 | var fset = token.NewFileSet() 30 | 31 | func main() { 32 | f, err := parser.ParseFile(fset, "hello.go", input, 0) 33 | if err != nil { 34 | log.Fatal(err) // parse error 35 | } 36 | 37 | conf := types.Config{Importer: importer.Default()} 38 | info := &types.Info{Types: make(map[ast.Expr]types.TypeAndValue)} 39 | if _, err := conf.Check("cmd/hello", fset, []*ast.File{f}, info); err != nil { 40 | log.Fatal(err) // type error 41 | } 42 | 43 | //!+inspect 44 | // f is a parsed, type-checked *ast.File. 45 | ast.Inspect(f, func(n ast.Node) bool { 46 | if expr, ok := n.(ast.Expr); ok { 47 | if tv, ok := info.Types[expr]; ok { 48 | fmt.Printf("%-24s\tmode: %s\n", nodeString(expr), mode(tv)) 49 | fmt.Printf("\t\t\t\ttype: %v\n", tv.Type) 50 | if tv.Value != nil { 51 | fmt.Printf("\t\t\t\tvalue: %v\n", tv.Value) 52 | } 53 | } 54 | } 55 | return true 56 | }) 57 | //!-inspect 58 | } 59 | 60 | // nodeString formats a syntax tree in the style of gofmt. 61 | func nodeString(n ast.Node) string { 62 | var buf bytes.Buffer 63 | format.Node(&buf, fset, n) 64 | return buf.String() 65 | } 66 | 67 | // mode returns a string describing the mode of an expression. 68 | func mode(tv types.TypeAndValue) string { 69 | s := "" 70 | if tv.IsVoid() { 71 | s += ",void" 72 | } 73 | if tv.IsType() { 74 | s += ",type" 75 | } 76 | if tv.IsBuiltin() { 77 | s += ",builtin" 78 | } 79 | if tv.IsValue() { 80 | s += ",value" 81 | } 82 | if tv.IsNil() { 83 | s += ",nil" 84 | } 85 | if tv.Addressable() { 86 | s += ",addressable" 87 | } 88 | if tv.Assignable() { 89 | s += ",assignable" 90 | } 91 | if tv.HasOk() { 92 | s += ",ok" 93 | } 94 | return s[1:] 95 | } 96 | 97 | /* 98 | //!+output 99 | $ go build golang.org/x/example/gotypes/typeandvalue 100 | $ ./typeandvalue 101 | make(map[string]int) mode: value 102 | type: map[string]int 103 | make mode: builtin 104 | type: func(map[string]int) map[string]int 105 | map[string]int mode: type 106 | type: map[string]int 107 | string mode: type 108 | type: string 109 | int mode: type 110 | type: int 111 | m["hello, "+"world"] mode: value,assignable,ok 112 | type: (int, bool) 113 | m mode: value,addressable,assignable 114 | type: map[string]int 115 | "hello, " + "world" mode: value 116 | type: string 117 | value: "hello, world" 118 | "hello, " mode: value 119 | type: untyped string 120 | value: "hello, " 121 | "world" mode: value 122 | type: untyped string 123 | value: "world" 124 | print(rune(v), ok) mode: void 125 | type: () 126 | print mode: builtin 127 | type: func(rune, bool) 128 | rune(v) mode: value 129 | type: rune 130 | rune mode: type 131 | type: rune 132 | ...more not shown... 133 | //!-output 134 | */ 135 | -------------------------------------------------------------------------------- /lesson55/workspace/hello/example/gotypes/weave.go: -------------------------------------------------------------------------------- 1 | // The weave command is a simple preprocessor for markdown files. 2 | // It builds a table of contents and processes %include directives. 3 | // 4 | // Example usage: 5 | // 6 | // $ go run weave.go go-types.md > README.md 7 | package main 8 | 9 | import ( 10 | "bufio" 11 | "bytes" 12 | "fmt" 13 | "log" 14 | "os" 15 | "path/filepath" 16 | "regexp" 17 | "strings" 18 | ) 19 | 20 | func main() { 21 | log.SetFlags(0) 22 | log.SetPrefix("weave: ") 23 | if len(os.Args) != 2 { 24 | log.Fatal("usage: weave input.md\n") 25 | } 26 | 27 | f, err := os.Open(os.Args[1]) 28 | if err != nil { 29 | log.Fatal(err) 30 | } 31 | defer f.Close() 32 | 33 | fmt.Println("") 34 | 35 | // Pass 1. 36 | var toc []string 37 | in := bufio.NewScanner(f) 38 | for in.Scan() { 39 | line := in.Text() 40 | if line == "" || (line[0] != '#' && line[0] != '%') { 41 | continue 42 | } 43 | line = strings.TrimSpace(line) 44 | if line == "%toc" { 45 | toc = nil 46 | } else if strings.HasPrefix(line, "# ") || strings.HasPrefix(line, "## ") { 47 | words := strings.Fields(line) 48 | depth := len(words[0]) 49 | words = words[1:] 50 | text := strings.Join(words, " ") 51 | for i := range words { 52 | words[i] = strings.ToLower(words[i]) 53 | } 54 | line = fmt.Sprintf("%s1. [%s](#%s)", 55 | strings.Repeat("\t", depth-1), text, strings.Join(words, "-")) 56 | toc = append(toc, line) 57 | } 58 | } 59 | 60 | // Pass 2. 61 | if _, err := f.Seek(0, os.SEEK_SET); err != nil { 62 | log.Fatalf("can't rewind input: %v", err) 63 | } 64 | in = bufio.NewScanner(f) 65 | for in.Scan() { 66 | line := in.Text() 67 | switch { 68 | case strings.HasPrefix(line, "%toc"): // ToC 69 | for _, h := range toc { 70 | fmt.Println(h) 71 | } 72 | case strings.HasPrefix(line, "%include"): 73 | words := strings.Fields(line) 74 | if len(words) < 2 { 75 | log.Fatal(line) 76 | } 77 | filename := words[1] 78 | 79 | // Show caption unless '-' follows. 80 | if len(words) < 4 || words[3] != "-" { 81 | fmt.Printf(" // go get golang.org/x/example/gotypes/%s\n\n", 82 | filepath.Dir(filename)) 83 | } 84 | 85 | section := "" 86 | if len(words) > 2 { 87 | section = words[2] 88 | } 89 | s, err := include(filename, section) 90 | if err != nil { 91 | log.Fatal(err) 92 | } 93 | fmt.Println("```") 94 | fmt.Println(cleanListing(s)) // TODO(adonovan): escape /^```/ in s 95 | fmt.Println("```") 96 | default: 97 | fmt.Println(line) 98 | } 99 | 100 | } 101 | } 102 | 103 | // include processes an included file, and returns the included text. 104 | // Only lines between those matching !+tag and !-tag will be returned. 105 | // This is true even if tag=="". 106 | func include(file, tag string) (string, error) { 107 | f, err := os.Open(file) 108 | if err != nil { 109 | return "", err 110 | } 111 | defer f.Close() 112 | 113 | startre, err := regexp.Compile("!\\+" + tag + "$") 114 | if err != nil { 115 | return "", err 116 | } 117 | endre, err := regexp.Compile("!\\-" + tag + "$") 118 | if err != nil { 119 | return "", err 120 | } 121 | 122 | var text bytes.Buffer 123 | in := bufio.NewScanner(f) 124 | var on bool 125 | for in.Scan() { 126 | line := in.Text() 127 | switch { 128 | case startre.MatchString(line): 129 | on = true 130 | case endre.MatchString(line): 131 | on = false 132 | case on: 133 | text.WriteByte('\t') 134 | text.WriteString(line) 135 | text.WriteByte('\n') 136 | } 137 | } 138 | if text.Len() == 0 { 139 | return "", fmt.Errorf("no lines of %s matched tag %q", file, tag) 140 | } 141 | return text.String(), nil 142 | } 143 | 144 | func isBlank(line string) bool { return strings.TrimSpace(line) == "" } 145 | 146 | func indented(line string) bool { 147 | return strings.HasPrefix(line, " ") || strings.HasPrefix(line, "\t") 148 | } 149 | 150 | // cleanListing removes entirely blank leading and trailing lines from 151 | // text, and removes n leading tabs. 152 | func cleanListing(text string) string { 153 | lines := strings.Split(text, "\n") 154 | 155 | // remove minimum number of leading tabs from all non-blank lines 156 | tabs := 999 157 | for i, line := range lines { 158 | if strings.TrimSpace(line) == "" { 159 | lines[i] = "" 160 | } else { 161 | if n := leadingTabs(line); n < tabs { 162 | tabs = n 163 | } 164 | } 165 | } 166 | for i, line := range lines { 167 | if line != "" { 168 | line := line[tabs:] 169 | lines[i] = line // remove leading tabs 170 | } 171 | } 172 | 173 | // remove leading blank lines 174 | for len(lines) > 0 && lines[0] == "" { 175 | lines = lines[1:] 176 | } 177 | // remove trailing blank lines 178 | for len(lines) > 0 && lines[len(lines)-1] == "" { 179 | lines = lines[:len(lines)-1] 180 | } 181 | return strings.Join(lines, "\n") 182 | } 183 | 184 | func leadingTabs(s string) int { 185 | var i int 186 | for i = 0; i < len(s); i++ { 187 | if s[i] != '\t' { 188 | break 189 | } 190 | } 191 | return i 192 | } 193 | -------------------------------------------------------------------------------- /lesson55/workspace/hello/example/hello/hello.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 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 | package main 18 | 19 | import ( 20 | "fmt" 21 | 22 | "golang.org/x/example/stringutil" 23 | ) 24 | 25 | func main() { 26 | fmt.Println(stringutil.Reverse("!selpmaxe oG ,olleH")) 27 | } 28 | -------------------------------------------------------------------------------- /lesson55/workspace/hello/example/outyet/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:onbuild 2 | EXPOSE 8080 3 | -------------------------------------------------------------------------------- /lesson55/workspace/hello/example/outyet/containers.yaml: -------------------------------------------------------------------------------- 1 | version: v1beta2 2 | containers: 3 | - name: outyet 4 | image: adg1/outyet 5 | ports: 6 | - name: http 7 | hostPort: 80 8 | containerPort: 8080 9 | -------------------------------------------------------------------------------- /lesson55/workspace/hello/example/outyet/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 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 | // outyet is a web server that announces whether or not a particular Go version 18 | // has been tagged. 19 | package main 20 | 21 | import ( 22 | "expvar" 23 | "flag" 24 | "fmt" 25 | "html/template" 26 | "log" 27 | "net/http" 28 | "sync" 29 | "time" 30 | ) 31 | 32 | // Command-line flags. 33 | var ( 34 | httpAddr = flag.String("http", ":8080", "Listen address") 35 | pollPeriod = flag.Duration("poll", 5*time.Second, "Poll period") 36 | version = flag.String("version", "1.4", "Go version") 37 | ) 38 | 39 | const baseChangeURL = "https://go.googlesource.com/go/+/" 40 | 41 | func main() { 42 | flag.Parse() 43 | changeURL := fmt.Sprintf("%sgo%s", baseChangeURL, *version) 44 | http.Handle("/", NewServer(*version, changeURL, *pollPeriod)) 45 | log.Fatal(http.ListenAndServe(*httpAddr, nil)) 46 | } 47 | 48 | // Exported variables for monitoring the server. 49 | // These are exported via HTTP as a JSON object at /debug/vars. 50 | var ( 51 | hitCount = expvar.NewInt("hitCount") 52 | pollCount = expvar.NewInt("pollCount") 53 | pollError = expvar.NewString("pollError") 54 | pollErrorCount = expvar.NewInt("pollErrorCount") 55 | ) 56 | 57 | // Server implements the outyet server. 58 | // It serves the user interface (it's an http.Handler) 59 | // and polls the remote repository for changes. 60 | type Server struct { 61 | version string 62 | url string 63 | period time.Duration 64 | 65 | mu sync.RWMutex // protects the yes variable 66 | yes bool 67 | } 68 | 69 | // NewServer returns an initialized outyet server. 70 | func NewServer(version, url string, period time.Duration) *Server { 71 | s := &Server{version: version, url: url, period: period} 72 | go s.poll() 73 | return s 74 | } 75 | 76 | // poll polls the change URL for the specified period until the tag exists. 77 | // Then it sets the Server's yes field true and exits. 78 | func (s *Server) poll() { 79 | for !isTagged(s.url) { 80 | pollSleep(s.period) 81 | } 82 | s.mu.Lock() 83 | s.yes = true 84 | s.mu.Unlock() 85 | pollDone() 86 | } 87 | 88 | // Hooks that may be overridden for integration tests. 89 | var ( 90 | pollSleep = time.Sleep 91 | pollDone = func() {} 92 | ) 93 | 94 | // isTagged makes an HTTP HEAD request to the given URL and reports whether it 95 | // returned a 200 OK response. 96 | func isTagged(url string) bool { 97 | pollCount.Add(1) 98 | r, err := http.Head(url) 99 | if err != nil { 100 | log.Print(err) 101 | pollError.Set(err.Error()) 102 | pollErrorCount.Add(1) 103 | return false 104 | } 105 | return r.StatusCode == http.StatusOK 106 | } 107 | 108 | // ServeHTTP implements the HTTP user interface. 109 | func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { 110 | hitCount.Add(1) 111 | s.mu.RLock() 112 | data := struct { 113 | URL string 114 | Version string 115 | Yes bool 116 | }{ 117 | s.url, 118 | s.version, 119 | s.yes, 120 | } 121 | s.mu.RUnlock() 122 | err := tmpl.Execute(w, data) 123 | if err != nil { 124 | log.Print(err) 125 | } 126 | } 127 | 128 | // tmpl is the HTML template that drives the user interface. 129 | var tmpl = template.Must(template.New("tmpl").Parse(` 130 |
131 |

Is Go {{.Version}} out yet?

132 |

133 | {{if .Yes}} 134 | YES! 135 | {{else}} 136 | No. :-( 137 | {{end}} 138 |

139 |
140 | `)) 141 | -------------------------------------------------------------------------------- /lesson55/workspace/hello/example/outyet/main_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 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 | package main 18 | 19 | import ( 20 | "net/http" 21 | "net/http/httptest" 22 | "strings" 23 | "testing" 24 | "time" 25 | ) 26 | 27 | // statusHandler is an http.Handler that writes an empty response using itself 28 | // as the response status code. 29 | type statusHandler int 30 | 31 | func (h *statusHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 32 | w.WriteHeader(int(*h)) 33 | } 34 | 35 | func TestIsTagged(t *testing.T) { 36 | // Set up a fake "Google Code" web server reporting 404 not found. 37 | status := statusHandler(http.StatusNotFound) 38 | s := httptest.NewServer(&status) 39 | defer s.Close() 40 | 41 | if isTagged(s.URL) { 42 | t.Fatal("isTagged == true, want false") 43 | } 44 | 45 | // Change fake server status to 200 OK and try again. 46 | status = http.StatusOK 47 | 48 | if !isTagged(s.URL) { 49 | t.Fatal("isTagged == false, want true") 50 | } 51 | } 52 | 53 | func TestIntegration(t *testing.T) { 54 | status := statusHandler(http.StatusNotFound) 55 | ts := httptest.NewServer(&status) 56 | defer ts.Close() 57 | 58 | // Replace the pollSleep with a closure that we can block and unblock. 59 | sleep := make(chan bool) 60 | pollSleep = func(time.Duration) { 61 | sleep <- true 62 | sleep <- true 63 | } 64 | 65 | // Replace pollDone with a closure that will tell us when the poller is 66 | // exiting. 67 | done := make(chan bool) 68 | pollDone = func() { done <- true } 69 | 70 | // Put things as they were when the test finishes. 71 | defer func() { 72 | pollSleep = time.Sleep 73 | pollDone = func() {} 74 | }() 75 | 76 | s := NewServer("1.x", ts.URL, 1*time.Millisecond) 77 | 78 | <-sleep // Wait for poll loop to start sleeping. 79 | 80 | // Make first request to the server. 81 | r, _ := http.NewRequest("GET", "/", nil) 82 | w := httptest.NewRecorder() 83 | s.ServeHTTP(w, r) 84 | if b := w.Body.String(); !strings.Contains(b, "No.") { 85 | t.Fatalf("body = %s, want no", b) 86 | } 87 | 88 | status = http.StatusOK 89 | 90 | <-sleep // Permit poll loop to stop sleeping. 91 | <-done // Wait for poller to see the "OK" status and exit. 92 | 93 | // Make second request to the server. 94 | w = httptest.NewRecorder() 95 | s.ServeHTTP(w, r) 96 | if b := w.Body.String(); !strings.Contains(b, "YES!") { 97 | t.Fatalf("body = %q, want yes", b) 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /lesson55/workspace/hello/example/stringutil/reverse.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 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 | // Package stringutil contains utility functions for working with strings. 18 | package stringutil 19 | 20 | import "unicode" 21 | 22 | // Reverse returns its argument string reversed rune-wise left to right. 23 | func Reverse(s string) string { 24 | r := []rune(s) 25 | for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 { 26 | r[i], r[j] = r[j], r[i] 27 | } 28 | return string(r) 29 | } 30 | 31 | // ToUpper uppercases all the runes in its argument string. 32 | func ToUpper(s string) string { 33 | r := []rune(s) 34 | for i := range r { 35 | r[i] = unicode.ToUpper(r[i]) 36 | } 37 | return string(r) 38 | } 39 | -------------------------------------------------------------------------------- /lesson55/workspace/hello/example/stringutil/reverse_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 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 | package stringutil 18 | 19 | import "testing" 20 | 21 | func TestReverse(t *testing.T) { 22 | for _, c := range []struct { 23 | in, want string 24 | }{ 25 | {"Hello, world", "dlrow ,olleH"}, 26 | {"Hello, 世界", "界世 ,olleH"}, 27 | {"", ""}, 28 | } { 29 | got := Reverse(c.in) 30 | if got != c.want { 31 | t.Errorf("Reverse(%q) == %q, want %q", c.in, got, c.want) 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lesson55/workspace/hello/example/template/image.tmpl: -------------------------------------------------------------------------------- 1 | {{define "content"}} 2 |
3 | {{.Title}} 4 |
5 | {{end}} 6 | 7 | {{define "sidebar"}} 8 | Back 9 | {{end}} 10 | -------------------------------------------------------------------------------- /lesson55/workspace/hello/example/template/index.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{.Title}} 6 | 17 | 18 | 19 |

{{.Title}}

20 | 21 | 34 | 35 | {{block "content" .}} 36 |
37 | {{.Body}} 38 |
39 | {{end}} 40 | 41 | 42 | -------------------------------------------------------------------------------- /lesson55/workspace/hello/example/template/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 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 | // Command template is a trivial web server that uses the text/template (and 18 | // html/template) package's "block" feature to implement a kind of template 19 | // inheritance. 20 | // 21 | // It should be executed from the directory in which the source resides, 22 | // as it will look for its template files in the current directory. 23 | package main 24 | 25 | import ( 26 | "html/template" 27 | "log" 28 | "net/http" 29 | "strings" 30 | ) 31 | 32 | func main() { 33 | http.HandleFunc("/", indexHandler) 34 | http.HandleFunc("/image/", imageHandler) 35 | log.Fatal(http.ListenAndServe("localhost:8080", nil)) 36 | } 37 | 38 | // indexTemplate is the main site template. 39 | // The default template includes two template blocks ("sidebar" and "content") 40 | // that may be replaced in templates derived from this one. 41 | var indexTemplate = template.Must(template.ParseFiles("index.tmpl")) 42 | 43 | // Index is a data structure used to populate an indexTemplate. 44 | type Index struct { 45 | Title string 46 | Body string 47 | Links []Link 48 | } 49 | 50 | type Link struct { 51 | URL, Title string 52 | } 53 | 54 | // indexHandler is an HTTP handler that serves the index page. 55 | func indexHandler(w http.ResponseWriter, r *http.Request) { 56 | data := &Index{ 57 | Title: "Image gallery", 58 | Body: "Welcome to the image gallery.", 59 | } 60 | for name, img := range images { 61 | data.Links = append(data.Links, Link{ 62 | URL: "/image/" + name, 63 | Title: img.Title, 64 | }) 65 | } 66 | if err := indexTemplate.Execute(w, data); err != nil { 67 | log.Println(err) 68 | } 69 | } 70 | 71 | // imageTemplate is a clone of indexTemplate that provides 72 | // alternate "sidebar" and "content" templates. 73 | var imageTemplate = template.Must(template.Must(indexTemplate.Clone()).ParseFiles("image.tmpl")) 74 | 75 | // Image is a data structure used to populate an imageTemplate. 76 | type Image struct { 77 | Title string 78 | URL string 79 | } 80 | 81 | // imageHandler is an HTTP handler that serves the image pages. 82 | func imageHandler(w http.ResponseWriter, r *http.Request) { 83 | data, ok := images[strings.TrimPrefix(r.URL.Path, "/image/")] 84 | if !ok { 85 | http.NotFound(w, r) 86 | return 87 | } 88 | if err := imageTemplate.Execute(w, data); err != nil { 89 | log.Println(err) 90 | } 91 | } 92 | 93 | // images specifies the site content: a collection of images. 94 | var images = map[string]*Image{ 95 | "go": {"The Go Gopher", "https://golang.org/doc/gopher/frontpage.png"}, 96 | "google": {"The Google Logo", "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"}, 97 | } 98 | -------------------------------------------------------------------------------- /lesson55/workspace/hello/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/weirubo/hello 2 | 3 | go 1.19 4 | 5 | require golang.org/x/example v0.0.0-20220412213650-2e68773dfca0 // indirect 6 | 7 | //replace golang.org/x/example v0.0.0-20220412213650-2e68773dfca0 => /Users/frank/workspace/hello/example 8 | -------------------------------------------------------------------------------- /lesson55/workspace/hello/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/example v0.0.0-20220412213650-2e68773dfca0 h1:ygD+9PaH9IfzZUF131IxmiXGkxzuN/pphDjzh2LY8N8= 6 | golang.org/x/example v0.0.0-20220412213650-2e68773dfca0/go.mod h1:+yakPl5KR9J+ysfUNADYwEU5qeqjUO473wDktD4xMYw= 7 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 8 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 9 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 10 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 11 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 12 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 13 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 14 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 15 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 16 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 17 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 18 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 19 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 24 | -------------------------------------------------------------------------------- /lesson55/workspace/hello/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "golang.org/x/example/stringutil" 6 | ) 7 | 8 | func main() { 9 | str := "hello" 10 | reverseStr := stringutil.Reverse(str) 11 | fmt.Println(reverseStr) 12 | toUpperStr := stringutil.ToUpper(str) 13 | fmt.Println(toUpperStr) 14 | 15 | } 16 | -------------------------------------------------------------------------------- /lesson56/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/weirubo/learn_go/lesson56 2 | 3 | go 1.19 4 | -------------------------------------------------------------------------------- /lesson56/reverse.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | input := "The quick brown fox jumped over the lazy dog" 7 | rev := Reverse(input) 8 | doubleRev := Reverse(rev) 9 | fmt.Printf("original: %q\n", input) 10 | fmt.Printf("reversed: %q\n", rev) 11 | fmt.Printf("reversed again: %q\n", doubleRev) 12 | } 13 | 14 | func Reverse(s string) string { 15 | //b := []byte(s) 16 | b := []rune(s) 17 | for i, j := 0, len(b)-1; i < len(b)/2; i, j = i+1, j-1 { 18 | b[i], b[j] = b[j], b[i] 19 | } 20 | return string(b) 21 | } 22 | -------------------------------------------------------------------------------- /lesson56/reverse_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | "unicode/utf8" 6 | ) 7 | 8 | func TestReverse(t *testing.T) { 9 | testcases := []struct { 10 | in, want string 11 | }{ 12 | {"Hello, world", "dlrow ,olleH"}, 13 | {" ", " "}, 14 | {"!12345", "54321!"}, 15 | {"我爱学编程", "程编学爱我"}, 16 | } 17 | for _, tc := range testcases { 18 | rev := Reverse(tc.in) 19 | if rev != tc.want { 20 | t.Errorf("Reverse: %q, want %q", rev, tc.want) 21 | } 22 | } 23 | } 24 | 25 | func FuzzReverse(f *testing.F) { 26 | testcases := []string{"Hello, world", " ", "!12345"} 27 | for _, tc := range testcases { 28 | f.Add(tc) // Use f.Add to provide a seed corpus 29 | } 30 | f.Fuzz(func(t *testing.T, orig string) { 31 | rev := Reverse(orig) 32 | doubleRev := Reverse(rev) 33 | if orig != doubleRev { 34 | t.Errorf("Before: %q, after: %q", orig, doubleRev) 35 | } 36 | if utf8.ValidString(orig) && !utf8.ValidString(rev) { 37 | t.Errorf("Reverse produced invalid UTF-8 string %q", rev) 38 | } 39 | }) 40 | } 41 | -------------------------------------------------------------------------------- /lesson56/testdata/fuzz/FuzzReverse/5d9cdd0e9f28de1a8961208a454ad8b2b2982f5554f43fba7000318303416ead: -------------------------------------------------------------------------------- 1 | go test fuzz v1 2 | string("\x81") 3 | -------------------------------------------------------------------------------- /lesson57/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | // 内置函数 7 | // append 8 | //s := []int{1, 2, 3} 9 | //fmt.Printf("%p %d\n", s, s) 10 | //s1 := append(s, 4) 11 | //fmt.Printf("%p %d\n", s, s) 12 | //fmt.Printf("%p %d\n", s1, s1) 13 | 14 | // copy 15 | //src := []string{"go", "vue"} 16 | //dst := make([]string, 3) 17 | //n := copy(dst, src) 18 | //fmt.Printf("%s %d\n", dst, n) 19 | 20 | //str := "hello" 21 | //bs := make([]byte, 5) 22 | //n := copy(bs, str) 23 | //fmt.Printf("%s %d\n", bs, n) 24 | 25 | // map 26 | //var m map[int]string 27 | //fmt.Println(m) 28 | //delete(m, 0) 29 | //fmt.Println(m) 30 | //m1 := make(map[int]string) 31 | //fmt.Println(m1) 32 | //delete(m1, 0) 33 | //fmt.Println(m1) 34 | //m2 := make(map[int]string, 2) 35 | //m2[0] = "hello" 36 | //m2[1] = "world" 37 | //fmt.Println(m2) 38 | //delete(m2, 0) 39 | //fmt.Println(m2) 40 | 41 | // len 42 | //arr := [3]int{1, 2, 3} 43 | //fmt.Println(arr) 44 | //fmt.Println(len(arr)) 45 | //var arr1 *[3]int 46 | //fmt.Println(arr1) 47 | //fmt.Println(len(arr1)) 48 | //var s []int 49 | //fmt.Println(len(s)) 50 | //s = []int{1, 2, 3} 51 | //fmt.Println(len(s)) 52 | //var m map[int]string 53 | //fmt.Println(len(m)) 54 | //m = make(map[int]string) 55 | //m[0] = "hello" 56 | //fmt.Println(len(m)) 57 | //str := "frank" 58 | //fmt.Println(len(str)) 59 | //var c chan int 60 | //fmt.Println(c) 61 | //fmt.Println(len(c)) 62 | //c = make(chan int) 63 | //fmt.Println(len(c)) 64 | 65 | // cap 66 | var arr [3]int 67 | fmt.Println(arr) 68 | fmt.Println(cap(arr)) 69 | var arr1 *[3]int 70 | fmt.Println(arr1) 71 | fmt.Println(cap(arr1)) 72 | var s []string 73 | fmt.Println(s) 74 | fmt.Println(cap(s)) 75 | s = make([]string, 1) 76 | s[0] = "go" 77 | fmt.Println(s) 78 | fmt.Println(cap(s)) 79 | var c chan int 80 | fmt.Println(c) 81 | fmt.Println(cap(c)) 82 | } 83 | -------------------------------------------------------------------------------- /lesson58/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/weirubo/learn_go/lesson58 2 | 3 | go 1.20 4 | 5 | require github.com/spf13/cast v1.5.1 6 | -------------------------------------------------------------------------------- /lesson58/go.sum: -------------------------------------------------------------------------------- 1 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 2 | github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= 3 | github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= 4 | github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= 5 | github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 6 | github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= 7 | github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= 8 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 9 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 10 | github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= 11 | github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= 12 | github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= 13 | github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= 14 | github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= 15 | -------------------------------------------------------------------------------- /lesson58/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/spf13/cast" 6 | "strconv" 7 | ) 8 | 9 | func main() { 10 | salary := 5000 11 | salaryStr := strconv.Itoa(salary) 12 | fmt.Printf("%T salary=%d\n", salary, salary) 13 | fmt.Printf("%T salaryStr=%s\n", salaryStr, salaryStr) 14 | 15 | age := "23" 16 | ageInt, err := strconv.Atoi(age) 17 | fmt.Printf("%T age=%s\n", age, age) 18 | fmt.Printf("%T ageInt=%d err=%v\n", ageInt, ageInt, err) 19 | 20 | ageInt8 := int8(ageInt) 21 | fmt.Println(ageInt8) 22 | 23 | phoneNumber := "138001380001380013800013800138000" 24 | phoneNumberInt, err := strconv.Atoi(phoneNumber) 25 | fmt.Printf("%T phoneNumber=%s\n", phoneNumber, phoneNumber) 26 | fmt.Printf("%T phoneNumberInt=%d err=%v\n", phoneNumberInt, phoneNumberInt, err) 27 | 28 | age2 := "23" 29 | age2Int8 := cast.ToInt8(age2) 30 | fmt.Printf("%T age2=%s\n", age2, age2) 31 | fmt.Printf("%T age2Int8=%d\n", age2Int8, age2Int8) 32 | 33 | phoneNumber2 := "138001380001380013800013800138000" 34 | phoneNumber2Int := cast.ToInt(phoneNumber2) 35 | fmt.Printf("%T phoneNumber2=%s\n", phoneNumber2, phoneNumber2) 36 | fmt.Printf("%T phoneNumber2Int=%d\n", phoneNumber2Int, phoneNumber2Int) 37 | 38 | month := "07" 39 | monthInt8 := cast.ToInt8(month) 40 | fmt.Printf("%T month=%s\n", month, month) 41 | fmt.Printf("%T monthInt8=%d\n", monthInt8, monthInt8) 42 | 43 | month2 := "08" 44 | month2Int8 := cast.ToInt8(month2) 45 | fmt.Printf("%T month2=%s\n", month2, month2) 46 | fmt.Printf("%T month2Int8=%d\n", month2Int8, month2Int8) 47 | 48 | month2Int2, err := strconv.Atoi(month2) 49 | fmt.Printf("%T month2Int2=%d err=%v\n", month2Int2, month2Int2, err) 50 | } 51 | -------------------------------------------------------------------------------- /lesson59/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/weirubo/learn_go/lesson59 2 | 3 | go 1.20 4 | 5 | require ( 6 | github.com/go-sql-driver/mysql v1.6.0 7 | xorm.io/xorm v1.3.2 8 | ) 9 | -------------------------------------------------------------------------------- /lesson59/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | _ "github.com/go-sql-driver/mysql" 6 | "time" 7 | "xorm.io/xorm" 8 | ) 9 | 10 | func main() { 11 | // 创建 Engine 12 | engine, err := xorm.NewEngine("mysql", "root:root@/example?charset=utf8") 13 | defer func() { 14 | err = engine.Close() 15 | if err != nil { 16 | fmt.Printf("engine close err=%v\n", err) 17 | return 18 | } 19 | }() 20 | if err != nil { 21 | fmt.Printf("init xorm engine fail, err=%v\n", err) 22 | return 23 | } 24 | 25 | // 更改数据 26 | sql := "UPDATE example SET title=?, view=?, created=? WHERE id=?" 27 | res, err := engine.Exec(sql, "Python", 60, time.Now().Unix(), 2) 28 | if err != nil { 29 | fmt.Printf("Update err=%v\n", err) 30 | return 31 | } 32 | affected, err := res.RowsAffected() 33 | if err != nil { 34 | fmt.Printf("RowsAffected err=%v\n", err) 35 | return 36 | } 37 | fmt.Printf("affected=%d\n", affected) 38 | 39 | //example := &Example{ 40 | // Title: "JavaScript", 41 | // View: 98, 42 | //} 43 | // 44 | //condi := &Example{ 45 | // Id: 2, 46 | //} 47 | // 48 | //affected, err := engine.Update(example, condi) 49 | //if err != nil { 50 | // fmt.Printf("Update err=%v\n", err) 51 | // return 52 | //} 53 | //fmt.Printf("affected=%d\n", affected) 54 | 55 | // 插入数据 56 | //example := &Example{ 57 | // Title: "Vue", 58 | // View: 85, 59 | //} 60 | //affected, err := engine.Insert(example) 61 | //if err != nil { 62 | // fmt.Printf("Insert err=%v\n", err) 63 | // return 64 | //} 65 | //id := example.Id 66 | //fmt.Printf("affected=%v || id=%d\n", affected, id) 67 | 68 | // 更新数据 69 | //example := &Example{ 70 | // Title: "Java", 71 | // View: 0, 72 | //} 73 | //condi := &Example{ 74 | // Id: 2, 75 | //} 76 | ////affected, err := engine.Update(example, condi) 77 | //affected, err := engine.Cols("title", "view").Update(example, condi) 78 | //if err != nil { 79 | // fmt.Printf("Update err=%v\n", err) 80 | // return 81 | //} 82 | //fmt.Printf("affected=%d\n", affected) 83 | 84 | } 85 | 86 | type Example struct { 87 | Id int `json:"id" form:"id" xorm:"autoincr"` 88 | Title string `json:"title" form:"title"` 89 | View int `json:"view" form:"view"` 90 | Created int `json:"created" form:"created" xorm:"created"` 91 | Updated int `json:"updated" form:"updated" xorm:"updated"` 92 | } 93 | -------------------------------------------------------------------------------- /lesson60/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/weirubo/learn_go/lesson60 2 | 3 | go 1.20 4 | -------------------------------------------------------------------------------- /lesson60/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | ) 7 | 8 | func main() { 9 | //var a int64 10 | //a = 1 11 | //fmt.Printf("%T\t%d\n", a, a) 12 | //var b int8 13 | //b = int8(a) 14 | //fmt.Printf("%T\t%d\n", b, b) 15 | 16 | //var a float64 17 | //a = 3.1415926 18 | //fmt.Printf("%T\t%f\n", a, a) 19 | //var b float32 20 | //b = float32(a) 21 | //fmt.Printf("%T\t%f\n", b, b) 22 | //var c int64 23 | //c = int64(b) 24 | //fmt.Printf("%T\t%d\n", c, c) 25 | 26 | //var a string 27 | //a = "golang" 28 | //fmt.Printf("%T\t%s\n", a, a) 29 | //var b []byte 30 | //b = []byte(a) 31 | //fmt.Printf("%T\t%d\n", b, b) 32 | 33 | //var a bool 34 | //a = true 35 | //fmt.Printf("%T\t%t\n", a, a) 36 | //var b string 37 | //b = strconv.FormatBool(a) 38 | //fmt.Printf("%T\t%s\n", b, b) 39 | 40 | //var id interface{} 41 | //id = 1 // 参数 id 接收到的值为整型 42 | //fmt.Printf("%T\t%v\n", id, id) 43 | //// 需要使用字符串类型的变量 id 赋值给字符串类型的变量 uid 44 | //var uid string 45 | //value, ok := id.(string) 46 | //if ok { 47 | // uid = value 48 | //} 49 | //fmt.Printf("%T\t%v\n", uid, uid) 50 | 51 | var id interface{} 52 | id = 1 // 参数 id 接收到的值为整型 53 | fmt.Printf("0-%T\t%v\n", id, id) 54 | // 需要使用字符串类型的变量 id 赋值给字符串类型的变量 uid 55 | var uid string 56 | switch val := id.(type) { 57 | case string: 58 | uid = val 59 | fmt.Printf("1-%T\t%v\n", uid, uid) 60 | case int: 61 | uid = strconv.Itoa(val) 62 | fmt.Printf("2-%T\t%v\n", uid, uid) 63 | default: 64 | fmt.Printf("3-%T\t%v\n", uid, uid) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /lesson61/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/weirubo/learn_go/lesson61 2 | 3 | go 1.21.0 4 | -------------------------------------------------------------------------------- /lesson61/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | //m := min() 7 | //fmt.Println(m) 8 | //s := []int{1, 2, 3} 9 | //m := min(s...) 10 | //fmt.Println(m) 11 | //m := min(3.14, math.NaN(), 1.0) 12 | //fmt.Println(m) 13 | //m := max(2, math.NaN(), 1) 14 | //fmt.Println(m) 15 | //var x int 16 | //m := min(x) // m == x 17 | //fmt.Println(m) // 0 18 | //var x, y int = 1, 2 19 | //m := min(x, y) // m is the smaller of x and y 20 | //fmt.Println(m) 21 | //m := max(x, y, 10) // m is the larger of x and y but at least 10 22 | //c := min(1, 2.0, 3) // c == 1.0 (floating-point kind) 23 | //fmt.Printf("%T\t%v\n", c, c) 24 | //f := max(0, float32(x)) // type of f is float32 25 | //var s []string 26 | //_ = min(s...) // invalid: slice arguments are not permitted 27 | //t := min("", "foo", "bar") // t == "" (string kind) 28 | //fmt.Println(t) 29 | 30 | //s := []int{1, 2, 3} 31 | //fmt.Printf("len=%d\t s=%+v\n", len(s), s) 32 | //clear(s) 33 | //fmt.Printf("len=%d\t s=%+v\n", len(s), s) 34 | 35 | //m := map[string]int{"go": 100, "php": 80} 36 | //fmt.Printf("len=%d\tm=%+v\n", len(m), m) 37 | //clear(m) 38 | //fmt.Printf("len=%d\tm=%+v\n", len(m), m) 39 | 40 | //var s []int 41 | //clear(s) 42 | 43 | //var m map[string]int 44 | //clear(m) 45 | 46 | d := []Data{ 47 | { 48 | User: map[int]string{1: "frank", 2: "lucy"}, 49 | Salary: map[string]int{"frank": 1000, "lucy": 2000}, 50 | }, 51 | } 52 | fmt.Printf("d=%+v\n", d) 53 | clear(d) 54 | fmt.Printf("d=%+v\n", d) 55 | 56 | d1 := []Data1{ 57 | { 58 | User: "frank", 59 | Salary: 1000, 60 | }, 61 | } 62 | fmt.Printf("d1=%+v\n", d1) 63 | clear(d1) 64 | fmt.Printf("d1=%+v\n", d1) 65 | } 66 | 67 | type Data struct { 68 | User map[int]string 69 | Salary map[string]int 70 | } 71 | 72 | type Data1 struct { 73 | User string 74 | Salary int 75 | } 76 | -------------------------------------------------------------------------------- /lesson62/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/weirubo/learn_go/lesson62 2 | 3 | go 1.21 4 | -------------------------------------------------------------------------------- /lesson62/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "maps" 6 | ) 7 | 8 | func main() { 9 | m1 := map[string]int{"lucy": 17, "lily": 18} 10 | m2 := map[string]int{"lucy": 17, "lily": 18} 11 | m3 := map[string]int{"lucy": 18, "lily": 17} 12 | fmt.Println(maps.Equal(m1, m2)) 13 | fmt.Println(maps.Equal(m1, m3)) 14 | 15 | //maps.EqualFunc() 16 | } 17 | 18 | /** 19 | BinarySearch searches for target in a sorted slice and returns the position where target is found, 20 | or the position where target would appear in the sort order; 21 | it also returns a bool saying whether the target is really found in the slice. 22 | The slice must be sorted in increasing order. 23 | */ 24 | //names := []string{"Alice", "Bob", "Vera"} 25 | //n, found := slices.BinarySearch(names, "Vera") 26 | //fmt.Println("Vera:", n, found) 27 | //n, found = slices.BinarySearch(names, "Bill") 28 | //fmt.Println("Bill:", n, found) 29 | 30 | ///** 31 | //BinarySearchFunc works like BinarySearch, but uses a custom comparison function. 32 | //The slice must be sorted in increasing order, where "increasing" is defined by cmp. 33 | //cmp should return 0 if the slice element matches the target, a negative number if the slice element precedes the target, 34 | //or a positive number if the slice element follows the target. cmp must implement the same ordering as the slice, 35 | //such that if cmp(a, t) < 0 and cmp(b, t) >= 0, then a must precede b in the slice. 36 | //*/ 37 | //type Person struct { 38 | // Name string 39 | // Age int 40 | //} 41 | //people := []Person{ 42 | // {"Alice", 55}, 43 | // {"Bob", 24}, 44 | // {"Gopher", 13}, 45 | //} 46 | //n, found := slices.BinarySearchFunc(people, Person{"Bob", 0}, func(a, b Person) int { 47 | // return cmp.Compare(a.Name, b.Name) 48 | //}) 49 | //fmt.Println("Bob:", n, found) 50 | -------------------------------------------------------------------------------- /lesson63/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/weirubo/learn_go/lesson63 2 | 3 | go 1.21.0 4 | -------------------------------------------------------------------------------- /lesson63/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "log/slog" 7 | "os" 8 | ) 9 | 10 | func main() { 11 | log.Println("This is log") 12 | slog.Debug("This is Debug Level") 13 | slog.Info("This is Info Level") 14 | slog.Warn("This is Warn Level") 15 | slog.Error("This is Error Level") 16 | 17 | slog.Log(context.Background(), -4, "This is Debug Level") 18 | slog.Log(context.Background(), 0, "This is Info Level") 19 | slog.Log(context.Background(), 4, "This is Warn Level") 20 | slog.Log(context.Background(), 8, "This is Error Level") 21 | 22 | slog.Info("This is Info Level", "uid", 1001) 23 | 24 | logger := slog.New(slog.NewTextHandler(os.Stdout, nil)) 25 | logger.Info("This is a new text Info Level", "uid", 1002) 26 | 27 | jsonLogger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) 28 | jsonLogger.Info("This is a json format Info Level", "uid", 1003) 29 | 30 | opts := &slog.HandlerOptions{Level: slog.LevelDebug} 31 | textLogger := slog.New(slog.NewJSONHandler(os.Stdout, opts)) 32 | textLogger.Debug("This is a logger of support Debug Level", "uid", 1004) 33 | } 34 | -------------------------------------------------------------------------------- /lesson64/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/weirubo/learn_go/lesson64 2 | 3 | go 1.21.0 4 | 5 | require ( 6 | github.com/gin-gonic/gin v1.9.1 7 | github.com/prometheus/client_golang v1.17.0 8 | ) 9 | -------------------------------------------------------------------------------- /lesson64/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/prometheus/client_golang/prometheus/promhttp" 6 | "github.com/weirubo/learn_go/lesson64/middleware" 7 | ) 8 | 9 | func main() { 10 | r := gin.New() 11 | r.Use(middleware.Metrics()) 12 | r.GET("/metrics", gin.WrapH(promhttp.Handler())) 13 | r.GET("/ping", func(c *gin.Context) { 14 | c.JSON(200, gin.H{ 15 | "message": "pong", 16 | }) 17 | }) 18 | r.Run() 19 | } 20 | -------------------------------------------------------------------------------- /lesson64/middleware/metrics.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "fmt" 5 | "github.com/gin-gonic/gin" 6 | "github.com/weirubo/learn_go/lesson64/prom" 7 | ) 8 | 9 | func Metrics() gin.HandlerFunc { 10 | return func(c *gin.Context) { 11 | c.Next() 12 | code := fmt.Sprintf("%d", c.Writer.Status()) 13 | method := c.Request.Method 14 | labels := []string{"example-service", code, c.FullPath(), method} 15 | prom.RequestCounter.WithLabelValues(labels...).Inc() 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /lesson64/prom/metrics.go: -------------------------------------------------------------------------------- 1 | package prom 2 | 3 | import "github.com/prometheus/client_golang/prometheus" 4 | 5 | var ( 6 | labelNames = []string{"service", "code", "path", "method"} 7 | RequestCounter = prometheus.NewCounterVec( 8 | prometheus.CounterOpts{ 9 | Name: "http_request_count_total", 10 | Help: "Total number of HTTP requests made.", 11 | }, labelNames, 12 | ) 13 | ) 14 | 15 | func init() { 16 | prometheus.MustRegister(RequestCounter) 17 | } 18 | -------------------------------------------------------------------------------- /lesson65/gin_middleware/metrics.go: -------------------------------------------------------------------------------- 1 | package gin_middleware 2 | 3 | import ( 4 | "fmt" 5 | "github.com/gin-gonic/gin" 6 | "github.com/prometheus/client_golang/prometheus" 7 | "github.com/weirubo/learn_go/lesson65/prometheus_metrics" 8 | ) 9 | 10 | func Metrics() gin.HandlerFunc { 11 | return func(c *gin.Context) { 12 | c.Next() 13 | host := c.RemoteIP() 14 | code := fmt.Sprintf("%d", c.Writer.Status()) 15 | method := c.Request.Method 16 | labelsByHttpReqs := []string{host, code, c.FullPath(), method} 17 | prometheus_metrics.HttpReqs.WithLabelValues(labelsByHttpReqs...).Inc() 18 | prometheus_metrics.OpsQueued.With(prometheus.Labels{"type": "delete", "user": "alice"}).Inc() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lesson65/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/weirubo/learn_go/lesson65 2 | 3 | go 1.21.0 4 | 5 | require ( 6 | github.com/gin-gonic/gin v1.9.1 7 | github.com/prometheus/client_golang v1.17.0 8 | ) 9 | -------------------------------------------------------------------------------- /lesson65/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/prometheus/client_golang/prometheus" 6 | "github.com/prometheus/client_golang/prometheus/promhttp" 7 | "github.com/weirubo/learn_go/lesson65/gin_middleware" 8 | "github.com/weirubo/learn_go/lesson65/prometheus_metrics" 9 | ) 10 | 11 | func init() { 12 | // 注册 13 | reg := prometheus.NewRegistry() 14 | reg.MustRegister(prometheus_metrics.HttpReqs, prometheus_metrics.OpsQueued, prometheus_metrics.Latencies, prometheus_metrics.Temps) 15 | } 16 | 17 | func main() { 18 | r := gin.New() 19 | r.Use(gin_middleware.Metrics()) 20 | r.GET("/metrics", gin.WrapH(promhttp.Handler())) 21 | r.GET("/ping", func(c *gin.Context) { 22 | c.JSON(200, gin.H{ 23 | "message": "pong", 24 | }) 25 | }) 26 | err := r.Run() 27 | if err != nil { 28 | return 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lesson65/prometheus_metrics/metrics.go: -------------------------------------------------------------------------------- 1 | package prometheus_metrics 2 | 3 | import "github.com/prometheus/client_golang/prometheus" 4 | 5 | var ( 6 | // 标签名 7 | labelNamesByHttpReqs = []string{"server", "code", "path", "method"} 8 | // HttpReqs 实例化 CounterVec 9 | HttpReqs *prometheus.CounterVec = prometheus.NewCounterVec(prometheus.CounterOpts{ 10 | Name: "http_requests_total", 11 | Help: "How many HTTP requests processed, partitioned by status code and HTTP method.", 12 | }, 13 | labelNamesByHttpReqs, 14 | ) 15 | 16 | labelNamesByOpsQueued = []string{ 17 | // Which user has requested the operation? 18 | "user", 19 | // Of what type is the operation? 20 | "type", 21 | } 22 | OpsQueued = prometheus.NewGaugeVec( 23 | prometheus.GaugeOpts{ 24 | // fqName = strings.Join([]string{namespace, subsystem, name}, "_") 25 | //Namespace: "our_company", 26 | //Subsystem: "blob_storage", 27 | Name: "ops_queued", 28 | // fqName 相同的指标,Help 信息也需要相同。 29 | Help: "Number of blob storage operations waiting to be processed, partitioned by user and type.", 30 | }, 31 | labelNamesByOpsQueued, 32 | ) 33 | 34 | labelNamesByHistogram = []string{"method", "code"} 35 | Latencies = prometheus.NewHistogramVec( 36 | prometheus.HistogramOpts{ 37 | Name: "http_request_duration_seconds", 38 | Help: "Tracks the latencies for HTTP requests.", 39 | Buckets: []float64{0.99, 0.9, 0.5}, 40 | }, 41 | labelNamesByHistogram, 42 | ) 43 | 44 | labelNamesByTemps = []string{"species"} 45 | Temps = prometheus.NewSummaryVec( 46 | prometheus.SummaryOpts{ 47 | Name: "pond_temperature_celsius", 48 | Help: "The temperature of the frog pond.", 49 | Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, 50 | }, 51 | labelNamesByTemps, 52 | ) 53 | ) 54 | -------------------------------------------------------------------------------- /lesson67/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/weirubo/learn_go/lesson67 2 | 3 | go 1.21.0 4 | -------------------------------------------------------------------------------- /lesson67/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | //func main() { 9 | // v := "true" 10 | // if s, err := strconv.ParseBool(v); err == nil { 11 | // fmt.Printf("%T, %v\n", s, s) 12 | // } 13 | //} 14 | 15 | //func main() { 16 | // v := "3.1415926535" 17 | // if s, err := strconv.ParseFloat(v, 32); err == nil { 18 | // fmt.Printf("%T, %v\n", s, s) 19 | // } 20 | // if s, err := strconv.ParseFloat(v, 64); err == nil { 21 | // fmt.Printf("%T, %v\n", s, s) 22 | // } 23 | // if s, err := strconv.ParseFloat("NaN", 32); err == nil { 24 | // fmt.Printf("%T, %v\n", s, s) 25 | // } 26 | // // ParseFloat is case insensitive 27 | // if s, err := strconv.ParseFloat("nan", 32); err == nil { 28 | // fmt.Printf("%T, %v\n", s, s) 29 | // } 30 | // if s, err := strconv.ParseFloat("inf", 32); err == nil { 31 | // fmt.Printf("%T, %v\n", s, s) 32 | // } 33 | // if s, err := strconv.ParseFloat("+Inf", 32); err == nil { 34 | // fmt.Printf("%T, %v\n", s, s) 35 | // } 36 | // if s, err := strconv.ParseFloat("-Inf", 32); err == nil { 37 | // fmt.Printf("%T, %v\n", s, s) 38 | // } 39 | // if s, err := strconv.ParseFloat("-0", 32); err == nil { 40 | // fmt.Printf("%T, %v\n", s, s) 41 | // } 42 | // if s, err := strconv.ParseFloat("+0", 32); err == nil { 43 | // fmt.Printf("%T, %v\n", s, s) 44 | // } 45 | //} 46 | 47 | //func main() { 48 | // v32 := "-354634382" 49 | // if s, err := strconv.ParseInt(v32, 10, 32); err == nil { 50 | // fmt.Printf("s:%T, %v\n", s, s) 51 | // } 52 | // s1, err := strconv.ParseInt(v32, 16, 32) 53 | // fmt.Println(s1, err) 54 | // if err == nil { 55 | // fmt.Printf("s1:%T, %v\n", s1, s1) 56 | // } 57 | // 58 | // v64 := "-3546343826724305832" 59 | // if s2, err := strconv.ParseInt(v64, 10, 64); err == nil { 60 | // fmt.Printf("s2:%T, %v\n", s2, s2) 61 | // } 62 | // if s3, err := strconv.ParseInt(v64, 16, 64); err == nil { 63 | // fmt.Printf("s3:%T, %v\n", s3, s3) 64 | // } 65 | //} 66 | 67 | //func main() { 68 | // v := true 69 | // s := strconv.FormatBool(v) 70 | // fmt.Printf("%T, %v\n", s, s) 71 | //} 72 | 73 | //func main() { 74 | // v := 3.1415926535 75 | // 76 | // s32 := strconv.FormatFloat(v, 'E', -1, 32) 77 | // fmt.Printf("%T, %v\n", s32, s32) 78 | // 79 | // s64 := strconv.FormatFloat(v, 'E', -1, 64) 80 | // fmt.Printf("%T, %v\n", s64, s64) 81 | // 82 | // // fmt.Println uses these arguments to print floats 83 | // fmt64 := strconv.FormatFloat(v, 'g', -1, 64) 84 | // fmt.Printf("%T, %v\n", fmt64, fmt64) 85 | //} 86 | 87 | //func main() { 88 | // v := int64(-42) 89 | // 90 | // s10 := strconv.FormatInt(v, 10) 91 | // fmt.Printf("%T, %v\n", s10, s10) 92 | // 93 | // s16 := strconv.FormatInt(v, 16) 94 | // fmt.Printf("%T, %v\n", s16, s16) 95 | //} 96 | 97 | //func main() { 98 | // fmt.Println(strings.Contains("seafood", "foo")) 99 | // fmt.Println(strings.Contains("seafood", "bar")) 100 | // fmt.Println(strings.Contains("seafood", "")) 101 | // fmt.Println(strings.Contains("", "")) 102 | //} 103 | 104 | //func main() { 105 | // fmt.Println(strings.ContainsAny("team", "i")) 106 | // fmt.Println(strings.ContainsAny("fail", "ui")) 107 | // fmt.Println(strings.ContainsAny("ure", "ui")) 108 | // fmt.Println(strings.ContainsAny("failure", "ui")) 109 | // fmt.Println(strings.ContainsAny("foo", "")) 110 | // fmt.Println(strings.ContainsAny("", "")) 111 | //} 112 | 113 | //func main() { 114 | // fmt.Print(strings.Trim("¡¡¡Hello, Gophers!!!", "!¡")) 115 | //} 116 | 117 | //func main() { 118 | // fmt.Println(strings.ToUpper("Gopher")) 119 | //} 120 | 121 | //func main() { 122 | // fmt.Printf("%q\n", strings.Split("a,b,c", ",")) 123 | // fmt.Printf("%q\n", strings.Split("a man a plan a canal panama", "a ")) 124 | // fmt.Printf("%q\n", strings.Split(" xyz ", "")) 125 | // fmt.Printf("%q\n", strings.Split("", "Bernardo O'Higgins")) 126 | //} 127 | 128 | func main() { 129 | s := []string{"foo", "bar", "baz"} 130 | fmt.Println(strings.Join(s, ", ")) 131 | } 132 | -------------------------------------------------------------------------------- /lesson68/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/weirubo/learb_go/lesson68 2 | 3 | go 1.21.0 4 | -------------------------------------------------------------------------------- /lesson68/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var arr1 [2]int 7 | var arr2 = [2]int{1, 2} 8 | var arr3 = [...]int{1, 2, 3} 9 | fmt.Println(arr1) 10 | fmt.Println(arr2) 11 | fmt.Println(arr3) 12 | fmt.Println(len(arr3)) 13 | //fmt.Println(arr2 == arr3) 14 | //fmt.Println(arr3[3]) 15 | //arr3[3] = 4 16 | Get(arr2) 17 | fmt.Printf("arr2=%p\n%d\n", &arr2, arr2) 18 | Store() 19 | } 20 | 21 | func Get(arr [2]int) { 22 | fmt.Printf("Get()=%p\n%d\n", &arr, arr) 23 | } 24 | 25 | func Store() { 26 | var arr [2]int 27 | for i := 0; i < 5; i++ { 28 | arr[i] = i + 1 29 | } 30 | fmt.Println(arr) 31 | } 32 | -------------------------------------------------------------------------------- /lesson69/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/weirubo/learn_go/lesson69 2 | 3 | go 1.21.0 4 | -------------------------------------------------------------------------------- /lesson69/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var s0 []int 7 | fmt.Println(s0) 8 | if s0 == nil { 9 | fmt.Println("ok") 10 | } 11 | s0 = append(s0, 1) 12 | fmt.Println(s0) 13 | var s1 = []int{1, 2, 3} 14 | fmt.Println(s1) 15 | 16 | var s2 []int = make([]int, 3) 17 | fmt.Println(s2) 18 | var s3 []int = make([]int, 3, 5) 19 | fmt.Println(s3) 20 | 21 | var arr [2]int 22 | arr[0] = 1 23 | arr[1] = 2 24 | //arr[2] = 3 25 | } 26 | -------------------------------------------------------------------------------- /lesson70/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/weirubo/learn_go/lesson70 2 | 3 | go 1.21.0 4 | -------------------------------------------------------------------------------- /lesson70/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func main() { 9 | var m = make(map[int]string) 10 | fmt.Println(m) 11 | // 赋值 12 | m[0] = "a" 13 | m[1] = "b" 14 | fmt.Println(m) 15 | // 读取 16 | val := m[1] 17 | fmt.Println(val) 18 | // 删除 19 | delete(m, 1) 20 | fmt.Println(m) 21 | // 更新 22 | m[1] = "x" 23 | fmt.Println(m) 24 | 25 | //go func() { 26 | // for { 27 | // m[1] = "xx" 28 | // } 29 | //}() 30 | 31 | go func() { 32 | for { 33 | _ = m[1] 34 | } 35 | }() 36 | 37 | go func() { 38 | for { 39 | delete(m, 1) 40 | } 41 | }() 42 | 43 | //// 并发读 44 | //for i := 0; i < 10; i++ { 45 | // go fmt.Println(m[i]) 46 | //} 47 | // 48 | //// 并发写 49 | //for i := 0; i < 10; i++ { 50 | // go func() { 51 | // m[i] = "y" 52 | // fmt.Println(m[1]) 53 | // }() 54 | //} 55 | time.Sleep(time.Second * 3) 56 | } 57 | -------------------------------------------------------------------------------- /lesson71/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/weirubo/learn_go/lesson71 2 | 3 | go 1.21.0 4 | -------------------------------------------------------------------------------- /lesson71/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | //name := GetUserName("frank") 7 | //fmt.Printf("name:%s\n", name) 8 | //if name != "gopher" { 9 | // return 10 | //} 11 | //defer fmt.Println("this is a defer call") 12 | var count int64 13 | defer func(data int64) { 14 | fmt.Println("defer:", data) 15 | }(count + 1) 16 | count = 100 17 | fmt.Println("main:", count) 18 | } 19 | 20 | func GetUserName(name string) string { 21 | return name 22 | } 23 | -------------------------------------------------------------------------------- /lesson72/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/weirubo/learn_go/lesson72 2 | 3 | go 1.21.0 4 | -------------------------------------------------------------------------------- /lesson72/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func main() { 9 | s := []int{1, 2, 3} 10 | for _, v := range s { 11 | go func() { 12 | fmt.Println(v) 13 | }() 14 | } 15 | time.Sleep(time.Second * 1) 16 | } 17 | -------------------------------------------------------------------------------- /lesson73/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/weirubo/lesson73 2 | 3 | go 1.22.1 4 | -------------------------------------------------------------------------------- /lesson73/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/http" 7 | ) 8 | 9 | func main() { 10 | // 使用 GET 方法注册处理器 11 | mux := http.NewServeMux() 12 | mux.HandleFunc("GET /goods/{name...}", func(w http.ResponseWriter, r *http.Request) { 13 | fmt.Fprintf(w, "iPhone") 14 | log.Println(r.PathValue("name")) 15 | }) 16 | // 创建服务器 17 | server := http.Server{ 18 | Handler: mux, 19 | } 20 | log.Fatal(server.ListenAndServe()) 21 | } 22 | -------------------------------------------------------------------------------- /lesson74/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/weirubo/learn_go/lesson74 2 | 3 | go 1.22.1 4 | -------------------------------------------------------------------------------- /lesson74/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "slices" 6 | ) 7 | 8 | func main() { 9 | //s1 := []int{1, 2, 3} 10 | //s2 := []int{4, 5, 6} 11 | //s3 := []int{7, 8, 9} 12 | //s := slices.Concat(s1, s2, s3) 13 | ////var s []int 14 | ////s = append(s, s1...) 15 | ////s = append(s, s2...) 16 | ////s = append(s, s3...) 17 | //fmt.Println(s) 18 | 19 | //s1 := []int{1, 2, 3, 4, 5, 6, 7, 8, 9} 20 | //s2 := slices.Delete(s1, 2, 5) 21 | 22 | //s1 := []int{1, 2, 3, 4, 5, 6, 7, 8, 9} 23 | //s2 := slices.DeleteFunc(s1, func(i int) bool { 24 | // return i%2 != 0 25 | //}) 26 | 27 | //s1 := []int{1, 2, 2, 3, 4, 3, 5, 4} 28 | //s2 := slices.Compact(s1) 29 | //fmt.Printf("len=%d\tcap=%d\tval=%d\t\n", len(s1), cap(s1), s1) 30 | //fmt.Printf("len=%d\tcap=%d\tval=%d\t\n", len(s2), cap(s2), s2) 31 | 32 | //s1 := []string{"go", "php", "php", "java", "python"} 33 | //s2 := slices.CompactFunc(s1, strings.EqualFold) 34 | 35 | //s1 := []string{"php", "java", "go", "python"} 36 | //s2 := slices.Replace(s1, 1, 3, "rust") 37 | 38 | s1 := []string{"Go", "PHP", "Java", "Rust"} 39 | s2 := slices.Insert(s1, 5) 40 | fmt.Printf("len=%d\tcap=%d\tval=%#v\n", len(s1), cap(s1), s1) 41 | fmt.Printf("len=%d\tcap=%d\tval=%#v\n", len(s2), cap(s2), s2) 42 | } 43 | --------------------------------------------------------------------------------