├── README.md ├── LICENSE ├── python_tips.py ├── gotips_test.go └── swift.swift /README.md: -------------------------------------------------------------------------------- 1 | # CodeTips 2 | 3 | 当我们学习任何一门新语言时,都需要按照一定的步骤顺序去学习该语言的规则和特性。比如:HelloWorld怎么写,数据类型(包括字符处理),控制流程,异常处理,函数,面向对象,文件操作,并发处理,网络编程等等。 4 | 5 | 如今编程语言更新换代更加快速,越来越多新语言新技术如雨后春笋般涌现,快速学习并掌握新语言新技术的能力变得尤为重要。 6 | 7 | 在这么多种语言中,我喜欢Python的一个原因是她的语法是如此的简单,以至于我在隔上很长一段时间之后回来,依旧快速切换到Python的语法世界。 8 | 9 | 而Go语言是让我非常惊喜的,她和Python一样是简洁的,甚至我会认为她比Python更优雅。作为处女座程序员,`GoFmt`让我写代码时少了一大堆不必要的纠结和取舍,而我要做的仅仅是按照她唯一正确的方式去专心完成程序功能。 10 | 11 | Go拥抱开放,鼓励合作,import机制可以方便的从Github上引入大量第三方库,只需要执行一个简单的命令就可以把依赖的库下载下来。 12 | 13 | 如今,掌握多种语言,并且在合适的场景下进行切换已经是一项必备的技能了。而CodeTips就是为了这种切换能够更加便利。 14 | 15 | CodeTips的特点是使用一个代码文件将该语言大多数常用的用法罗列一遍,在你需要写该语言的代码时,可以直接打开CodeTips进行对比参照,提高效率,而不用去记忆那些容易忘记的细节。 16 | 17 | # Languages List 18 | 19 | * Go : [gotips_test.go](https://github.com/coderzh/CodeTips/blob/master/gotips_test.go) 20 | * Python [python_tips.py](https://github.com/coderzh/CodeTips/blob/master/python_tips.py) 21 | 22 | # Pull Request 23 | 24 | 如果你也觉得很有用,和我一起来改进她,大胆的把Pull Request丢过来吧。 25 | 26 | 如果你对其他语言也感兴趣,并且自己总结了一套该语言的CodeTips,也勇敢的Pull Request吧。 27 | 28 | # About 29 | 30 | 也欢迎和我交流,我的邮箱是pythonzh@gmail.com,博客地址:[blog.coderzh.com](http://blog.coderzh.com),谢谢! 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 coderzh 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /python_tips.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import os 5 | import argparse 6 | import subprocess 7 | 8 | # print 尽量用函数,不用语句 9 | print('Hello World') 10 | # do not use 11 | print 'Hello World' 12 | 13 | def subprocess_test(): 14 | # 执行子进程获得输出内容,尽量用 subprocess吧 15 | text = os.popen('echo 123').read() 16 | print(text) 17 | 18 | # subprocess 19 | # 父进程等待子进程完成 20 | subprocess.call(['ls', '-l']) 21 | return_code = subprocess.call('echo subprocess.call', shell=True) 22 | print(return_code) 23 | 24 | # Popen 不等待子进程完成,需调用 wait() 等待完成 25 | child = subprocess.Popen(['ls', '-l']) 26 | child.wait() 27 | ''' 28 | child.poll() # 检查子进程状态 29 | child.kill() # 终止子进程 30 | child.send_signal() # 向子进程发送信号 31 | child.terminate() # 终止子进程 32 | ''' 33 | print('parent process') 34 | 35 | # communicate 36 | # 尽量不要用 shell=True 37 | child1 = subprocess.Popen(['ls', '-l'], stdout=subprocess.PIPE) 38 | child2 = subprocess.Popen(['wc'], stdin=child1.stdout, stdout=subprocess.PIPE) 39 | out = child2.communicate() 40 | print('wc:', out) 41 | 42 | 43 | def os_file_demo(): 44 | # 遍历目录文件 45 | root = '.' 46 | for f in os.listdir(root): 47 | path = os.path.join(root, f) 48 | print(path) 49 | 50 | # 分割扩展名 ext 51 | print(os.path.splitext(os.path.basename('/a/b/c.txt'))) 52 | 53 | 54 | def main(): 55 | subprocess_test() 56 | os_file_demo() 57 | 58 | if __name__ == '__main__': 59 | parser = argparse.ArgumentParser(description='desc') 60 | # 参数 61 | # parser.add_argument('wan', help='eth0') 62 | # parser.add_argument('lan', help='wlan0') 63 | # 选项 64 | parser.add_argument('-v', dest='version', default=None, help='version') 65 | parser.add_argument('-u', dest='uin', default=None, help='uin') 66 | parser.add_argument('--verbose', dest='verbose', action='store_true', help='show verbose') 67 | 68 | args = parser.parse_args() 69 | #print(args.wan, args.lan, args.version, args.uin) 70 | 71 | main() 72 | 73 | 74 | -------------------------------------------------------------------------------- /gotips_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | gotips_test.go: 3 | Golang速学速查速用代码手册 4 | 5 | Source: github.com/coderzh/CodeTips/blob/master/gotips_test.go 6 | 7 | Author: coderzh(github.com/coderzh) 8 | Blog: http://blog.coderzh.com 9 | 参考:《Go语言编程》 10 | */ 11 | 12 | package main 13 | 14 | import ( 15 | "errors" 16 | "fmt" 17 | "github.com/stretchr/testify/assert" 18 | "io" 19 | "io/ioutil" 20 | "log" 21 | "math" 22 | "os" 23 | "path/filepath" 24 | "regexp" 25 | "strings" 26 | "sync" 27 | "testing" 28 | "time" 29 | ) 30 | 31 | // 0. 注释 32 | /* 33 | 规范: 34 | 1. 命名:骆驼命名法(不要用下划线) 35 | 36 | 命令: 37 | go get github.com/coderzh/xxx 38 | go build calc 39 | go run xxx.go 40 | go install calc 41 | */ 42 | 43 | // 1. Hello World 44 | func helloWorld() { 45 | fmt.Println("Hello, 世界") 46 | } 47 | 48 | // 2.变量类型 49 | func typeDemo() { 50 | // 变量声明 51 | var v1 int 52 | var ( 53 | v2 int 54 | v3 string 55 | ) 56 | //var p *int // 指针类型 57 | 58 | // 变量初始化 59 | var v4 int = 10 60 | // 等价于: 61 | var v5 = 10 62 | // 一般这样就好 63 | v6 := 10 64 | 65 | // 赋值,多重赋值 66 | v1 = 10 67 | v2, v3 = 20, "test" 68 | // 匿名变量 _ 69 | _, v4 = v5, v6 70 | 71 | fmt.Println(v1, v2, v3, v4) 72 | 73 | // 常量 74 | const Pi float64 = 3.1415926 75 | const MaxPlayer = 10 76 | 77 | // 枚举 78 | const ( 79 | Sunday = iota // iota从0递增 80 | Mondy 81 | Tuesday 82 | // ... 83 | ) 84 | 85 | // 类型 86 | // 1. 布尔 87 | var b1 bool 88 | b1 = true 89 | b1 = (1 == 2) 90 | 91 | fmt.Println(b1) 92 | 93 | // 2. 整形 94 | // int8 uint8 int16 uint16 int32 uint32 int64 uint64 int uint uintptr 95 | var i32 int32 96 | // 强制转换 97 | i32 = int32(64) 98 | // 运算:+, -, *, /, %(求余) 99 | // 比较:>, <, ==, >=, <=, != 100 | // 位运算:x << y, x >> y, x ^ y, x & y, x | y, ^x (取反) 101 | 102 | fmt.Println(i32) 103 | 104 | // 3. 浮点 105 | // float32, float64 106 | var f1 float64 = 1.0001 107 | var f2 float64 = 1.0002 108 | // 浮点比较 109 | isEqual := math.Dim(f1, f2) < 0.0001 110 | 111 | fmt.Println(isEqual) 112 | 113 | // 4. 字符串 114 | var s1 string 115 | s1 = "abc" 116 | // 字符串连接 117 | s1 = s1 + "ddd" 118 | // 取长度 119 | n := len(s1) 120 | // 取字符 121 | c1 := s1[0] 122 | // 反引号,不转义,常用于正则表达式 123 | s1 = `\w+` 124 | 125 | fmt.Println(c1) 126 | 127 | fmt.Println(strings.HasPrefix("prefix", "pre")) // true 128 | fmt.Println(strings.HasSuffix("suffix", "fix")) // true 129 | 130 | // 字节遍历 131 | for i := 0; i < n; i++ { 132 | ch := s1[i] 133 | fmt.Println(ch) 134 | } 135 | // Unicode字符Rune遍历 136 | for i, ch := range s1 { 137 | fmt.Println(i, ch) 138 | } 139 | 140 | // 5. 数组 141 | var arr1 [32]int 142 | //var arr2 [3][8]int // 二维数组 143 | // 初始化 144 | arr1 = [32]int{0} 145 | array := [5]int{1, 2, 3, 4, 5} 146 | // 临时结构体数组 147 | structArray := []struct { 148 | name string 149 | age int 150 | }{{"Tim", 18}, {"Jim", 20}} 151 | 152 | // 数组遍历 153 | for i := 0; i < len(array); i++ { 154 | fmt.Println(array[i]) 155 | } 156 | for i, v := range structArray { 157 | fmt.Println(i, v) 158 | } 159 | // 数组是值类型,每次参数传递都是一份拷贝 160 | 161 | // 数组切片Slice 162 | var mySlice []int = arr1[:2] 163 | mySlice1 := make([]int, 5) 164 | mySlice2 := make([]int, 5, 10) 165 | 166 | fmt.Println("len(mySlice2:", len(mySlice2)) // 5 167 | fmt.Println("cap(mySlice2:", cap(mySlice2)) // 10 168 | 169 | mySlice3 := append(mySlice, 2, 3, 4) 170 | mySlice4 := append(mySlice, mySlice1...) 171 | 172 | copy(mySlice3, mySlice4) 173 | 174 | // 6. Map 175 | var m map[int]string 176 | m[1] = "ddd" 177 | m1 := make(map[int]string) 178 | m2 := map[int]string{ 179 | 1: "a", 180 | 2: "b", 181 | } 182 | 183 | delete(m2, 1) 184 | 185 | value, ok := m1[1] 186 | if ok { 187 | fmt.Println(value) 188 | } 189 | 190 | for k, v := range m2 { 191 | fmt.Println(k, v) 192 | } 193 | 194 | } 195 | 196 | // 3. 流程控制 197 | func flowDemo() { 198 | // if else 199 | a := 10 200 | if a < 10 { 201 | // .. 202 | } else { 203 | // .. 204 | } 205 | 206 | // switch 207 | switch a { 208 | case 0: 209 | fmt.Println("0") 210 | case 10: 211 | fmt.Println("10") 212 | default: 213 | fmt.Println("default") 214 | } 215 | 216 | switch { 217 | case a < 10: 218 | fmt.Println("<10") 219 | case a < 20: 220 | fmt.Println("<20") 221 | } 222 | 223 | // 循环 224 | for i := 0; i < 10; i++ { 225 | } 226 | // 无限循环 227 | sum := 0 228 | for { 229 | sum++ 230 | if sum > 10 { 231 | break 232 | // 指定break 233 | // break JLoop 234 | } 235 | } 236 | 237 | goto JLoop 238 | 239 | JLoop: 240 | // break to here 241 | 242 | } 243 | 244 | // 4. 函数 245 | // func 函数名(参数列表)(返回值列表) { 246 | // } 247 | func sum1(value1 int, value2 int) (result int, err error) { 248 | // err = errors.New("xxxx") 249 | return value1 + value2, nil 250 | } 251 | 252 | func sum2(value1, value2 int) int { 253 | return value1 + value2 254 | } 255 | 256 | // 不定参数 257 | // myFunc(1, 2, 3, 4, 5) 258 | func myFunc(args ...int) { 259 | for _, arg := range args { 260 | fmt.Println(arg) 261 | } 262 | // 传递 263 | // myFunc2(args...) 264 | // myFunc2(args[1:]...) 265 | } 266 | 267 | // 任意类型的不定参数 268 | func myPrintf(args ...interface{}) { 269 | for _, arg := range args { 270 | switch arg.(type) { 271 | case int: 272 | fmt.Println(arg, "is int") 273 | case string: 274 | fmt.Println(arg, "is string") 275 | default: 276 | fmt.Println(arg, "is unknown") 277 | } 278 | } 279 | } 280 | 281 | // 匿名函数 282 | func anonymousFunc() { 283 | f := func(a, b int) int { 284 | return a + b 285 | } 286 | 287 | f(1, 2) 288 | } 289 | 290 | // defer 291 | func deferDemo(path string) { 292 | f, err := os.Open(path) 293 | if err != nil { 294 | return 295 | } 296 | 297 | defer f.Close() 298 | // or 299 | defer func() { 300 | if r := recover(); r != nil { 301 | fmt.Printf("Runtime error caught: %v", r) 302 | } 303 | }() 304 | } 305 | 306 | // 5. 结构体 307 | type Rect struct { 308 | // 小写为private 309 | x, y float64 310 | // 大写为public 311 | Width, Height float64 312 | } 313 | 314 | // 大写方法为public,小写为private 315 | func (r *Rect) Area() float64 { 316 | return r.Width * r.Height 317 | } 318 | 319 | func netRect(x, y, width, height float64) *Rect { 320 | // 实例化结构体 321 | // rect1 := new(Rect) 322 | // rect2 := &Rect{} 323 | // rect3 := &Rect{Width:100, Height:200} 324 | return &Rect{x, y, width, height} 325 | } 326 | 327 | // 匿名组合 328 | type Base struct { 329 | Name string 330 | } 331 | 332 | func (base *Base) Foo() {} 333 | func (base *Base) Bar() {} 334 | 335 | type Foo struct { 336 | Base 337 | *log.Logger 338 | } 339 | 340 | func (foo *Foo) Bar() { 341 | foo.Base.Bar() 342 | // ... 343 | } 344 | 345 | // 非侵入式接口 346 | type IFile interface { 347 | Read(buf []byte) (n int, err error) 348 | Write(buf []byte) (n int, err error) 349 | } 350 | 351 | type File struct { 352 | } 353 | 354 | func (file *File) Read(buf []byte) (n int, err error) { 355 | return 0, nil 356 | } 357 | 358 | func (file *File) Write(buf []byte) (n int, err error) { 359 | return 0, nil 360 | } 361 | 362 | func interfaceDemo() { 363 | // 只要实现了Read, Write方法即可 364 | var file IFile = new(File) 365 | 366 | // 接口查询 367 | // 是否实现了IFile接口 368 | if file2, ok := file.(IFile); ok { 369 | file2.Read([]byte{}) 370 | } 371 | // 实例类型是否是File 372 | if file3, ok := file.(*File); ok { 373 | file3.Read([]byte{}) 374 | } 375 | 376 | // 类型查询 377 | switch v := file.(type) { 378 | } 379 | } 380 | 381 | // 6. 并发编程 382 | func counting(ch chan int) { 383 | ch <- 1 384 | fmt.Println("counting") 385 | } 386 | 387 | func channelDemo() { 388 | chs := make([]chan int, 10) 389 | for i := 0; i < len(chs); i++ { 390 | chs[i] = make(chan int) 391 | // 带缓冲区大小 392 | // c: = make(chan int, 1024) 393 | // for i:= range c { 394 | // } 395 | go counting(chs[i]) 396 | } 397 | 398 | for _, ch := range chs { 399 | <-ch 400 | // channel select 401 | /* 402 | select { 403 | case <-ch: 404 | // ... 405 | case ch <- 1: 406 | } 407 | */ 408 | } 409 | 410 | // 单向Channel 411 | var ch1 chan<- int // 只能写入int 412 | var ch2 <-chan int // 只能读出int 413 | 414 | // 关闭Channel 415 | close(ch1) 416 | _, ok := <-ch2 417 | if !ok { 418 | // already closed 419 | } 420 | } 421 | 422 | // 锁 423 | var m sync.Mutex 424 | 425 | func lockDemo() { 426 | m.Lock() 427 | // do something 428 | defer m.Unlock() 429 | } 430 | 431 | // 全局唯一操作 432 | var once sync.Once 433 | 434 | // once.Do(someFunction) 435 | 436 | // 7. 网络编程 437 | // import "net" 438 | // net.Dial("tcp", "127.0.0.1:8080") 439 | 440 | // 8. json处理 441 | // import "encoding/json" 442 | // json.Marshal(obj) 序列化 443 | // json.Unmarshal() 反序列化 444 | 445 | // 9. Web开发 446 | // import "net/http" 447 | // 模板 448 | // import "html/template" 449 | 450 | // 10. 常用库 451 | // import "os" 452 | // import "io" 453 | // import "flag" 454 | // import "strconv" 455 | // import "crypto/sha1" 456 | // import "crypto/md5" 457 | 458 | // 11. 单元测试 459 | // _test结尾的go文件: xxx_test.go 460 | // 函数名以Test开头 461 | func TestDemo(t *testing.T) { 462 | r := sum2(2, 3) 463 | if r != 5 { 464 | t.Errorf("sum2(2, 3) failed. Got %d, expect 5.", r) 465 | } 466 | 467 | assert.Equal(t, 1, 1) 468 | } 469 | 470 | // 12. 性能测试 471 | func benchmarkAdd(b *testing.B) { 472 | b.StopTimer() 473 | // dosometing 474 | b.StartTimer() 475 | } 476 | 477 | /* 478 | 其他常用的代码片段 479 | */ 480 | 481 | // 1. 遍历文件 filepath.Walk 482 | // import "path/filepath" 483 | func doHashWalk(dirPath string) error { 484 | 485 | fullPath, err := filepath.Abs(dirPath) 486 | 487 | if err != nil { 488 | return err 489 | } 490 | 491 | callback := func(path string, fi os.FileInfo, err error) error { 492 | return hashFile(fullPath, path, fi, err) 493 | } 494 | 495 | return filepath.Walk(fullPath, callback) 496 | } 497 | 498 | func hashFile(root string, path string, fi os.FileInfo, err error) error { 499 | if fi.IsDir() { 500 | return nil 501 | } 502 | rel, err := filepath.Rel(root, path) 503 | if err != nil { 504 | return err 505 | } 506 | log.Println("hash rel:", rel, "abs:", path) 507 | return nil 508 | } 509 | 510 | // 2. 读取文件 511 | // import "io/ioutil" 512 | func readFileDemo(filename string) { 513 | content, err := ioutil.ReadFile(filename) 514 | if err != nil { 515 | //Do something 516 | } 517 | lines := strings.Split(string(content), "\n") 518 | fmt.Println("line count:", len(lines)) 519 | } 520 | 521 | // 判断目录或文件是否存在 522 | func existsPathCheck(path string) (bool, error) { 523 | // 判断不存在 524 | if _, err := os.Stat(path); os.IsNotExist(err) { 525 | // 不存在 526 | } 527 | 528 | // 判断是否存在 529 | _, err := os.Stat(path) 530 | if err == nil { 531 | return true, nil 532 | } 533 | if os.IsNotExist(err) { 534 | return false, nil 535 | } 536 | return true, err 537 | } 538 | 539 | // 文件目录操作 540 | func fileDirDemo() { 541 | // 级联创建目录 542 | os.MkdirAll("/path/to/create", 0777) 543 | } 544 | 545 | // 拷贝文件 546 | func copyFile(source string, dest string) (err error) { 547 | sf, err := os.Open(source) 548 | if err != nil { 549 | return err 550 | } 551 | defer sf.Close() 552 | df, err := os.Create(dest) 553 | if err != nil { 554 | return err 555 | } 556 | defer df.Close() 557 | _, err = io.Copy(df, sf) 558 | if err == nil { 559 | si, err := os.Stat(source) 560 | if err != nil { 561 | err = os.Chmod(dest, si.Mode()) 562 | } 563 | 564 | } 565 | return 566 | } 567 | 568 | // 拷贝目录 569 | func copyDir(source string, dest string) (err error) { 570 | fi, err := os.Stat(source) 571 | if err != nil { 572 | return err 573 | } 574 | if !fi.IsDir() { 575 | return errors.New(source + " is not a directory") 576 | } 577 | err = os.MkdirAll(dest, fi.Mode()) 578 | if err != nil { 579 | return err 580 | } 581 | entries, err := ioutil.ReadDir(source) 582 | for _, entry := range entries { 583 | sfp := filepath.Join(source, entry.Name()) 584 | dfp := filepath.Join(dest, entry.Name()) 585 | if entry.IsDir() { 586 | err = copyDir(sfp, dfp) 587 | if err != nil { 588 | fmt.Println(err) 589 | } 590 | } else { 591 | err = copyFile(sfp, dfp) 592 | if err != nil { 593 | fmt.Println(err) 594 | } 595 | } 596 | 597 | } 598 | return nil 599 | } 600 | 601 | // 3. 时间处理 602 | // import "time" 603 | func TestTimeDemo(t *testing.T) { 604 | // Parse 605 | postDate, err := time.Parse("2006-01-02 15:04:05", "2015-09-30 19:19:00") 606 | fmt.Println(postDate, err) 607 | 608 | // Format 609 | assert.Equal(t, "2015/Sep/30 07:19:00", postDate.Format("2006/Jan/02 03:04:05")) 610 | assert.Equal(t, "2015-09-30T19:19:00Z", postDate.Format(time.RFC3339)) 611 | } 612 | 613 | // 4. 正则表达式 614 | // import "regexp" 615 | func TestRegexp(t *testing.T) { 616 | // 查找匹配 617 | re := regexp.MustCompile(`(\d+)-(\d+)`) 618 | r := re.FindAllStringSubmatch("123-666", -1) 619 | 620 | assert.Equal(t, 1, len(r)) 621 | assert.Equal(t, "123", r[0][1]) 622 | assert.Equal(t, "666", r[0][2]) 623 | 624 | cjkRe := regexp.MustCompile(`\p{Han}|\p{Hangul}|\p{Hiragana}|\p{Katakana}`) 625 | 626 | assert.True(t, cjkRe.MatchString("中文")) 627 | assert.True(t, cjkRe.MatchString("도형이")) 628 | assert.True(t, cjkRe.MatchString("カテゴリー")) 629 | assert.False(t, cjkRe.MatchString("abc")) 630 | } 631 | 632 | func main() { 633 | helloWorld() 634 | } 635 | -------------------------------------------------------------------------------- /swift.swift: -------------------------------------------------------------------------------- 1 | /* 2 | swift.playground: 3 | Swift 速学速查速用代码手册 4 | Source: github.com/coderzh/CodeTips/blob/master/swift.swift 5 | Author: coderzh(github.com/coderzh) 6 | Blog: http://blog.coderzh.com 7 | 参考:《Swift Programming Language》 8 | */ 9 | 10 | import Cocoa 11 | 12 | // 0. 注释 13 | /* 14 | 块注释 15 | 行尾分号可不用 16 | */ 17 | 18 | // 1. Hello World 19 | print("Hello Swift") 20 | 21 | // 2. 常量变量类型 22 | let constValue = 3.14 23 | var variable = 18 24 | 25 | variable += 1 26 | 27 | // 指定类型 28 | let age: Int = 18 29 | // 多重赋值 30 | var (a, b) = (1, 2) 31 | // 匿名占位符 32 | (_, b) = (3, 4) 33 | 34 | // 类型会自动推导 35 | let name = "It's a string" 36 | let gravity = 0.98 // 默认 double 37 | 38 | // 永远不做隐式转换,必须自己强转 39 | let sum = Double(age) + gravity 40 | 41 | // 运算:+, -, *, /, % 求余 42 | // 比较:<, >, ==, >=, <=, != 43 | // === 恒等,是否为同一个对象 44 | // !== 不恒等 45 | // 位运算:~x 取反,& 与,| 或,^ 异或,<< 左移动,>> 右移 46 | // 溢出运算符 &+ &- &* &/ &% ,这样溢出部分就会丢掉,不会出错,比如: 47 | var willOverflow = UInt8.max 48 | willOverflow = willOverflow &+ 1 // = 0 49 | 50 | // 类型 51 | let b1 = true 52 | let i32: Int32 = 6 53 | let f64: Float64 = 3.1415 54 | 55 | // 字符串 56 | let str = "swift" 57 | // 字符串连接,使用\() 58 | var hello = "hello \(str)" 59 | let count = str.characters.count 60 | let c = hello[hello.startIndex] 61 | for i in hello.characters.indices { 62 | print("\(hello[i])") 63 | } 64 | 65 | hello.insert("!", atIndex: hello.endIndex) 66 | hello.insertContentsOf(" there".characters, at: hello.endIndex.predecessor()) 67 | hello.removeAtIndex(hello.endIndex.predecessor()) 68 | hello.hasPrefix("hello") 69 | hello.hasSuffix("swift") 70 | 71 | let unicode = "你好 swift" 72 | unicode.characters.count // 8 73 | 74 | for codeUnit in unicode.utf8 { 75 | print("\(codeUnit)", terminator: "") 76 | } 77 | if hello == unicode{ 78 | 79 | } 80 | 81 | // 数组 82 | var shoppingList = ["test", "book", "bike"] 83 | shoppingList[2] = "joke" 84 | shoppingList.append("bus") 85 | shoppingList.insert("foo", atIndex: 0) 86 | shoppingList.removeAtIndex(0) 87 | 88 | // 类似 slice 89 | shoppingList[0..<2] // ["test", "book"] 90 | shoppingList[0...2] // ["test", "book", "joke"] 91 | 92 | for item in shoppingList { 93 | print(item) 94 | } 95 | 96 | for (index, value) in shoppingList.enumerate() { 97 | print("\(index): \(value)") 98 | } 99 | 100 | let emptyArray = [String]() 101 | var someInts = [Int]() 102 | var someInts2 = [Int](count: 3, repeatedValue: 8) // [8, 8, 8] 103 | var someInts3 = [Int](count: 3, repeatedValue: 2) 104 | 105 | // 任意类型数组 106 | var anyArray = [Any]() 107 | anyArray.append(1) 108 | anyArray.append("book") 109 | 110 | someInts = someInts2 + someInts3 // [8, 8, 8, 2, 2, 2] 111 | 112 | // 元组 113 | let httpResponse = (404, "Not Found") 114 | print(httpResponse.0) 115 | 116 | // 集合 Sets 117 | var setBooks: Set = ["book1", "book2"] 118 | // 自动推导 119 | var setBooks2: Set = ["book1", "book2", "book3"] 120 | 121 | setBooks.intersect(setBooks2) // 交集 122 | setBooks.exclusiveOr(setBooks2) // 非交集 123 | setBooks.union(setBooks2) // 并集 124 | setBooks.subtract(setBooks2) // 减集 125 | 126 | setBooks.isSubsetOf(setBooks2) 127 | setBooks2.isSupersetOf(setBooks) 128 | setBooks.isStrictSubsetOf(setBooks2) // 被包含且不相等 129 | 130 | // 字典 131 | var map = [ 132 | "Malcolm": "hehe", 133 | "Keylee": 123, 134 | ] 135 | map["Keylee"] = 166 136 | 137 | var namesOfInt = [Int: String]() 138 | namesOfInt[10] = "ten" 139 | 140 | if let oldValue = namesOfInt.updateValue("Ten", forKey: 10) { 141 | print("\(oldValue)") 142 | } 143 | 144 | if let name = namesOfInt[8] { 145 | print("\(name)") 146 | } else { 147 | print("not exist 8") 148 | } 149 | 150 | for (intKey, strValue) in namesOfInt { 151 | print("\(intKey):\(strValue)") 152 | } 153 | 154 | // namsOfInt.values 155 | for intKeys in namesOfInt.keys { 156 | 157 | } 158 | 159 | let intKeys = [Int](namesOfInt.keys) 160 | 161 | // 可空变量,用 ? 162 | var optionalString: String? = nil 163 | 164 | if let name = optionalString { 165 | print("hello \(name)") 166 | } 167 | 168 | // 3. 流程控制 169 | // 循环 170 | // [0, 4) 171 | for i in 0..<4 { 172 | print("print \(i)") // 4 times 173 | } 174 | 175 | // [0, 4] 176 | for i in 0...4 { 177 | print("print \(i)") // 5 times 178 | } 179 | 180 | var i = 0 181 | while i < 2 { 182 | print("\(i)") 183 | i += 1 184 | } 185 | 186 | repeat { 187 | print("\(i)") 188 | i += 1 189 | } while i < 5 190 | 191 | // 判断 192 | if i < 5 { 193 | 194 | } else if i < 10 { 195 | 196 | } else { 197 | 198 | } 199 | 200 | // 强大的 switch 201 | // 不需要 break 202 | switch i { 203 | case 1, 2, 3: 204 | print("123") 205 | case 5: 206 | print("5") 207 | case 6..<10: 208 | print("6-9") 209 | default: 210 | print("default") 211 | } 212 | 213 | let somePoint = (1, 1) 214 | 215 | switch somePoint { 216 | case (0, 0): 217 | print("0, 0") 218 | case (_, 1): 219 | print("y is 1") 220 | case (-2...2, -2...2): // 区间 221 | print("from (-2,-2) to (2, 2)") 222 | case (let x, 0): // 值绑定 223 | print("\(x)") 224 | case let (x, y) where x == y: // where 225 | print("x == y") 226 | case (10, 11): 227 | fallthrough // 贯穿,继续向下 228 | default: 229 | print("default") 230 | } 231 | 232 | // 控制转移 233 | // continue break fallthrough retrun throw 234 | 235 | // 带标签 236 | i = 0 237 | gameLoop: while i > -1 { 238 | i = i + 1 239 | if i > 3 { 240 | break gameLoop 241 | } 242 | } 243 | 244 | // 提前退出(提前返回) 245 | func greet(person: [String:String]) { 246 | guard let name = person["name"] else { 247 | return 248 | } 249 | print("\(name)") 250 | } 251 | 252 | greet(["age":"18"]) 253 | 254 | // 4. 函数 255 | func greet(name: String, day: String) { 256 | print("Hello \(name), today is \(day)") 257 | } 258 | 259 | // 第二个参数默认需要指定名称 260 | greet("tom", day: "2016") 261 | 262 | func sum(a: Int, b: Int) -> Int { 263 | return a + b 264 | } 265 | 266 | sum(1, b: 2) 267 | 268 | // 多重返回值 269 | func minMax(array: [Int]) -> (min: Int, max: Int) { 270 | // ... 271 | return (0, 1) 272 | } 273 | 274 | // 可选返回值加 ? 275 | func minMax2(array: [Int]) -> (min: Int, max: Int)? { 276 | if array.isEmpty { return nil } 277 | return (0, 1) 278 | } 279 | 280 | // 指定外部参数名 281 | func sayHello(to person: String, and anotherPerson: String) { 282 | print("Hello \(person) and \(anotherPerson)") 283 | } 284 | 285 | sayHello(to: "coderzh", and: "tom") 286 | 287 | // 忽略外部参数名,使用 _ 288 | func sayHello2(person: String, _ anotherPerson: String) { 289 | print("Hello \(person) and \(anotherPerson)") 290 | } 291 | 292 | sayHello2("coderzh", "jack") 293 | 294 | // 默认参数 295 | func someFunction(p: Int = 10) { 296 | print("\(p)") 297 | } 298 | 299 | someFunction() 300 | 301 | // 可变参数 302 | func sum(numbers: Int...) -> Int { 303 | var total = 0 304 | for n in numbers { 305 | total += n 306 | } 307 | 308 | return total 309 | } 310 | 311 | sum(1, 2, 3, 4, 5) 312 | 313 | // 参数默认是常量类型,如需指定变量类型,前面加 var(swift 3 将移除 var) 314 | func alignRight(var string: String, totalLength: Int, pad: Character) -> String { 315 | string = string + "!" 316 | return string 317 | } 318 | 319 | // 传入传出参数 inout 320 | func swap(inout a: Int, inout _ b: Int) { 321 | let temp = a 322 | a = b 323 | b = temp 324 | } 325 | 326 | var someInt = 7 327 | var anotherInt = 8 328 | 329 | // inout 参数必须加 & 330 | swap(&someInt, &anotherInt) 331 | 332 | // 函数类型,函数变量 333 | var sumFunc: (Int, Int) -> Int = sum 334 | sumFunc(1, 2) 335 | 336 | // 函数可做参数 337 | func doSum(handler:(Int, Int) -> Int, _ a: Int, _ b: Int) { 338 | handler(a, b) 339 | } 340 | 341 | // 函数可做返回值 342 | func getSum() -> (Int, Int) -> Int { 343 | // 函数可嵌套 344 | func someFunc(a: Int, b: Int) -> Int { return a + b } 345 | return someFunc 346 | } 347 | 348 | doSum(sum, 2, 3) 349 | 350 | // 闭包 351 | // 闭包是引用类型 352 | let reversed2 = shoppingList.sort({a, b in a < b}) 353 | let r = shoppingList.sort({ $0 < $1 }) 354 | let r2 = shoppingList.sort(<) 355 | let r3 = shoppingList.sort{ $0 < $1 } 356 | 357 | // 非逃逸闭包(noescape closure) 358 | // 闭包只能在函数内执行,不能「逃逸」出去 359 | func someClosure(@noescape closure: () -> Void) { 360 | closure() 361 | } 362 | 363 | // 自动闭包(这样不用写花括号了?) 364 | func autoClosure(@autoclosure provider: () -> String) { 365 | provider() 366 | } 367 | 368 | autoClosure(shoppingList.removeAtIndex(0)) 369 | 370 | // 5. 枚举(一等公民,十分强大) 371 | // 值类型 372 | enum Rank: Int { 373 | case Ace = 1 374 | case Two, Three 375 | } 376 | 377 | var ace = Rank.Ace // Ace 378 | Rank.Ace.rawValue // 1 379 | let ace1 = Rank(rawValue: 1) // Ace 380 | ace = .Two 381 | 382 | enum ServerResponse { 383 | case Result(String, String) 384 | case Error(String) 385 | } 386 | 387 | // 可失败构造器 388 | enum TemperatureUnit { 389 | case Kelvin, Celsius, Fahrenheit 390 | init?(symbol: Character) { 391 | switch symbol { 392 | case "K": 393 | self = .Kelvin 394 | case "C": 395 | self = .Celsius 396 | case "F": 397 | self = .Fahrenheit 398 | default: 399 | return nil 400 | } 401 | } 402 | } 403 | 404 | 405 | let success = ServerResponse.Result("6:00am", "6:00pm") 406 | let failure = ServerResponse.Error("Out of cheese") 407 | 408 | switch success { 409 | case let .Result(sunrise, sunset): 410 | let serverResponse = "sunrise at \(sunrise), sunset at \(sunset)" 411 | case let .Error(error): 412 | let serverResponse = "Error \(error)" 413 | } 414 | 415 | // 枚举递归... 416 | enum ArithmeticExpression { 417 | case Number(Int) 418 | indirect case Addition(ArithmeticExpression, ArithmeticExpression) 419 | indirect case Multiplication(ArithmeticExpression, ArithmeticExpression) 420 | } 421 | 422 | func evaluate(expression: ArithmeticExpression) -> Int { 423 | switch expression { 424 | case .Number(let value): 425 | return value 426 | case .Addition(let left, let right): 427 | return evaluate(left) + evaluate(right) 428 | case .Multiplication(let left, let right): 429 | return evaluate(left) * evaluate(right) 430 | } 431 | } 432 | 433 | // 计算 (5 + 4) * 2 434 | let five = ArithmeticExpression.Number(5) 435 | let four = ArithmeticExpression.Number(4) 436 | let sum2 = ArithmeticExpression.Addition(five, four) 437 | let product = ArithmeticExpression.Multiplication(sum2, ArithmeticExpression.Number(2)) 438 | print(evaluate(product)) // 输出 "18” 439 | 440 | // 6. 类和结构体 441 | // 结构体是值类型,类是引用类型 442 | class SomeClass { 443 | var width = 0 444 | var height = 0 445 | 446 | // class 不需要 mutating 447 | func incrementWidth() { 448 | self.width += 1 449 | } 450 | 451 | // 下标操作: [n] 452 | subscript(index: Int) -> Int { 453 | get { 454 | return 0 455 | } 456 | set(newValue) { 457 | // set from newValue 458 | } 459 | } 460 | } 461 | 462 | let s1 = SomeClass() 463 | 464 | struct SomeStruct { 465 | static var someValue = 100 466 | static func staticFunc() -> Int { 467 | return 1 468 | } 469 | 470 | var x = 0 471 | var y = 0 472 | 473 | var doubleX: Int { 474 | get { 475 | return x * 2 476 | } 477 | set { 478 | x = newValue / 2 479 | } 480 | } 481 | 482 | // readonly 483 | var doubleY: Int { 484 | return y * 2 485 | } 486 | 487 | var total: Int { 488 | willSet(newTotal) { 489 | print("will set \(newTotal)") 490 | } 491 | 492 | didSet { 493 | print("old: \(oldValue), new: \(total)") 494 | } 495 | } 496 | 497 | // 如果会改变类成员,比如声明 mutating 498 | mutating func incrementX() { 499 | self.x += 1 500 | } 501 | } 502 | 503 | var s2 = SomeStruct(x: 2, y: 3, total: 10) 504 | s2.doubleX = 10 // s2.x == 5 505 | s2.total = 5 506 | 507 | // 继承 508 | class Animal { 509 | // 构造函数 510 | init() { 511 | 512 | } 513 | 514 | // 必要构造器,子类必须实现,而且声明为 required 515 | required init(name: String, age: Int) { 516 | 517 | } 518 | 519 | func makeNoise() { 520 | print("wowowo") 521 | } 522 | } 523 | 524 | class Cat: Animal { 525 | var name: String = "" 526 | var nickName: String = "" 527 | 528 | init(name: String) { 529 | super.init() 530 | self.name = name 531 | } 532 | 533 | init(fromNickName nickName: String) { 534 | super.init(name: nickName, age: 18) 535 | self.nickName = nickName 536 | } 537 | 538 | // 便利构造器:必须调用其他构造器 539 | convenience override init() { 540 | self.init(name: "UnKnown") 541 | } 542 | 543 | // 可失败构造器 544 | init?(age: Int) { 545 | super.init(name: "UnKnown", age: age) 546 | if age < 0 { return nil } 547 | } 548 | 549 | required init(name: String, age: Int) { 550 | self.name = name 551 | super.init(name: name, age: age) 552 | } 553 | 554 | // 析构,默认会先调用父类的析构 555 | deinit { 556 | 557 | } 558 | 559 | override func makeNoise() { 560 | print("miaomiaomiao") 561 | } 562 | } 563 | 564 | final class CannotInheirt { 565 | 566 | } 567 | 568 | // 7. 自动引用计数 ARC 569 | // weak 弱引用 570 | // unowned 无主引用 571 | 572 | // 8. 可空链式调用 573 | /* For example: 574 | if let johnsStreet = john.residence?.address?.street { 575 | print("John's street name is \(johnsStreet).") 576 | } else { 577 | print("Unable to retrieve the address.") 578 | } 579 | */ 580 | // 如果确定有值,使用! 581 | // let roomCount = john.residence!.numberOfRooms 582 | 583 | 584 | // 9. 错误处理 585 | 586 | enum CustomError : ErrorType { 587 | case Invalid 588 | case OutOfRange 589 | } 590 | 591 | func makeASandwich() throws -> String { 592 | throw CustomError.Invalid 593 | } 594 | 595 | do { 596 | try makeASandwich() 597 | } catch CustomError.Invalid { 598 | print("Invalid") 599 | } 600 | 601 | // 可空 602 | let x = try? makeASandwich() 603 | // 使错误传递失效,肯定不throw,否则 assert 604 | // let y = try! makeASandwich() 605 | 606 | // defer 和 Golang 里的 defer 一样,用来退出清理 607 | /* 608 | func processFile(filename: String) throws { 609 | if exists(filename) { 610 | let file = open(filename) 611 | defer { 612 | close(file) 613 | } 614 | while let line = try file.readline() { 615 | // 处理文件 616 | } 617 | // 在这里,作用域的最后调用 close(file) 618 | } 619 | } 620 | */ 621 | 622 | // 10. 类型转换: is as (和 CSharp 类似) 623 | // 任意类型: 624 | // 1. AnyObject 任何 class 类型实例 625 | // 2. Any 任何类型 626 | 627 | // 11. 扩展(extension,类似 CSharp 里的扩展方法,但是貌似更强大) 628 | // 比如:扩展内置类型 Double 629 | // 几乎一切都可扩展,用到时再查用法吧 630 | extension Double { 631 | var km: Double { return self * 1_000.0 } 632 | var m : Double { return self } 633 | var cm: Double { return self / 100.0 } 634 | var mm: Double { return self / 1_000.0 } 635 | var ft: Double { return self / 3.28084 } 636 | } 637 | 638 | // 12. 协议(类似接口的东西) 639 | // 当同时有继承时,先写继承,再写协议,协议可以有多个 640 | protocol FullyNamed { 641 | var fullName: String { get } 642 | } 643 | 644 | // 协议也可继承 645 | protocol SubFullyNamed: FullyNamed { 646 | var nickName: String { get } 647 | } 648 | 649 | struct Person: FullyNamed{ 650 | var fullName: String 651 | } 652 | 653 | // 专属协议,指定只能用在 class 上 654 | protocol ClassOnlyProtocol: class, FullyNamed { 655 | 656 | } 657 | 658 | protocol Aged { 659 | var age: Int { get set } 660 | } 661 | 662 | // 协议合成 663 | func foo(pro: protocol, base: Any) { 664 | // 协议判断 665 | if let p = base as? Aged { 666 | print(p.age) 667 | } 668 | } 669 | 670 | // 可选协议(既然是协议,还可选,醉了) 671 | // @objc protocol 672 | 673 | // 13. 泛型 674 | func swapTwoValues(inout a: T, inout _ b: T) { 675 | let temporaryA = a 676 | a = b 677 | b = temporaryA 678 | } 679 | 680 | // 泛型约束 681 | func someFunction(someT: T, someU: U) { 682 | // 这里是函数主体 683 | } 684 | 685 | // Where 686 | /* 687 | func allItemsMatch< 688 | C1: Container, C2: Container 689 | where C1.ItemType == C2.ItemType, C1.ItemType: Equatable> 690 | (someContainer: C1, anotherContainer: C2) -> Bool { 691 | } 692 | */ 693 | 694 | // 14. 访问控制 695 | // public internal(默认) private 696 | // 加在 class var 等前 697 | --------------------------------------------------------------------------------