github.com/nibnait/go-learn@v0.0.0-20220227013611-dfa47ea6d2da/chapter/README.md (about) 1 [https://github.com/geektime-geekbang/go_learning](https://github.com/geektime-geekbang/go_learning) 2 3 ## ch1 基本数据类型 4 5 ### 数据类型 02_type_test.go 6 7 #### 基本数据类型 8 9 bool 10 string 11 int int8 int16 int32 int64 12 uint uint8 uint16 uint32 uint64 uintptr 13 byte // alias for uint8 14 rune // alias for int32, represents a Unicode code point 15 float32 float64 16 complex64 complex128 17 18 #### 类型转换 19 20 go 语言 **不支持隐式**类型转换 21 显示类型转换,OK 22 23 24 #### 类型的预定义值 25 26 math.MaxInt64 27 math.MaxFloat64 28 math.MaxUint32 29 30 31 ##### 与其他主要编程语言的差异 32 33 1. 不支持指针运算 34 2. string 是值类型,其默认的初始化值为空字符串,而不是 nil 35 36 ### 运算符 04_operator_test.go 37 38 #### 算术运算符 39 40 ![](./img/算术运算符.png) 41 42 #### 比较运算符 43 44 ![](./img/比较运算符.png) 45 46 #### 用 == 比较数组 47 48 相同维数且含有相同个数元素的数组才可以比较 49 每个元素都相同的才相等 50 51 #### 逻辑运算符 52 53 ![](./img/逻辑运算符.png) 54 55 #### 位运算符 56 57 ![](./img/位运算符.png) 58 59 ##### 与其他主要编程语言的差异 60 61 ![](./img/按位置零.png) 62 63 ### 循环 05_loop_test.go 64 65 一个 for 66 67 ### 条件 06_condition_test.go 68 69 #### if 条件 70 71 ##### 与其他主要编程语言的差异 72 73 1. condition 表达式结果必须为布尔值 74 2. 支持变量赋值: 75 76 ```go 77 if var declaration; condition { 78 // code to be executed if condition is true 79 } 80 ``` 81 82 #### switch 条件 83 84 ##### 与其他主要编程语言的差异 85 86 1. 条件表达式不限制为常量或者整数; 87 2. 单个 case 中,可以出现多个结果选项,使用逗号分隔;(TestSwitchMultiCase) 88 3.与C/Java语言等规则相反,Go语言不需要用break来明确退出一个case; 89 4.可以不设定switch之后的条件表达式,在此种情况下,整个switch结构与多个 if...else... 的逻辑作用等同(TestSwitchCaseCondition) 90 91 92 ### 数组 07_array_test.go 93 94 #### 数组截取 95 96 ```go 97 // a[开始索引(包含), 结束索引(不包含)] 98 func TestArraySection(t *testing.T) { 99 arr := [...]int{0, 1, 2, 3, 4, 5} 100 assert.Equal(t, arr[1:2], [...]int{1}) 101 assert.Equal(t, arr[1:3], [...]int{1, 2}) 102 assert.Equal(t, arr[1:], [...]int{1, 2, 3, 4, 5}) 103 assert.Equal(t, arr[:3], [...]int{0, 1, 2}) 104 } 105 ``` 106 107 ### 切片 08_slice_test.go 108 109 ![](./img/slice_growing_test.png) 110 111 ### Map 09_map_test.go 112 113 ```go 114 func TestAccessNotExistingKey(t *testing.T) { 115 if value, isExist := m1[3]; isExist { 116 t.Logf("key 3 存在。 value = %d", value) 117 } else { 118 t.Log("key 3 不存在") 119 } 120 } 121 122 func TestTravelMap(t *testing.T) { 123 m1 := map[int]int{1: 1, 2: 4, 3: 9} 124 125 for k, v := range m1 { 126 t.Log(k, v) 127 } 128 129 } 130 ``` 131 132 #### 10_mal_ext_test.go 133 134 ```go 135 map[key]func(){} 136 map[key]bool{} 137 ``` 138 139 ### 字符串 11_string_fun_test.go 140 141 #### 与其他主要变成语言的差异 142 143 1. string 是数据类型,不是引用或指针类型 144 2. string 是只读的 byte slice,len 函数可以它所包含的 byte 数 145 3. string 的 byte 数组可以存放任何数据 146 147 1.strings包 [https://golang.org/pkg/strings/](https://golang.org/pkg/strings/) 148 2.strconv包 [https://golang.org/pkg/strconv/](https://golang.org/pkg/strconv/) 149 150 # ch2 函数及面向对象介绍 151 152 ### Go 语言的函数 153 154 #### 与其他主要变成语言的差异(Go语言的函数是一等公民) 155 156 1. 可以有多个返回值 157 2. 所有参数都是**值传递**:slice, map, channel 会有传引用的错觉 158 3. 函数可以作为变量的值 159 4. 函数可以作为参数和返回值 160 161 --- 162 163 ### Go 语言 是面向对象的语言吗? 164 165 yes and no. [https://go.dev/doc/faq#Is_Go_an_object-oriented_language](https://go.dev/doc/faq#Is_Go_an_object-oriented_language) 166 167 168 ### 封装 169 170 ```go 171 type Person struct { 172 name string 173 age int 174 } 175 ``` 176 177 ### 接口 178 179 _与其他主要变成语言的差异(Go语言的函数是一等公民):_ 180 1.接口为非入侵性,实现不依赖于借口定义 181 2.所以接口的定义可以包含在接口使用者包内 182 183 ### 扩展与复用(继承) 184 185 17_extension_test.go 186 _与其他主要变成语言的差异:_ 187 **不支持**继承、**不支持**重载、**不支持**LSP 188 它不是继承,如果我们把“内部 struct ”看作⽗类,把“外部 struct” 看作⼦类, 会发现如下问题: 189 190 1. 不⽀持⼦类替换 191 2. ⼦类并不是真正继承了⽗类的⽅法 192 • ⽗类的定义的⽅法⽆法访问⼦类的数据和⽅法 193 194 ### 多态 195 196 18_polymorphism_test.go 197 1个接口,多个实现 198 199 ### 空接口与断言 200 201 19_empty_interface_test.go 202 203 1. 空接⼝可以表示任何类型 204 2. 通过断⾔来将空接⼝转换为制定类型 205 206 ```go 207 v, ok := p.(int) //ok=true 时为转换成功 208 ``` 209 210 # ch3 项目编程规范 211 212 ### Go 的错误机制 213 214 20_err_test.go 215 216 #### 与其他主要变成语言的差异 217 218 1. 没有异常 try catch 机制 219 2. error 类型实现了 error 接⼝ 220 221 ```go 222 type error interface { 223 Error() string 224 } 225 ``` 226 227 3. 可以通过 errors.New 来快速创建错误实例 228 229 ```go 230 errors.New("n must be in the range [0,100]") 231 ``` 232 233 #### panic vs os.Exit 234 235 21_panic_recover_test.go 236 237 | panic | os.Exit | 238 | ----------------------------------- | --------------------------------------- | 239 | panic ⽤于不可以恢复的错误 | | 240 | panic 退出前会执⾏ defer 指定的内容 | os.Exit 退出时不会调⽤ defer 指定的函数 | 241 | os.Exit 退出时不输出当前调⽤栈信息 | | 242 243 ## 包 package 244 245 246 1. 基本复⽤模块单元 以⾸字⺟⼤写来表明可被包外代码访问 247 2. 代码的 package 可以和所在的⽬录不⼀致 248 3. 同⼀⽬录⾥的 Go 代码的 package 要保持⼀致 249 250 ### init 方法 251 252 - 在 main 被执⾏前,所有依赖的 package 的 init ⽅法都会被执⾏ 253 - 不同包的 init 函数按照包导⼊的依赖关系决定执⾏顺序 254 - 每个包可以有多个 init 函数 255 - 包的每个源⽂件也可以有多个 init 函数,这点⽐较特殊 256 257 ### 获取远程依赖 258 259 1. 通过 go get 来获取远程依赖 260 261 go get -u "github.com/easierway/concurrent_map" 262 263 264 2. 注意代码在 GitHub 上的组织形式,以适应 go get 265 266 直接以代码路径开始,不要有 src 267 268 示例: https://github.com/easierway/concurrent_map 269 270 --- 271 272 常用 module 273 274 > go get -u github.com/easierway/concurrent_map 275 > 276 > go get -u github.com/stretchr/testify/assert 277 > 278 > go get -u github.com/smartystreets/goconvey/convey 279 > 280 > go get -u github.com/mailru/easyjson/... 281 > 282 > go get -u github.com/julienschmidt/httprouter