├── .DS_Store ├── .idea ├── book.iml ├── misc.xml ├── modules.xml ├── vcs.xml └── workspace.xml ├── README.md ├── ch03 ├── 3.1 │ ├── array │ │ └── main.go │ └── strings │ │ └── main.go ├── 3.2 │ ├── append │ │ └── main.go │ ├── copy │ │ └── main.go │ └── slicebase │ │ └── main.go ├── 3.3 │ └── main.go └── 3.4 │ ├── compli │ └── main.go │ └── pointer │ └── main.go ├── ch04 ├── 4.1 │ ├── argu │ │ └── main.go │ ├── clo │ │ └── main.go │ └── clo2 │ │ └── main.go ├── 4.2 │ ├── base │ │ └── main.go │ ├── extends │ │ └── main.go │ └── pointer │ │ └── main.go ├── 4.3 │ ├── adv │ │ └── main.go │ └── base │ │ └── myinterface.go └── 4.4 │ ├── adv │ └── main.go │ └── main.go ├── ch05 ├── 5.1 │ ├── adv1 │ │ └── main.go │ ├── adv2 │ │ └── main.go │ ├── base │ │ └── main.go │ └── sync │ │ └── main.go ├── 5.2 │ ├── buffer │ │ └── main.go │ ├── read │ │ └── main.go │ ├── select │ │ └── main.go │ ├── timeout1 │ │ └── main.go │ ├── timeout2 │ │ └── main.go │ └── write │ │ └── main.go └── 5.3 │ └── main.go ├── ch06 ├── .DS_Store ├── 6.2 │ ├── cpu.svg │ ├── cpu_profile.prof │ ├── mem.png │ ├── mem.svg │ ├── mem_profile1.prof │ ├── mem_profile2.prof │ ├── mem_profile3.prof │ ├── mem_profile4.prof │ └── profile.go └── 6.3 │ ├── bhmark │ ├── bhmark │ ├── testBenchmark.go │ └── testBenchmark_test.go │ ├── example │ ├── exam_test.go │ └── testExam.go │ └── test │ ├── testTest.go │ └── testTest_test.go ├── ch08 ├── 8.2 │ ├── RWMutex │ │ └── rwmutex.go │ ├── cond │ │ └── cond.go │ ├── map │ │ └── map.go │ ├── mutex │ │ └── mutex.go │ ├── once │ │ └── once.go │ └── pool │ │ └── pool.go ├── 8.3 │ ├── advanced │ │ └── context.go │ └── context.go ├── 8.4 │ ├── simple │ │ └── workpool.go │ └── workpool.go └── race │ └── datarace.go ├── ch09 ├── 9.1 │ └── httpDemo.go ├── 9.2 │ └── httprouter.go ├── 9.3 │ ├── tcpClient │ │ └── tcpClient.go │ ├── tcpServer │ │ └── tcpServer.go │ ├── udpClient │ │ └── udpClient.go │ ├── udpServer │ │ └── udpServer.go │ └── websocket │ │ ├── index.html │ │ └── ws.go └── 9.4 │ ├── adv │ └── adv.go │ ├── basic │ └── basicmiddle.go │ └── nomiddle.go ├── ch13 ├── 13.2 │ ├── main.go │ └── protocol │ │ ├── test.pb.go │ │ └── test.proto └── 13.3 │ ├── grpc │ ├── client │ │ └── client.go │ ├── protocol │ │ ├── hello.pb.go │ │ └── hello.proto │ └── server │ │ └── server.go │ └── rpc │ ├── client │ └── client.go │ └── server │ └── server.go ├── chapter0 └── sample.go └── chapter01 ├── 1.1 ├── helloserver │ └── main.go └── helloworld │ ├── hello │ └── hello.go ├── 1.2 ├── iota │ └── main.go ├── pointer │ └── main.go └── var │ └── main.go └── 1.4 └── loop.go /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottAI/book/5851b283d7dbfb91b42f5f4f1da4fbe6aec3acb4/.DS_Store -------------------------------------------------------------------------------- /.idea/book.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # book 2 | 本仓库是本人的出版书籍《Go微服务实战》的配套示例代码。 3 | 读者在使用过程中有任何问题可以提出issue,便于在加印时修正。 4 | 5 | 感谢读者的支持! 6 | -------------------------------------------------------------------------------- /ch03/3.1/array/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | a := [...]int{1,2,3,4} 7 | b := &a 8 | fmt.Println(a[0],a[1]) 9 | fmt.Println(b[0],b[1]) 10 | var s = [...]string{"hello","世界"} 11 | for i,v := range s { 12 | fmt.Printf("s[%d]:%s\n",i,v) 13 | } 14 | for i:=0;i 2 | 4 | 6 | 7 | 8 | 297 | unnamed 298 | 299 | 300 | cluster_L 301 | 302 | 303 | 304 | 305 | Type: cpu 306 | 307 | Type: cpu 308 | Time: Aug 27, 2019 at 9:01am (CST) 309 | Duration: 15.12s, Total samples = 25.55s (169.03%) 310 | Showing nodes accounting for 25.30s, 99.02% of 25.55s total 311 | Dropped 10 nodes (cum <= 0.13s) 312 | 313 | 314 | 315 | N1 316 | 317 | 318 | runtime 319 | pthread_cond_signal 320 | 12.19s (47.71%) 321 | 322 | 323 | 324 | 325 | 326 | N2 327 | 328 | 329 | runtime 330 | pthread_cond_wait 331 | 7.41s (29.00%) 332 | 333 | 334 | 335 | 336 | 337 | N3 338 | 339 | 340 | runtime 341 | usleep 342 | 4.72s (18.47%) 343 | of 4.73s (18.51%) 344 | 345 | 346 | 347 | 348 | 349 | N4 350 | 351 | 352 | runtime 353 | mstart 354 | 0 of 11.07s (43.33%) 355 | 356 | 357 | 358 | 359 | 360 | N34 361 | 362 | 363 | runtime 364 | systemstack 365 | 0 of 11.06s (43.29%) 366 | 367 | 368 | 369 | 370 | 371 | N4->N34 372 | 373 | 374 | 375 | 376 | 377 | 378 | 11.06s 379 | 380 | 381 | 382 | 383 | 384 | N5 385 | 386 | 387 | runtime 388 | mcall 389 | 0 of 10.89s (42.62%) 390 | 391 | 392 | 393 | 394 | 395 | N28 396 | 397 | 398 | runtime 399 | park_m 400 | 0 of 10.89s (42.62%) 401 | 402 | 403 | 404 | 405 | 406 | N5->N28 407 | 408 | 409 | 410 | 411 | 412 | 413 | 10.89s 414 | 415 | 416 | 417 | 418 | 419 | N6 420 | 421 | 422 | runtime 423 | findrunnable 424 | 0 of 9.59s (37.53%) 425 | 426 | 427 | 428 | 429 | 430 | N31 431 | 432 | 433 | runtime 434 | runqsteal 435 | 0 of 2.20s (8.61%) 436 | 437 | 438 | 439 | 440 | 441 | N6->N31 442 | 443 | 444 | 445 | 446 | 447 | 448 | 2.20s 449 | 450 | 451 | 452 | 453 | 454 | N33 455 | 456 | 457 | runtime 458 | stopm 459 | 0 of 7.39s (28.92%) 460 | 461 | 462 | 463 | 464 | 465 | N6->N33 466 | 467 | 468 | 469 | 470 | 471 | 472 | 7.39s 473 | 474 | 475 | 476 | 477 | 478 | N7 479 | 480 | 481 | runtime 482 | wakep 483 | 0 of 12.35s (48.34%) 484 | 485 | 486 | 487 | 488 | 489 | N32 490 | 491 | 492 | runtime 493 | startm 494 | 0 of 12.35s (48.34%) 495 | 496 | 497 | 498 | 499 | 500 | N7->N32 501 | 502 | 503 | 504 | 505 | 506 | 507 | 12.35s 508 | 509 | 510 | 511 | 512 | 513 | N8 514 | 515 | 516 | runtime 517 | schedule 518 | 0 of 10.89s (42.62%) 519 | 520 | 521 | 522 | 523 | 524 | N8->N6 525 | 526 | 527 | 528 | 529 | 530 | 531 | 9.59s 532 | 533 | 534 | 535 | 536 | 537 | N21 538 | 539 | 540 | runtime 541 | resetspinning 542 | 0.01s (0.039%) 543 | of 1.30s (5.09%) 544 | 545 | 546 | 547 | 548 | 549 | N8->N21 550 | 551 | 552 | 553 | 554 | 555 | 556 | 1.30s 557 | 558 | 559 | 560 | 561 | 562 | N9 563 | 564 | 565 | runtime 566 | semawakeup 567 | 0 of 12.61s (49.35%) 568 | 569 | 570 | 571 | 572 | 573 | N9->N1 574 | 575 | 576 | 577 | 578 | 579 | 580 | 12.19s 581 | 582 | 583 | 584 | 585 | 586 | N13 587 | 588 | 589 | runtime 590 | pthread_mutex_lock 591 | 0.34s (1.33%) 592 | 593 | 594 | 595 | 596 | 597 | N9->N13 598 | 599 | 600 | 601 | 602 | 603 | 604 | 0.34s 605 | 606 | 607 | 608 | 609 | 610 | N10 611 | 612 | 613 | runtime 614 | main 615 | 0 of 3.14s (12.29%) 616 | 617 | 618 | 619 | 620 | 621 | N22 622 | 623 | 624 | main 625 | main 626 | 0 of 3.14s (12.29%) 627 | 628 | 629 | 630 | 631 | 632 | N10->N22 633 | 634 | 635 | 636 | 637 | 638 | 639 | 3.14s 640 | 641 | 642 | 643 | 644 | 645 | N11 646 | 647 | 648 | runtime 649 | selectgo 650 | 0.09s (0.35%) 651 | of 3.09s (12.09%) 652 | 653 | 654 | 655 | 656 | 657 | N14 658 | 659 | 660 | runtime 661 | unlock 662 | 0.09s (0.35%) 663 | of 0.35s (1.37%) 664 | 665 | 666 | 667 | 668 | 669 | N11->N14 670 | 671 | 672 | 673 | 674 | 675 | 676 | 0.10s 677 | 678 | 679 | 680 | 681 | 682 | N17 683 | 684 | 685 | runtime 686 | (*waitq) 687 | dequeue 688 | 0.22s (0.86%) 689 | 690 | 691 | 692 | 693 | 694 | N11->N17 695 | 696 | 697 | 698 | 699 | 700 | 701 | 0.22s 702 | 703 | 704 | 705 | 706 | 707 | N20 708 | 709 | 710 | runtime 711 | sellock 712 | 0.02s (0.078%) 713 | of 2.61s (10.22%) 714 | 715 | 716 | 717 | 718 | 719 | N11->N20 720 | 721 | 722 | 723 | 724 | 725 | 726 | 2.61s 727 | 728 | 729 | 730 | 731 | 732 | N12 733 | 734 | 735 | runtime 736 | lock 737 | 0.13s (0.51%) 738 | of 2.76s (10.80%) 739 | 740 | 741 | 742 | 743 | 744 | N27 745 | 746 | 747 | runtime 748 | osyield 749 | 0 of 2.53s (9.90%) 750 | 751 | 752 | 753 | 754 | 755 | N12->N27 756 | 757 | 758 | 759 | 760 | 761 | 762 | 2.53s 763 | 764 | 765 | 766 | 767 | 768 | N14->N9 769 | 770 | 771 | 772 | 773 | 774 | 775 | 0.26s 776 | 777 | 778 | 779 | 780 | 781 | N15 782 | 783 | 784 | runtime 785 | chansend 786 | 0.02s (0.078%) 787 | of 0.44s (1.72%) 788 | 789 | 790 | 791 | 792 | 793 | N15->N12 794 | 795 | 796 | 797 | 798 | 799 | 800 | 0.17s 801 | 802 | 803 | 804 | 805 | 806 | N15->N14 807 | 808 | 809 | 810 | 811 | 812 | 813 | 0.25s 814 | 815 | 816 | 817 | 818 | 819 | N16 820 | 821 | 822 | main 823 | runcputest 824 | 0.01s (0.039%) 825 | of 0.45s (1.76%) 826 | 827 | 828 | 829 | 830 | 831 | N23 832 | 833 | 834 | runtime 835 | chansend1 836 | 0 of 0.44s (1.72%) 837 | 838 | 839 | 840 | 841 | 842 | N16->N23 843 | 844 | 845 | 846 | 847 | 848 | 849 | 0.44s 850 | 851 | 852 | 853 | 854 | 855 | N18 856 | 857 | 858 | main 859 | procmsg 860 | 0.05s (0.2%) 861 | of 3.14s (12.29%) 862 | 863 | 864 | 865 | 866 | 867 | N18->N11 868 | 869 | 870 | 871 | 872 | 873 | 874 | 3.09s 875 | 876 | 877 | 878 | 879 | 880 | N19 881 | 882 | 883 | runtime 884 | semasleep 885 | 0 of 7.41s (29.00%) 886 | 887 | 888 | 889 | 890 | 891 | N19->N2 892 | 893 | 894 | 895 | 896 | 897 | 898 | 7.41s 899 | 900 | 901 | 902 | 903 | 904 | N20->N12 905 | 906 | 907 | 908 | 909 | 910 | 911 | 2.59s 912 | 913 | 914 | 915 | 916 | 917 | N21->N7 918 | 919 | 920 | 921 | 922 | 923 | 924 | 1.29s 925 | 926 | 927 | 928 | 929 | 930 | N22->N18 931 | 932 | 933 | 934 | 935 | 936 | 937 | 3.14s 938 | 939 | 940 | 941 | 942 | 943 | N23->N15 944 | 945 | 946 | 947 | 948 | 949 | 950 | 0.44s 951 | 952 | 953 | 954 | 955 | 956 | N24 957 | 958 | 959 | runtime 960 | goready 961 | func1 962 | 0 of 11.06s (43.29%) 963 | 964 | 965 | 966 | 967 | 968 | N29 969 | 970 | 971 | runtime 972 | ready 973 | 0 of 11.06s (43.29%) 974 | 975 | 976 | 977 | 978 | 979 | N24->N29 980 | 981 | 982 | 983 | 984 | 985 | 986 | 11.06s 987 | 988 | 989 | 990 | 991 | 992 | N25 993 | 994 | 995 | runtime 996 | notesleep 997 | 0 of 7.39s (28.92%) 998 | 999 | 1000 | 1001 | 1002 | 1003 | N25->N19 1004 | 1005 | 1006 | 1007 | 1008 | 1009 | 1010 | 7.39s 1011 | 1012 | 1013 | 1014 | 1015 | 1016 | N26 1017 | 1018 | 1019 | runtime 1020 | notewakeup 1021 | 0 of 12.35s (48.34%) 1022 | 1023 | 1024 | 1025 | 1026 | 1027 | N26->N9 1028 | 1029 | 1030 | 1031 | 1032 | 1033 | 1034 | 12.35s 1035 | 1036 | 1037 | 1038 | 1039 | 1040 | N27->N3 1041 | 1042 | 1043 | 1044 | 1045 | 1046 | 1047 | 2.53s 1048 | 1049 | 1050 | 1051 | 1052 | 1053 | N28->N8 1054 | 1055 | 1056 | 1057 | 1058 | 1059 | 1060 | 10.89s 1061 | 1062 | 1063 | 1064 | 1065 | 1066 | N29->N7 1067 | 1068 | 1069 | 1070 | 1071 | 1072 | 1073 | 11.06s 1074 | 1075 | 1076 | 1077 | 1078 | 1079 | N30 1080 | 1081 | 1082 | runtime 1083 | runqgrab 1084 | 0 of 2.20s (8.61%) 1085 | 1086 | 1087 | 1088 | 1089 | 1090 | N30->N3 1091 | 1092 | 1093 | 1094 | 1095 | 1096 | 1097 | 2.20s 1098 | 1099 | 1100 | 1101 | 1102 | 1103 | N31->N30 1104 | 1105 | 1106 | 1107 | 1108 | 1109 | 1110 | 2.20s 1111 | 1112 | 1113 | 1114 | 1115 | 1116 | N32->N26 1117 | 1118 | 1119 | 1120 | 1121 | 1122 | 1123 | 12.35s 1124 | 1125 | 1126 | 1127 | 1128 | 1129 | N33->N25 1130 | 1131 | 1132 | 1133 | 1134 | 1135 | 1136 | 7.39s 1137 | 1138 | 1139 | 1140 | 1141 | 1142 | N34->N24 1143 | 1144 | 1145 | 1146 | 1147 | 1148 | 1149 | 11.06s 1150 | 1151 | 1152 | 1153 | 1154 | 1155 | -------------------------------------------------------------------------------- /ch06/6.2/cpu_profile.prof: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottAI/book/5851b283d7dbfb91b42f5f4f1da4fbe6aec3acb4/ch06/6.2/cpu_profile.prof -------------------------------------------------------------------------------- /ch06/6.2/mem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottAI/book/5851b283d7dbfb91b42f5f4f1da4fbe6aec3acb4/ch06/6.2/mem.png -------------------------------------------------------------------------------- /ch06/6.2/mem.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | 297 | unnamed 298 | 299 | 300 | cluster_L 301 | 302 | 303 | 304 | 305 | Type: inuse_space 306 | 307 | Type: inuse_space 308 | Time: Aug 27, 2019 at 9:01am (CST) 309 | Showing nodes accounting for 1.10MB, 100% of 1.10MB total 310 | 311 | 312 | 313 | N1 314 | 315 | 316 | main 317 | runMEMTest 318 | 1.10MB (100%) 319 | 320 | 321 | 322 | 323 | 324 | NN1_0 325 | 326 | 327 | 328 | 329 | 330 | 944kB 331 | 332 | 333 | 334 | 335 | 336 | N1->NN1_0 337 | 338 | 339 | 340 | 341 | 342 | 343 | 1.10MB 344 | 345 | 346 | 347 | 348 | 349 | N2 350 | 351 | 352 | runtime 353 | main 354 | 0 of 1.10MB (100%) 355 | 356 | 357 | 358 | 359 | 360 | N3 361 | 362 | 363 | main 364 | main 365 | 0 of 1.10MB (100%) 366 | 367 | 368 | 369 | 370 | 371 | N2->N3 372 | 373 | 374 | 375 | 376 | 377 | 378 | 1.10MB 379 | 380 | 381 | 382 | 383 | 384 | N3->N1 385 | 386 | 387 | 388 | 389 | 390 | 391 | 1.10MB 392 | 393 | 394 | 395 | 396 | 397 | -------------------------------------------------------------------------------- /ch06/6.2/mem_profile1.prof: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottAI/book/5851b283d7dbfb91b42f5f4f1da4fbe6aec3acb4/ch06/6.2/mem_profile1.prof -------------------------------------------------------------------------------- /ch06/6.2/mem_profile2.prof: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottAI/book/5851b283d7dbfb91b42f5f4f1da4fbe6aec3acb4/ch06/6.2/mem_profile2.prof -------------------------------------------------------------------------------- /ch06/6.2/mem_profile3.prof: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottAI/book/5851b283d7dbfb91b42f5f4f1da4fbe6aec3acb4/ch06/6.2/mem_profile3.prof -------------------------------------------------------------------------------- /ch06/6.2/mem_profile4.prof: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottAI/book/5851b283d7dbfb91b42f5f4f1da4fbe6aec3acb4/ch06/6.2/mem_profile4.prof -------------------------------------------------------------------------------- /ch06/6.2/profile.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "os" 6 | "runtime" 7 | "runtime/pprof" 8 | "time" 9 | ) 10 | 11 | var ch4cpu chan uint64 12 | var chTimer chan struct{} 13 | var memMap map[int]interface{} 14 | 15 | func init(){ 16 | ch4cpu = make(chan uint64, 10000) 17 | chTimer = make(chan struct{}, 20) 18 | memMap = make (map[int]interface{}) 19 | } 20 | func main() { 21 | c, err := os.Create("/Users/liujinliang/projects/go/src/ljl/book/ch06/6.2/cpu_profile.prof") 22 | if err != nil { 23 | log.Fatal(err) 24 | } 25 | 26 | defer c.Close() 27 | 28 | m1, err := os.Create("/Users/liujinliang/projects/go/src/ljl/book/ch06/6.2/mem_profile1.prof") 29 | if err != nil { 30 | log.Fatal(err) 31 | } 32 | 33 | m2, err := os.Create("/Users/liujinliang/projects/go/src/ljl/book/ch06/6.2/mem_profile2.prof") 34 | if err != nil { 35 | log.Fatal(err) 36 | } 37 | 38 | m3, err := os.Create("/Users/liujinliang/projects/go/src/ljl/book/ch06/6.2/mem_profile3.prof") 39 | if err != nil { 40 | log.Fatal(err) 41 | } 42 | 43 | m4, err := os.Create("/Users/liujinliang/projects/go/src/ljl/book/ch06/6.2/mem_profile4.prof") 44 | if err != nil { 45 | log.Fatal(err) 46 | } 47 | 48 | defer m1.Close() 49 | defer m2.Close() 50 | defer m3.Close() 51 | defer m4.Close() 52 | 53 | pprof.StartCPUProfile(c) 54 | defer pprof.StopCPUProfile() 55 | 56 | memMap[1]= runMEMTest() 57 | 58 | runtime.GC() 59 | pprof.Lookup("heap").WriteTo(m1, 0) 60 | //从此处开始ch4cpu通道被不断的写入数据 61 | go runcputest() 62 | //goroutine运行15秒后chTimer写入值 63 | go func(){ 64 | time.Sleep(15 * time.Second) 65 | log.Println("write timer") 66 | chTimer <- struct{}{} 67 | 68 | }() 69 | memMap[2]= runMEMTest() 70 | runtime.GC() 71 | pprof.Lookup("heap").WriteTo(m2, 0) 72 | 73 | memMap[2] = nil 74 | runtime.GC() 75 | pprof.Lookup("heap").WriteTo(m3, 0) 76 | 77 | memMap[1] = nil 78 | runtime.GC() 79 | pprof.Lookup("heap").WriteTo(m4, 0) 80 | 81 | procmsg() 82 | } 83 | 84 | func runMEMTest()([]int) { 85 | mem := make([]int, 100000, 120000) 86 | return mem 87 | } 88 | 89 | func runcputest(){ 90 | var i uint64 91 | for { 92 | ch4cpu <- i 93 | i++ 94 | } 95 | } 96 | 97 | func procmsg(){ 98 | for { 99 | select { 100 | case _ = <-ch4cpu: 101 | case _ = <-chTimer://直到满足此条件for循环才结束 102 | log.Println("timeout") 103 | return 104 | } 105 | } 106 | } -------------------------------------------------------------------------------- /ch06/6.3/bhmark/bhmark: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottAI/book/5851b283d7dbfb91b42f5f4f1da4fbe6aec3acb4/ch06/6.3/bhmark/bhmark -------------------------------------------------------------------------------- /ch06/6.3/bhmark/testBenchmark.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func fb1(n int) int { 6 | if n == 0 { 7 | return 0 8 | }else if n == 1 { 9 | return 1 10 | }else { 11 | return fb1(n-1) + fb1(n-2) 12 | } 13 | 14 | } 15 | 16 | func fb2(n int) int { 17 | if n == 0 || n == 1 { 18 | return n 19 | } 20 | return fb2(n-1) + fb2(n-2) 21 | } 22 | 23 | func fb3(n int) int { 24 | fbMap := make(map[int]int) 25 | for i := 0;i <= n;i++ { 26 | var t int 27 | if i <= 1 { 28 | t = i 29 | }else { 30 | t = fbMap[i-1] + fbMap[i-2] 31 | } 32 | fbMap[i] = t 33 | } 34 | return fbMap[n] 35 | } 36 | 37 | func main() { 38 | fmt.Println(fb1(50)) 39 | fmt.Println(fb2(50)) 40 | fmt.Println(fb3(50)) 41 | } 42 | -------------------------------------------------------------------------------- /ch06/6.3/bhmark/testBenchmark_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "testing" 4 | 5 | var final int 6 | func benchmarkfb1(b *testing.B,n int) { 7 | var end int 8 | for i := 0; i < b.N; i++ { 9 | end = fb1(n) 10 | } 11 | final = end 12 | } 13 | 14 | func Benchmarkfb2(b *testing.B,n int) { 15 | var end int 16 | for i := 0; i < b.N; i++ { 17 | end = fb2(n) 18 | } 19 | final = end 20 | } 21 | 22 | func Benchmarkfb3(b *testing.B,n int) { 23 | var end int 24 | for i := 0; i < b.N; i++ { 25 | end = fb3(n) 26 | } 27 | final = end 28 | } 29 | 30 | func Benchmark50fb1(b *testing.B) { 31 | benchmarkfb1(b,30) 32 | } 33 | 34 | func Benchmark50fb2(b *testing.B) { 35 | Benchmarkfb2(b,30) 36 | } 37 | 38 | func Benchmark50fb3(b *testing.B) { 39 | Benchmarkfb3(b,30) 40 | } -------------------------------------------------------------------------------- /ch06/6.3/example/exam_test.go: -------------------------------------------------------------------------------- 1 | package exam 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func ExampleSum() { 8 | fmt.Println(Sum(1,2)) 9 | // Output: 10 | // 3 11 | } 12 | -------------------------------------------------------------------------------- /ch06/6.3/example/testExam.go: -------------------------------------------------------------------------------- 1 | package exam 2 | 3 | func Sum(a,b int) int { 4 | return a+b 5 | } 6 | -------------------------------------------------------------------------------- /ch06/6.3/test/testTest.go: -------------------------------------------------------------------------------- 1 | package testTest 2 | 3 | func fb1(n int) int { 4 | if n == 0 { 5 | return 0 6 | } 7 | if n == 1 { 8 | return 1 9 | } 10 | return fb1(n-1) + fb1(n-2) 11 | } 12 | 13 | func fb2(n int) int { 14 | if n == 0 { 15 | return 0 16 | } 17 | if n == 1 { 18 | return 2 19 | } 20 | return fb2(n-1) + fb2(n-2) 21 | } 22 | -------------------------------------------------------------------------------- /ch06/6.3/test/testTest_test.go: -------------------------------------------------------------------------------- 1 | package testTest 2 | 3 | import "testing" 4 | 5 | func TestFb1(t *testing.T) { 6 | if fb1(0) != 0 { 7 | t.Error(`fb1(0)!=0`) 8 | } 9 | if fb1(1) != 1 { 10 | t.Error(`fb1(1)!=1`) 11 | } 12 | if fb1(2) != 1 { 13 | t.Error(`fb1(2)!=1`) 14 | } 15 | if fb1(10) != 55 { 16 | t.Error(`fb1(10)!=55`) 17 | } 18 | } 19 | 20 | func TestFb2(t *testing.T) { 21 | if fb2(0) != 0 { 22 | t.Error(`fb2(0)!=0`) 23 | } 24 | if fb2(1) != 1 { 25 | t.Error(`fb2(1)!=1`) 26 | } 27 | if fb2(2) != 1 { 28 | t.Error(`fb2(2)!=1`) 29 | } 30 | if fb2(10) != 55 { 31 | t.Error(`fb2(10)!=55`) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ch08/8.2/RWMutex/rwmutex.go: -------------------------------------------------------------------------------- 1 | package rwmutex 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | "time" 7 | ) 8 | 9 | type pass struct { 10 | RWM sync.RWMutex 11 | pwd string 12 | } 13 | var RoomPass = pass{pwd:"initPass"} 14 | 15 | func Change(p *pass,pwd string) { 16 | p.RWM.Lock() 17 | fmt.Println() 18 | time.Sleep(5*time.Second) 19 | p.pwd = pwd 20 | p.RWM.Unlock() 21 | } 22 | 23 | func getPWD(p *pass) string { 24 | p.RWM.RLock() 25 | fmt.Println("read pwd") 26 | time.Sleep(time.Second) 27 | defer p.RWM.RUnlock() 28 | return p.pwd 29 | } 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /ch08/8.2/cond/cond.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | "time" 7 | ) 8 | 9 | var ( 10 | ready = false 11 | singerNum = 3 12 | ) 13 | 14 | func Sing(singerId int,c *sync.Cond) { 15 | fmt.Printf("Singer (%d) is ready\n",singerId) 16 | c.L.Lock() 17 | for !ready { 18 | fmt.Printf("Singer (%d) is waiting\n",singerId) 19 | c.Wait() 20 | } 21 | fmt.Printf("Singer (%d) sing a song\n",singerId) 22 | ready = false 23 | c.L.Unlock() 24 | } 25 | 26 | func main() { 27 | cond := sync.NewCond(&sync.Mutex{}) 28 | for i:=0;i %d", Read()) 39 | }(i) 40 | } 41 | 42 | wg.Wait() 43 | } 44 | -------------------------------------------------------------------------------- /ch08/8.2/once/once.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | ) 7 | 8 | func main() { 9 | var wg sync.WaitGroup 10 | var once sync.Once 11 | for i:=0;i<10;i++{ 12 | wg.Add(1) 13 | go func() { 14 | defer wg.Done() 15 | once.Do(onlyOnce) 16 | }() 17 | } 18 | wg.Wait() 19 | } 20 | 21 | func onlyOnce() { 22 | fmt.Println("only once") 23 | } 24 | -------------------------------------------------------------------------------- /ch08/8.2/pool/pool.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | "time" 7 | ) 8 | 9 | var byteSlicePool = sync.Pool{ 10 | New: func() interface{} { 11 | b := make([]byte,1024) 12 | return &b 13 | }, 14 | } 15 | 16 | func main() { 17 | t1 := time.Now().Unix() 18 | //不使用Pool 19 | for i:=0;i<10000000000;i++{ 20 | bytes := make([]byte,1024) 21 | _ = bytes 22 | } 23 | t2 := time.Now().Unix() 24 | //使用Pool 25 | for i:=0;i<10000000000;i++{ 26 | bytes := byteSlicePool.Get().(*[]byte) 27 | _ = bytes 28 | byteSlicePool.Put(bytes) 29 | } 30 | t3 := time.Now().Unix() 31 | fmt.Printf("不使用Pool:%d s\n",t2-t1) 32 | fmt.Printf("使用Pool:%d s\n",t3-t2) 33 | } 34 | -------------------------------------------------------------------------------- /ch08/8.3/advanced/context.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "io/ioutil" 7 | "net/http" 8 | "sync" 9 | "time" 10 | ) 11 | 12 | var ( 13 | url string 14 | t = 5 15 | wg sync.WaitGroup 16 | ) 17 | 18 | type information struct { 19 | r *http.Response 20 | err error 21 | } 22 | 23 | func connect(c context.Context) error { 24 | defer wg.Done() 25 | info := make(chan information,1) 26 | tr := &http.Transport{} 27 | httpClient := &http.Client{Transport:tr} 28 | req,_ := http.NewRequest("GET",url,nil) 29 | req = req.WithContext(c) 30 | 31 | go func() { 32 | res,err := httpClient.Do(req) 33 | if err != nil { 34 | fmt.Println(err) 35 | info <- information{nil,err} 36 | return 37 | }else{ 38 | info <- information{res,err} 39 | } 40 | }() 41 | 42 | select { 43 | case <- c.Done(): 44 | fmt.Println("request is cancelled!!") 45 | case ok := <-info: 46 | err := ok.err 47 | r := ok.r 48 | if err != nil { 49 | fmt.Println("ERROR:",err) 50 | return err 51 | } 52 | defer r.Body.Close() 53 | realInfo,err := ioutil.ReadAll(r.Body) 54 | if err != nil { 55 | fmt.Println("ERROR:",err) 56 | return err 57 | } 58 | fmt.Printf("Response:%s\n",realInfo) 59 | } 60 | return nil 61 | } 62 | 63 | func main() { 64 | url = "http://google.com" //试着换成baidu 65 | ctx := context.Background() 66 | ctx,cancel := context.WithTimeout(ctx,time.Duration(t)*time.Second) 67 | defer cancel() 68 | fmt.Printf("connecting to %s \n",url) 69 | wg.Add(1) 70 | go connect(ctx) 71 | wg.Wait() 72 | fmt.Println("END...") 73 | } 74 | -------------------------------------------------------------------------------- /ch08/8.3/context.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "time" 7 | ) 8 | 9 | func testWCancel(t int) { 10 | ctx := context.Background() 11 | ctx,cancel := context.WithCancel(ctx) 12 | defer cancel() 13 | go func() { 14 | time.Sleep(3*time.Second) 15 | cancel() 16 | }() 17 | select { 18 | case <- ctx.Done(): 19 | fmt.Println("testWCancel.Done:",ctx.Err()) 20 | case e := <- time.After(time.Duration(t)*time.Second): 21 | fmt.Println("testWCancel:",e) 22 | } 23 | return 24 | } 25 | 26 | func testWDeadline(t int) { 27 | ctx := context.Background() 28 | dl := time.Now().Add(time.Duration(1*t)*time.Second) 29 | ctx,cancel := context.WithDeadline(ctx,dl) 30 | defer cancel() 31 | go func() { 32 | time.Sleep(3*time.Second) 33 | cancel() 34 | }() 35 | select { 36 | case <- ctx.Done(): 37 | fmt.Println("testWDeadline.Done:",ctx.Err()) 38 | case e := <-time.After(time.Duration(t)*time.Second): 39 | fmt.Println("testWDeadline:",e) 40 | } 41 | return 42 | } 43 | 44 | func testWTimeout(t int) { 45 | ctx := context.Background() 46 | ctx,cancel := context.WithTimeout(ctx,time.Duration(t)*time.Second) 47 | defer cancel() 48 | 49 | go func() { 50 | time.Sleep(3*time.Second) 51 | cancel() 52 | }() 53 | select { 54 | case <- ctx.Done(): 55 | fmt.Println("testWTimeout.Done:",ctx.Err()) 56 | case e := <-time.After(time.Duration(t)*time.Second): 57 | fmt.Println("testWTimeout:",e) 58 | } 59 | return 60 | } 61 | 62 | func main() { 63 | var t = 4 64 | testWCancel(t) 65 | testWDeadline(t) 66 | testWTimeout(t) 67 | } 68 | -------------------------------------------------------------------------------- /ch08/8.4/simple/workpool.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func worcker(id int,jobs <- chan int,results chan <- int) { 9 | for job := range jobs { 10 | fmt.Printf("worker(%d) start to do job(%d)\n",id,job) 11 | time.Sleep(time.Second) 12 | fmt.Printf("worker(%d) finished job(%d)\n",id,job) 13 | results <- job*job 14 | } 15 | } 16 | 17 | func main() { 18 | jobs := make(chan int,100) 19 | resultes := make(chan int,100) 20 | 21 | for id := 0;id<3;id++{ 22 | go worcker(id,jobs,resultes) 23 | } 24 | for job:=1;job<=5;job++{ 25 | jobs <- job 26 | } 27 | close(jobs) 28 | 29 | for i:=1;i<=5;i++{ 30 | <-resultes 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ch08/8.4/workpool.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | "time" 7 | ) 8 | 9 | type Task struct { 10 | Num int 11 | } 12 | 13 | type Job struct { 14 | Task Task 15 | } 16 | var ( 17 | MaxWorker = 5 18 | JobQueue chan Job //工作通道,模拟需要处理的所有工作 19 | ) 20 | 21 | type Worker struct { 22 | id int //id 23 | WorkerPool chan chan Job //工作者池(通道的通道),每个元素是一个job通道,公共的job 24 | JobChannel chan Job //工作通道,每个元素是一个job,worker私有的job 25 | exit chan bool //结束信号 26 | } 27 | 28 | func NewWorker(workerPool chan chan Job, id int) Worker { 29 | fmt.Printf("new a worker(%d)\n",id) 30 | return Worker{ 31 | id: id, 32 | WorkerPool: workerPool, //workerPool和scheduler的是同一个 33 | JobChannel: make(chan Job), 34 | exit: make(chan bool), 35 | } 36 | } 37 | 38 | //监听任务和结束信号 39 | func (w Worker) Start() { 40 | go func() { 41 | for { 42 | // 将当前的任务队列注册到工作池. 43 | w.WorkerPool <- w.JobChannel 44 | fmt.Println("register private JobChannel to public WorkerPool", w) 45 | select { 46 | case job := <-w.JobChannel://收到任务 47 | fmt.Println("get a job from private w.JobChannel") 48 | fmt.Println(job) 49 | time.Sleep(5* time.Second) 50 | case <-w.exit://收到结束信号 51 | fmt.Println("worker exit",w) 52 | return 53 | } 54 | } 55 | }() 56 | } 57 | 58 | func (w Worker) Stop() { 59 | go func() { 60 | w.exit <- true 61 | }() 62 | } 63 | 64 | //排程中心 65 | type Scheduler struct { 66 | WorkerPool chan chan Job //工作池 67 | MaxWorkers int //最大工作者数 68 | Workers []*Worker //worker队列 69 | } 70 | 71 | //创建排程中心 72 | func NewScheduler(maxWorkers int) *Scheduler { 73 | pool := make(chan chan Job, maxWorkers) //工作池 74 | return &Scheduler{WorkerPool: pool, MaxWorkers: maxWorkers} 75 | } 76 | 77 | //工作池的初始化 78 | func (s *Scheduler) Create() { 79 | workers := make([]*Worker,s.MaxWorkers) 80 | for i := 0; i < s.MaxWorkers; i++ { 81 | worker := NewWorker(s.WorkerPool, i) 82 | worker.Start() 83 | workers[i] = &worker 84 | } 85 | s.Workers = workers 86 | go s.schedule() 87 | } 88 | 89 | //工作池的关闭 90 | func (s *Scheduler) Shutdown() { 91 | workers := s.Workers 92 | for _,w := range workers{ 93 | w.Stop() 94 | } 95 | time.Sleep(time.Second) 96 | close(s.WorkerPool) 97 | } 98 | 99 | //排程 100 | func (s *Scheduler) schedule() { 101 | for { 102 | select { 103 | case job := <-JobQueue: 104 | fmt.Println("get a job from JobQueue") 105 | go func(job Job) { 106 | //从WorkerPool获取jobChannel,忙时阻塞 107 | jobChannel := <-s.WorkerPool 108 | fmt.Println("get a private jobChannel from public s.WorkerPool", reflect.TypeOf(jobChannel)) 109 | jobChannel <- job 110 | fmt.Println("worker's private jobChannel add one job") 111 | }(job) 112 | } 113 | } 114 | } 115 | 116 | func main() { 117 | JobQueue = make(chan Job, 5) 118 | scheduler := NewScheduler(MaxWorker) 119 | scheduler.Create() 120 | time.Sleep(1 * time.Second) 121 | go createJobQueue() 122 | time.Sleep(100 * time.Second) 123 | scheduler.Shutdown() 124 | time.Sleep(10*time.Second) 125 | } 126 | //创建模拟任务 127 | func createJobQueue() { 128 | for i := 0; i < 30; i++ { 129 | task := Task{Num: 1} 130 | job := Job{Task: task} 131 | JobQueue <- job 132 | fmt.Println("JobQueue add one job") 133 | time.Sleep(1 * time.Second) 134 | } 135 | 136 | } -------------------------------------------------------------------------------- /ch08/race/datarace.go: -------------------------------------------------------------------------------- 1 | package singlegoroutine 2 | 3 | var realNum = make(chan int)//设置数字值 4 | var delta = make(chan int)//设置设置的增减额 5 | 6 | func SetNumber(n int) { 7 | realNum <- n 8 | } 9 | func ChangeByDelta(d int) { 10 | delta <- d 11 | } 12 | func GetNumber() int{ 13 | return <- realNum 14 | } 15 | func moitor() { 16 | var i int //把数值限定在方法内,goroutine运行后仅在goroutine内 17 | for { 18 | select{ 19 | case i = <- realNum: 20 | case d := <- delta: 21 | i += d 22 | case realNum <- i: 23 | } 24 | } 25 | } 26 | func init() { 27 | go moitor() 28 | } -------------------------------------------------------------------------------- /ch09/9.1/httpDemo.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func main() { 6 | http.Handle("/", &ThisHandler{}) 7 | http.Handle("/hello", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 8 | w.Write([]byte("Hello!!")) 9 | })) 10 | http.HandleFunc("/hi", sayHi) 11 | 12 | http.ListenAndServe(":8080", nil) 13 | } 14 | 15 | func sayHi(w http.ResponseWriter, r *http.Request) { 16 | w.Write([]byte("Hi!!")) 17 | } 18 | 19 | type ThisHandler struct{} 20 | 21 | func (m *ThisHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 22 | w.Write([]byte("ThisHandler's ServeHTTP")) 23 | } -------------------------------------------------------------------------------- /ch09/9.2/httprouter.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/julienschmidt/httprouter" 6 | "log" 7 | "net/http" 8 | ) 9 | 10 | func Home(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { 11 | fmt.Fprint(w, "Welcome back to home!\n") 12 | } 13 | 14 | func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { 15 | fmt.Fprintf(w, "Hello, %s!\n", ps.ByName("name")) 16 | } 17 | 18 | func main() { 19 | router := httprouter.New() 20 | router.GET("/", Home) 21 | router.GET("/hello/:name", Hello) 22 | 23 | log.Fatal(http.ListenAndServe(":8081", router)) 24 | } -------------------------------------------------------------------------------- /ch09/9.3/tcpClient/tcpClient.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "net" 7 | "os" 8 | ) 9 | 10 | func main() { 11 | addr := "www.baidu.com:80" 12 | tcpAddr,err := net.ResolveTCPAddr("tcp",addr) 13 | if err != nil { 14 | fmt.Println("Error:",err.Error()) 15 | return 16 | } 17 | 18 | myConn,err := net.DialTCP("tcp",nil,tcpAddr) 19 | if err != nil { 20 | fmt.Println("Error:",err.Error()) 21 | return 22 | } 23 | 24 | _,err = myConn.Write([]byte("HEAD / HTTP/1.1\r\n\r\n")) 25 | 26 | result,err := ioutil.ReadAll(myConn) 27 | if err != nil { 28 | fmt.Println("Error:",err.Error()) 29 | return 30 | } 31 | fmt.Println(string(result)) 32 | os.Exit(0) 33 | } 34 | -------------------------------------------------------------------------------- /ch09/9.3/tcpServer/tcpServer.go: -------------------------------------------------------------------------------- 1 | 2 | package main 3 | 4 | import ( 5 | "fmt" 6 | "net" 7 | "os" 8 | "time" 9 | ) 10 | 11 | func checkError(err error) { 12 | if err != nil { 13 | fmt.Println("Fatal error :", err.Error()) 14 | os.Exit(1) 15 | } 16 | } 17 | 18 | func nowtime() string { 19 | return time.Now().String() 20 | } 21 | 22 | func main() { 23 | addr := ":7777" 24 | tcpAddr, err := net.ResolveTCPAddr("tcp", addr) 25 | checkError(err) 26 | 27 | mylistener, err := net.ListenTCP("tcp", tcpAddr) 28 | checkError(err) 29 | i := 0 30 | for { 31 | myconn, err := mylistener.Accept() 32 | fmt.Printf("myconn ") 33 | if err != nil { 34 | continue 35 | } 36 | i++ 37 | 38 | nowTime := nowtime() 39 | fmt.Printf("request no %d return time:%s \n",i,nowTime) 40 | myconn.Write([]byte(nowTime)) 41 | myconn.Close() 42 | 43 | } 44 | } -------------------------------------------------------------------------------- /ch09/9.3/udpClient/udpClient.go: -------------------------------------------------------------------------------- 1 | package main 2 | import ( 3 | "bufio" 4 | "fmt" 5 | "net" 6 | ) 7 | 8 | func main() { 9 | p := make([]byte, 512) 10 | conn, err := net.Dial("udp", "127.0.0.1:7778") 11 | defer conn.Close() 12 | if err != nil { 13 | fmt.Printf("Some error %v", err) 14 | return 15 | } 16 | fmt.Fprintf(conn, "Hi UDP Server, How are you? \n") 17 | n, err := bufio.NewReader(conn).Read(p) 18 | if err == nil { 19 | fmt.Printf("Response:%s\n", p[0:n]) 20 | } else { 21 | fmt.Printf("Error: %v\n", err) 22 | } 23 | } -------------------------------------------------------------------------------- /ch09/9.3/udpServer/udpServer.go: -------------------------------------------------------------------------------- 1 | package main 2 | import ( 3 | "fmt" 4 | "net" 5 | ) 6 | 7 | func sendResponse(conn *net.UDPConn, addr *net.UDPAddr) { 8 | _,err := conn.WriteToUDP([]byte("From server: Hello, I got your mesage "), addr) 9 | if err != nil { 10 | fmt.Printf("Couldn't send response %v", err) 11 | } 12 | } 13 | 14 | 15 | func main() { 16 | p := make([]byte, 512) 17 | addr := net.UDPAddr{ 18 | Port: 7778, 19 | IP: net.ParseIP("127.0.0.1"), 20 | } 21 | ser, err := net.ListenUDP("udp", &addr) 22 | if err != nil { 23 | fmt.Printf("Some error %v\n", err) 24 | return 25 | } 26 | for { 27 | n,remoteaddr,err := ser.ReadFromUDP(p) 28 | fmt.Printf("Read a message from %v : %s \n", remoteaddr, p[0:n]) 29 | if err != nil { 30 | fmt.Printf("Error: %v", err) 31 | continue 32 | } 33 | go sendResponse(ser, remoteaddr) 34 | } 35 | } -------------------------------------------------------------------------------- /ch09/9.3/websocket/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |

chat/history:

6 | 7 |
8 | 9 | 26 | 27 | -------------------------------------------------------------------------------- /ch09/9.3/websocket/ws.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io/ioutil" 7 | "log" 8 | "net/http" 9 | 10 | "github.com/gorilla/websocket" 11 | ) 12 | 13 | // 1 14 | type Message struct { 15 | Name string `json:"name"` 16 | Mess string `json:"mess"` 17 | } 18 | 19 | var clients = make(map[*websocket.Conn]bool) 20 | var broadcast = make(chan *Message) 21 | var upgrader = websocket.Upgrader{ 22 | CheckOrigin: func(r *http.Request) bool { 23 | return true 24 | }, 25 | } 26 | 27 | func main() { 28 | // 2 29 | http.HandleFunc("/", rootHandler) 30 | http.HandleFunc("/chat", messHandler) 31 | http.HandleFunc("/ws", wsHandler) 32 | go echo() 33 | 34 | panic(http.ListenAndServe(":7778", nil)) 35 | } 36 | 37 | func rootHandler(w http.ResponseWriter, r *http.Request) { 38 | content, err := ioutil.ReadFile("/Users/liujinliang/projects/go/src/ljl/book/ch09/9.3/websocket/index.html") 39 | if err != nil { 40 | fmt.Println("Could not open file.", err) 41 | } 42 | fmt.Fprintf(w, "%s", content) 43 | } 44 | 45 | func writer(mess *Message) { 46 | broadcast <- mess 47 | } 48 | 49 | func messHandler(w http.ResponseWriter, r *http.Request) { 50 | var mess Message 51 | if err := json.NewDecoder(r.Body).Decode(&mess); err != nil { 52 | log.Printf("ERROR: %s", err) 53 | http.Error(w, "Bad request", http.StatusTeapot) 54 | return 55 | } 56 | defer r.Body.Close() 57 | go writer(&mess) 58 | } 59 | 60 | func wsHandler(w http.ResponseWriter, r *http.Request) { 61 | ws, err := upgrader.Upgrade(w, r, nil) 62 | if err != nil { 63 | log.Fatal(err) 64 | } 65 | 66 | // register client 67 | clients[ws] = true 68 | } 69 | 70 | // 3 71 | func echo() { 72 | for { 73 | mess := <-broadcast 74 | hisMess := fmt.Sprintf("%s : %s \n", mess.Name, mess.Mess) 75 | fmt.Println(hisMess) 76 | // send to every client that is currently connected 77 | for client := range clients { 78 | err := client.WriteMessage(websocket.TextMessage, []byte(hisMess)) 79 | if err != nil { 80 | log.Printf("Websocket error: %s", err) 81 | client.Close() 82 | delete(clients, client) 83 | } 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /ch09/9.4/adv/adv.go: -------------------------------------------------------------------------------- 1 | package adv 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "log" 7 | "net/http" 8 | "time" 9 | ) 10 | 11 | type Middleware func(http.HandlerFunc) http.HandlerFunc 12 | 13 | //Get user's auth code 14 | func GetAuthCode() Middleware { 15 | // Create a new Middleware 16 | return func(f http.HandlerFunc) http.HandlerFunc { 17 | //Define the http.HandlerFunc 18 | return func(w http.ResponseWriter, r *http.Request) { 19 | code := 0 20 | //auth code is available only when access root 21 | if r.URL.Path != "/"{ 22 | code = -1 23 | } 24 | //create a new request context containing the auth code, context available >= go 1.7 25 | ctxWithUser := context.WithValue(r.Context(), code, "User") 26 | //create a new request using that new context 27 | rWithUser := r.WithContext(ctxWithUser) 28 | //call the real handler, passing the new request 29 | f(w,rWithUser) 30 | } 31 | } 32 | } 33 | 34 | // Ensure user's auth 35 | func EnsureAuth() Middleware { 36 | // Create a new Middleware 37 | return func(f http.HandlerFunc) http.HandlerFunc { 38 | //Define the http.HandlerFunc 39 | return func(w http.ResponseWriter, r *http.Request) { 40 | user := r.Context().Value(0) 41 | if user != nil { 42 | log.Println("auth available!") 43 | }else { 44 | http.Error(w,"Please sign in!",http.StatusUnauthorized) 45 | return 46 | } 47 | // Call the next middleware/handler in chain 48 | f(w,r) 49 | } 50 | } 51 | } 52 | // Logging logs all requests with its path and the time it took to process 53 | func Logging() Middleware { 54 | return func(f http.HandlerFunc) http.HandlerFunc { 55 | return func(w http.ResponseWriter, r *http.Request) { 56 | // Do middleware things 57 | start := time.Now() 58 | defer func() { log.Println(r.URL.Path, time.Since(start)) }() 59 | // Call the next middleware/handler in chain 60 | f(w, r) 61 | } 62 | } 63 | } 64 | 65 | // Method ensures that url can only be requested with a specific method, else returns a 400 Bad Request 66 | func Method(m string) Middleware { 67 | // Create a new Middleware 68 | return func(f http.HandlerFunc) http.HandlerFunc { 69 | // Define the http.HandlerFunc 70 | return func(w http.ResponseWriter, r *http.Request) { 71 | 72 | // Do middleware things 73 | if r.Method != m { 74 | http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) 75 | return 76 | }else { 77 | log.Println("request is :",m) 78 | } 79 | // Call the next middleware/handler in chain 80 | f(w, r) 81 | } 82 | } 83 | } 84 | 85 | // Chain applies middlewares to a http.HandlerFunc 86 | func Chain(f http.HandlerFunc, middlewares ...Middleware) http.HandlerFunc { 87 | for _, m := range middlewares { 88 | f = m(f) 89 | } 90 | return f 91 | } 92 | 93 | func Hello(w http.ResponseWriter, r *http.Request) { 94 | fmt.Fprintln(w, "hello world") 95 | } 96 | func Auth(w http.ResponseWriter, r *http.Request) { 97 | fmt.Fprintln(w,"You r authorized!") 98 | } 99 | 100 | func main() { 101 | http.HandleFunc("/", Chain(Hello, Method("GET"),GetAuthCode(), Logging())) 102 | http.HandleFunc("/auth/", Chain(Auth, Method("GET"),GetAuthCode(),EnsureAuth(), Logging())) 103 | http.ListenAndServe(":7775", nil) 104 | } -------------------------------------------------------------------------------- /ch09/9.4/basic/basicmiddle.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/http" 7 | "time" 8 | ) 9 | type Logger struct { //Logger is a middleware handler 10 | handler http.Handler 11 | } 12 | 13 | func (l *Logger) ServeHTTP(w http.ResponseWriter, r *http.Request) { 14 | start := time.Now() 15 | l.handler.ServeHTTP(w,r) 16 | log.Printf("%s %s %v",r.Method,r.URL.Path,time.Since(start)) 17 | } 18 | 19 | func NewLogger(handlerToWrap http.Handler) *Logger { 20 | return &Logger{handlerToWrap} 21 | } 22 | 23 | func HelloHandler(w http.ResponseWriter, r *http.Request) { 24 | w.Write([]byte("Hello,World!")) 25 | } 26 | func CurrentTimeHandler(w http.ResponseWriter, r *http.Request) { 27 | curTime := time.Now().Format(time.Kitchen) 28 | w.Write([]byte(fmt.Sprintf("Current time is %v",curTime))) 29 | } 30 | func main() { 31 | mux := http.NewServeMux() 32 | mux.HandleFunc("/v1/hello",HelloHandler) 33 | mux.HandleFunc("/v1/time",CurrentTimeHandler) 34 | wrappedMux := NewLogger(mux) //包装了中间件的mux 35 | addr := "localhost:7774" 36 | log.Printf("listen at:%s",addr) 37 | log.Fatal(http.ListenAndServe(addr,wrappedMux)) 38 | } 39 | 40 | -------------------------------------------------------------------------------- /ch09/9.4/nomiddle.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/http" 7 | "time" 8 | ) 9 | 10 | func HelloHandler(w http.ResponseWriter, r *http.Request) { 11 | w.Write([]byte("Hello,World!")) 12 | } 13 | 14 | func CurrentTimeHandler(w http.ResponseWriter, r *http.Request) { 15 | curTime := time.Now().Format(time.Kitchen) 16 | w.Write([]byte(fmt.Sprintf("Current time is %v",curTime))) 17 | } 18 | 19 | func main() { 20 | mux := http.NewServeMux() 21 | mux.HandleFunc("/v1/hello",HelloHandler) 22 | mux.HandleFunc("/v1/time",CurrentTimeHandler) 23 | addr := "localhost:7774" 24 | log.Printf("listen at:%s",addr) 25 | log.Fatal(http.ListenAndServe(addr,mux)) 26 | } 27 | -------------------------------------------------------------------------------- /ch13/13.2/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "./protocol" 5 | "github.com/gogo/protobuf/proto" 6 | "log" 7 | ) 8 | 9 | func main() { 10 | u := &protocol.UserInfo{ 11 | Message: *proto.String("testInfo"), 12 | Length: *proto.Int32(10), 13 | } 14 | 15 | data,err := proto.Marshal(u) 16 | if err != nil { 17 | log.Fatal("marshaling error: ", err) 18 | } 19 | newInfo := &protocol.UserInfo{} 20 | err = proto.Unmarshal(data,newInfo) 21 | if err != nil { 22 | log.Fatal("unmarshaling error: ", err) 23 | } 24 | 25 | log.Println(newInfo.GetMessage()) 26 | } -------------------------------------------------------------------------------- /ch13/13.2/protocol/test.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // source: test.proto 3 | 4 | package protocol 5 | 6 | import ( 7 | fmt "fmt" 8 | proto "github.com/golang/protobuf/proto" 9 | math "math" 10 | ) 11 | 12 | // Reference imports to suppress errors if they are not otherwise used. 13 | var _ = proto.Marshal 14 | var _ = fmt.Errorf 15 | var _ = math.Inf 16 | 17 | // This is a compile-time assertion to ensure that this generated file 18 | // is compatible with the proto package it is being compiled against. 19 | // A compilation error at this line likely means your copy of the 20 | // proto package needs to be updated. 21 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 22 | 23 | type FOO int32 24 | 25 | const ( 26 | FOO_X FOO = 0 27 | ) 28 | 29 | var FOO_name = map[int32]string{ 30 | 0: "X", 31 | } 32 | 33 | var FOO_value = map[string]int32{ 34 | "X": 0, 35 | } 36 | 37 | func (x FOO) String() string { 38 | return proto.EnumName(FOO_name, int32(x)) 39 | } 40 | 41 | func (FOO) EnumDescriptor() ([]byte, []int) { 42 | return fileDescriptor_c161fcfdc0c3ff1e, []int{0} 43 | } 44 | 45 | //message是固定关键字。UserInfo是自定义类名 46 | type UserInfo struct { 47 | Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` 48 | Length int32 `protobuf:"varint,2,opt,name=length,proto3" json:"length,omitempty"` 49 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 50 | XXX_unrecognized []byte `json:"-"` 51 | XXX_sizecache int32 `json:"-"` 52 | } 53 | 54 | func (m *UserInfo) Reset() { *m = UserInfo{} } 55 | func (m *UserInfo) String() string { return proto.CompactTextString(m) } 56 | func (*UserInfo) ProtoMessage() {} 57 | func (*UserInfo) Descriptor() ([]byte, []int) { 58 | return fileDescriptor_c161fcfdc0c3ff1e, []int{0} 59 | } 60 | 61 | func (m *UserInfo) XXX_Unmarshal(b []byte) error { 62 | return xxx_messageInfo_UserInfo.Unmarshal(m, b) 63 | } 64 | func (m *UserInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 65 | return xxx_messageInfo_UserInfo.Marshal(b, m, deterministic) 66 | } 67 | func (m *UserInfo) XXX_Merge(src proto.Message) { 68 | xxx_messageInfo_UserInfo.Merge(m, src) 69 | } 70 | func (m *UserInfo) XXX_Size() int { 71 | return xxx_messageInfo_UserInfo.Size(m) 72 | } 73 | func (m *UserInfo) XXX_DiscardUnknown() { 74 | xxx_messageInfo_UserInfo.DiscardUnknown(m) 75 | } 76 | 77 | var xxx_messageInfo_UserInfo proto.InternalMessageInfo 78 | 79 | func (m *UserInfo) GetMessage() string { 80 | if m != nil { 81 | return m.Message 82 | } 83 | return "" 84 | } 85 | 86 | func (m *UserInfo) GetLength() int32 { 87 | if m != nil { 88 | return m.Length 89 | } 90 | return 0 91 | } 92 | 93 | func init() { 94 | proto.RegisterEnum("protocol.FOO", FOO_name, FOO_value) 95 | proto.RegisterType((*UserInfo)(nil), "protocol.UserInfo") 96 | } 97 | 98 | func init() { proto.RegisterFile("test.proto", fileDescriptor_c161fcfdc0c3ff1e) } 99 | 100 | var fileDescriptor_c161fcfdc0c3ff1e = []byte{ 101 | // 112 bytes of a gzipped FileDescriptorProto 102 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2a, 0x49, 0x2d, 0x2e, 103 | 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x00, 0x53, 0xc9, 0xf9, 0x39, 0x4a, 0x36, 0x5c, 104 | 0x1c, 0xa1, 0xc5, 0xa9, 0x45, 0x9e, 0x79, 0x69, 0xf9, 0x42, 0x12, 0x5c, 0xec, 0xb9, 0xa9, 0xc5, 105 | 0xc5, 0x89, 0xe9, 0xa9, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0x30, 0xae, 0x90, 0x18, 0x17, 106 | 0x5b, 0x4e, 0x6a, 0x5e, 0x7a, 0x49, 0x86, 0x04, 0x93, 0x02, 0xa3, 0x06, 0x6b, 0x10, 0x94, 0xa7, 107 | 0xc5, 0xc3, 0xc5, 0xec, 0xe6, 0xef, 0x2f, 0xc4, 0xca, 0xc5, 0x18, 0x21, 0xc0, 0x90, 0xc4, 0x06, 108 | 0x36, 0xd5, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0x36, 0x8b, 0xb0, 0x7b, 0x6a, 0x00, 0x00, 0x00, 109 | } 110 | -------------------------------------------------------------------------------- /ch13/13.2/protocol/test.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; //指定版本(proto3、proto2) 2 | package protocol; 3 | 4 | enum FOO 5 | { 6 | X = 0; 7 | }; 8 | 9 | //message是固定关键字。UserInfo是自定义类名 10 | message UserInfo{ 11 | string message = 1; 12 | int32 length = 2; 13 | } -------------------------------------------------------------------------------- /ch13/13.3/grpc/client/client.go: -------------------------------------------------------------------------------- 1 | package main 2 | import ( 3 | "context" 4 | "fmt" 5 | "google.golang.org/grpc" 6 | pt "../protocol" 7 | ) 8 | const ( 9 | post = "127.0.0.1:18887" 10 | ) 11 | func main() { 12 | // 客户端连接服务器 13 | conn,err:=grpc.Dial(post,grpc.WithInsecure()) 14 | if err!=nil { 15 | fmt.Println("连接服务器失败",err) 16 | } 17 | 18 | defer conn.Close() 19 | 20 | //获得grpc句柄 21 | c:=pt.NewHelloServerClient(conn) 22 | 23 | //远程调用 SayHello接口 24 | r1, err := c.SayHello(context.Background(), &pt.HelloRequest{Name: "Scott"}) 25 | if err != nil { 26 | fmt.Println("cloud not get Hello server ..", err) 27 | return 28 | } 29 | fmt.Println("HelloServer resp: ", r1.Message) 30 | //远程调用 GetHelloMsg接口 31 | r2, err := c.GetHelloMsg(context.Background(), &pt.HelloRequest{Name: "Scott"}) 32 | if err != nil { 33 | fmt.Println("cloud not get hello msg ..", err) 34 | return 35 | } 36 | fmt.Println("HelloServer resp: ", r2.Msg) 37 | } -------------------------------------------------------------------------------- /ch13/13.3/grpc/protocol/hello.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // source: hello.proto 3 | 4 | package protocol 5 | 6 | import ( 7 | context "context" 8 | fmt "fmt" 9 | proto "github.com/golang/protobuf/proto" 10 | grpc "google.golang.org/grpc" 11 | codes "google.golang.org/grpc/codes" 12 | status "google.golang.org/grpc/status" 13 | math "math" 14 | ) 15 | 16 | // Reference imports to suppress errors if they are not otherwise used. 17 | var _ = proto.Marshal 18 | var _ = fmt.Errorf 19 | var _ = math.Inf 20 | 21 | // This is a compile-time assertion to ensure that this generated file 22 | // is compatible with the proto package it is being compiled against. 23 | // A compilation error at this line likely means your copy of the 24 | // proto package needs to be updated. 25 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 26 | 27 | type HelloRequest struct { 28 | Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` 29 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 30 | XXX_unrecognized []byte `json:"-"` 31 | XXX_sizecache int32 `json:"-"` 32 | } 33 | 34 | func (m *HelloRequest) Reset() { *m = HelloRequest{} } 35 | func (m *HelloRequest) String() string { return proto.CompactTextString(m) } 36 | func (*HelloRequest) ProtoMessage() {} 37 | func (*HelloRequest) Descriptor() ([]byte, []int) { 38 | return fileDescriptor_61ef911816e0a8ce, []int{0} 39 | } 40 | 41 | func (m *HelloRequest) XXX_Unmarshal(b []byte) error { 42 | return xxx_messageInfo_HelloRequest.Unmarshal(m, b) 43 | } 44 | func (m *HelloRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 45 | return xxx_messageInfo_HelloRequest.Marshal(b, m, deterministic) 46 | } 47 | func (m *HelloRequest) XXX_Merge(src proto.Message) { 48 | xxx_messageInfo_HelloRequest.Merge(m, src) 49 | } 50 | func (m *HelloRequest) XXX_Size() int { 51 | return xxx_messageInfo_HelloRequest.Size(m) 52 | } 53 | func (m *HelloRequest) XXX_DiscardUnknown() { 54 | xxx_messageInfo_HelloRequest.DiscardUnknown(m) 55 | } 56 | 57 | var xxx_messageInfo_HelloRequest proto.InternalMessageInfo 58 | 59 | func (m *HelloRequest) GetName() string { 60 | if m != nil { 61 | return m.Name 62 | } 63 | return "" 64 | } 65 | 66 | type HelloReplay struct { 67 | Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` 68 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 69 | XXX_unrecognized []byte `json:"-"` 70 | XXX_sizecache int32 `json:"-"` 71 | } 72 | 73 | func (m *HelloReplay) Reset() { *m = HelloReplay{} } 74 | func (m *HelloReplay) String() string { return proto.CompactTextString(m) } 75 | func (*HelloReplay) ProtoMessage() {} 76 | func (*HelloReplay) Descriptor() ([]byte, []int) { 77 | return fileDescriptor_61ef911816e0a8ce, []int{1} 78 | } 79 | 80 | func (m *HelloReplay) XXX_Unmarshal(b []byte) error { 81 | return xxx_messageInfo_HelloReplay.Unmarshal(m, b) 82 | } 83 | func (m *HelloReplay) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 84 | return xxx_messageInfo_HelloReplay.Marshal(b, m, deterministic) 85 | } 86 | func (m *HelloReplay) XXX_Merge(src proto.Message) { 87 | xxx_messageInfo_HelloReplay.Merge(m, src) 88 | } 89 | func (m *HelloReplay) XXX_Size() int { 90 | return xxx_messageInfo_HelloReplay.Size(m) 91 | } 92 | func (m *HelloReplay) XXX_DiscardUnknown() { 93 | xxx_messageInfo_HelloReplay.DiscardUnknown(m) 94 | } 95 | 96 | var xxx_messageInfo_HelloReplay proto.InternalMessageInfo 97 | 98 | func (m *HelloReplay) GetMessage() string { 99 | if m != nil { 100 | return m.Message 101 | } 102 | return "" 103 | } 104 | 105 | type HelloMessage struct { 106 | Msg string `protobuf:"bytes,1,opt,name=msg,proto3" json:"msg,omitempty"` 107 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 108 | XXX_unrecognized []byte `json:"-"` 109 | XXX_sizecache int32 `json:"-"` 110 | } 111 | 112 | func (m *HelloMessage) Reset() { *m = HelloMessage{} } 113 | func (m *HelloMessage) String() string { return proto.CompactTextString(m) } 114 | func (*HelloMessage) ProtoMessage() {} 115 | func (*HelloMessage) Descriptor() ([]byte, []int) { 116 | return fileDescriptor_61ef911816e0a8ce, []int{2} 117 | } 118 | 119 | func (m *HelloMessage) XXX_Unmarshal(b []byte) error { 120 | return xxx_messageInfo_HelloMessage.Unmarshal(m, b) 121 | } 122 | func (m *HelloMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 123 | return xxx_messageInfo_HelloMessage.Marshal(b, m, deterministic) 124 | } 125 | func (m *HelloMessage) XXX_Merge(src proto.Message) { 126 | xxx_messageInfo_HelloMessage.Merge(m, src) 127 | } 128 | func (m *HelloMessage) XXX_Size() int { 129 | return xxx_messageInfo_HelloMessage.Size(m) 130 | } 131 | func (m *HelloMessage) XXX_DiscardUnknown() { 132 | xxx_messageInfo_HelloMessage.DiscardUnknown(m) 133 | } 134 | 135 | var xxx_messageInfo_HelloMessage proto.InternalMessageInfo 136 | 137 | func (m *HelloMessage) GetMsg() string { 138 | if m != nil { 139 | return m.Msg 140 | } 141 | return "" 142 | } 143 | 144 | func init() { 145 | proto.RegisterType((*HelloRequest)(nil), "protocol.HelloRequest") 146 | proto.RegisterType((*HelloReplay)(nil), "protocol.HelloReplay") 147 | proto.RegisterType((*HelloMessage)(nil), "protocol.HelloMessage") 148 | } 149 | 150 | func init() { proto.RegisterFile("hello.proto", fileDescriptor_61ef911816e0a8ce) } 151 | 152 | var fileDescriptor_61ef911816e0a8ce = []byte{ 153 | // 177 bytes of a gzipped FileDescriptorProto 154 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0xce, 0x48, 0xcd, 0xc9, 155 | 0xc9, 0xd7, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x00, 0x53, 0xc9, 0xf9, 0x39, 0x4a, 0x4a, 156 | 0x5c, 0x3c, 0x1e, 0x20, 0x89, 0xa0, 0xd4, 0xc2, 0xd2, 0xd4, 0xe2, 0x12, 0x21, 0x21, 0x2e, 0x96, 157 | 0xbc, 0xc4, 0xdc, 0x54, 0x09, 0x46, 0x05, 0x46, 0x0d, 0xce, 0x20, 0x30, 0x5b, 0x49, 0x9d, 0x8b, 158 | 0x1b, 0xaa, 0xa6, 0x20, 0x27, 0xb1, 0x52, 0x48, 0x82, 0x8b, 0x3d, 0x37, 0xb5, 0xb8, 0x38, 0x31, 159 | 0x1d, 0xa6, 0x0a, 0xc6, 0x55, 0x52, 0x80, 0x1a, 0xe6, 0x0b, 0xe1, 0x0b, 0x09, 0x70, 0x31, 0xe7, 160 | 0x16, 0xa7, 0x43, 0x55, 0x81, 0x98, 0x46, 0xdd, 0x8c, 0x50, 0xb3, 0x82, 0x53, 0x8b, 0xca, 0x52, 161 | 0x8b, 0x84, 0xac, 0xb9, 0x38, 0x82, 0x13, 0x2b, 0xc1, 0x22, 0x42, 0x62, 0x7a, 0x30, 0x57, 0xe9, 162 | 0x21, 0x3b, 0x49, 0x4a, 0x14, 0x43, 0x1c, 0xe4, 0x0c, 0x25, 0x06, 0x21, 0x7b, 0x2e, 0x6e, 0xf7, 163 | 0xd4, 0x12, 0x88, 0x8d, 0xc5, 0xe9, 0x38, 0xf5, 0xa3, 0x8b, 0x43, 0x5d, 0xa7, 0xc4, 0x90, 0xc4, 164 | 0x06, 0x96, 0x30, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0xa4, 0xc8, 0x93, 0xa6, 0x1c, 0x01, 0x00, 165 | 0x00, 166 | } 167 | 168 | // Reference imports to suppress errors if they are not otherwise used. 169 | var _ context.Context 170 | var _ grpc.ClientConn 171 | 172 | // This is a compile-time assertion to ensure that this generated file 173 | // is compatible with the grpc package it is being compiled against. 174 | const _ = grpc.SupportPackageIsVersion4 175 | 176 | // HelloServerClient is the client API for HelloServer service. 177 | // 178 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. 179 | type HelloServerClient interface { 180 | // 创建第一个接口 181 | SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReplay, error) 182 | // 创建第二个接口 183 | GetHelloMsg(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloMessage, error) 184 | } 185 | 186 | type helloServerClient struct { 187 | cc *grpc.ClientConn 188 | } 189 | 190 | func NewHelloServerClient(cc *grpc.ClientConn) HelloServerClient { 191 | return &helloServerClient{cc} 192 | } 193 | 194 | func (c *helloServerClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReplay, error) { 195 | out := new(HelloReplay) 196 | err := c.cc.Invoke(ctx, "/protocol.HelloServer/SayHello", in, out, opts...) 197 | if err != nil { 198 | return nil, err 199 | } 200 | return out, nil 201 | } 202 | 203 | func (c *helloServerClient) GetHelloMsg(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloMessage, error) { 204 | out := new(HelloMessage) 205 | err := c.cc.Invoke(ctx, "/protocol.HelloServer/GetHelloMsg", in, out, opts...) 206 | if err != nil { 207 | return nil, err 208 | } 209 | return out, nil 210 | } 211 | 212 | // HelloServerServer is the server API for HelloServer service. 213 | type HelloServerServer interface { 214 | // 创建第一个接口 215 | SayHello(context.Context, *HelloRequest) (*HelloReplay, error) 216 | // 创建第二个接口 217 | GetHelloMsg(context.Context, *HelloRequest) (*HelloMessage, error) 218 | } 219 | 220 | // UnimplementedHelloServerServer can be embedded to have forward compatible implementations. 221 | type UnimplementedHelloServerServer struct { 222 | } 223 | 224 | func (*UnimplementedHelloServerServer) SayHello(ctx context.Context, req *HelloRequest) (*HelloReplay, error) { 225 | return nil, status.Errorf(codes.Unimplemented, "method SayHello not implemented") 226 | } 227 | func (*UnimplementedHelloServerServer) GetHelloMsg(ctx context.Context, req *HelloRequest) (*HelloMessage, error) { 228 | return nil, status.Errorf(codes.Unimplemented, "method GetHelloMsg not implemented") 229 | } 230 | 231 | func RegisterHelloServerServer(s *grpc.Server, srv HelloServerServer) { 232 | s.RegisterService(&_HelloServer_serviceDesc, srv) 233 | } 234 | 235 | func _HelloServer_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 236 | in := new(HelloRequest) 237 | if err := dec(in); err != nil { 238 | return nil, err 239 | } 240 | if interceptor == nil { 241 | return srv.(HelloServerServer).SayHello(ctx, in) 242 | } 243 | info := &grpc.UnaryServerInfo{ 244 | Server: srv, 245 | FullMethod: "/protocol.HelloServer/SayHello", 246 | } 247 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 248 | return srv.(HelloServerServer).SayHello(ctx, req.(*HelloRequest)) 249 | } 250 | return interceptor(ctx, in, info, handler) 251 | } 252 | 253 | func _HelloServer_GetHelloMsg_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 254 | in := new(HelloRequest) 255 | if err := dec(in); err != nil { 256 | return nil, err 257 | } 258 | if interceptor == nil { 259 | return srv.(HelloServerServer).GetHelloMsg(ctx, in) 260 | } 261 | info := &grpc.UnaryServerInfo{ 262 | Server: srv, 263 | FullMethod: "/protocol.HelloServer/GetHelloMsg", 264 | } 265 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 266 | return srv.(HelloServerServer).GetHelloMsg(ctx, req.(*HelloRequest)) 267 | } 268 | return interceptor(ctx, in, info, handler) 269 | } 270 | 271 | var _HelloServer_serviceDesc = grpc.ServiceDesc{ 272 | ServiceName: "protocol.HelloServer", 273 | HandlerType: (*HelloServerServer)(nil), 274 | Methods: []grpc.MethodDesc{ 275 | { 276 | MethodName: "SayHello", 277 | Handler: _HelloServer_SayHello_Handler, 278 | }, 279 | { 280 | MethodName: "GetHelloMsg", 281 | Handler: _HelloServer_GetHelloMsg_Handler, 282 | }, 283 | }, 284 | Streams: []grpc.StreamDesc{}, 285 | Metadata: "hello.proto", 286 | } 287 | -------------------------------------------------------------------------------- /ch13/13.3/grpc/protocol/hello.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package protocol; 3 | service HelloServer{ 4 | // 创建第一个接口 5 | rpc SayHello(HelloRequest)returns(HelloReplay){} 6 | // 创建第二个接口 7 | rpc GetHelloMsg(HelloRequest)returns(HelloMessage){} 8 | } 9 | message HelloRequest{ 10 | string name = 1 ; 11 | } 12 | message HelloReplay{ 13 | string message = 1; 14 | } 15 | message HelloMessage{ 16 | string msg = 1; 17 | } -------------------------------------------------------------------------------- /ch13/13.3/grpc/server/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | import ( 3 | "context" 4 | "fmt" 5 | "google.golang.org/grpc" 6 | pt "../protocol" 7 | "net" 8 | ) 9 | const ( 10 | post = "127.0.0.1:18887" 11 | ) 12 | //对象要和proto内定义的服务一样 13 | type server struct{} 14 | //实现RPC SayHello 接口 15 | func(s *server)SayHello(ctx context.Context,in *pt.HelloRequest)(*pt.HelloReplay , error){ 16 | return &pt.HelloReplay{Message:"hello"+in.GetName()},nil 17 | } 18 | //实现RPC GetHelloMsg 接口 19 | func (s *server) GetHelloMsg(ctx context.Context, in *pt.HelloRequest) (*pt.HelloMessage, error) { 20 | return &pt.HelloMessage{Msg: "this is from server!"}, nil 21 | } 22 | func main() { //监听网络 23 | ln ,err :=net.Listen("tcp",post) 24 | if err!=nil { 25 | fmt.Println("网络异常",err) } 26 | // 创建一个grpc的句柄 27 | srv:= grpc.NewServer() 28 | //将server结构体注册到 grpc服务中 29 | pt.RegisterHelloServerServer(srv,&server{}) 30 | //监听grpc服务 31 | err= srv.Serve(ln) 32 | if err!=nil { 33 | fmt.Println("网络启动异常",err) 34 | } 35 | } -------------------------------------------------------------------------------- /ch13/13.3/rpc/client/client.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "log" 6 | "net/rpc" 7 | "os" 8 | ) 9 | 10 | func main() { 11 | client, err := rpc.Dial("tcp", "localhost:13133") 12 | if err != nil { 13 | log.Fatal(err) 14 | } 15 | 16 | in := bufio.NewReader(os.Stdin) 17 | for { 18 | line, _, err := in.ReadLine() 19 | if err != nil { 20 | log.Fatal(err) 21 | } 22 | var reply bool 23 | err = client.Call("Listener.GetLine", line, &reply) 24 | if err != nil { 25 | log.Fatal(err) 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /ch13/13.3/rpc/server/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net" 7 | "net/rpc" 8 | ) 9 | 10 | type Listener int 11 | 12 | func (l *Listener) GetLine(line []byte, ack *bool) error { 13 | fmt.Println(string(line)) 14 | return nil 15 | } 16 | 17 | func main() { 18 | addy, err := net.ResolveTCPAddr("tcp", "0.0.0.0:13133") 19 | if err != nil { 20 | log.Fatal(err) 21 | } 22 | 23 | inbound, err := net.ListenTCP("tcp", addy) 24 | if err != nil { 25 | log.Fatal(err) 26 | } 27 | 28 | listener := new(Listener) 29 | rpc.Register(listener) 30 | rpc.Accept(inbound) 31 | } -------------------------------------------------------------------------------- /chapter0/sample.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func main() { 8 | fmt.Println("Go代码示例!") 9 | } 10 | -------------------------------------------------------------------------------- /chapter01/1.1/helloserver/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/http" 7 | ) 8 | 9 | func handler(w http.ResponseWriter,r *http.Request) { 10 | s := "你好,世界!" 11 | fmt.Fprintf(w,"%s",s) 12 | log.Printf("%s",s) 13 | } 14 | func main() { 15 | fmt.Println("server start.") 16 | http.HandleFunc("/",handler) 17 | if err := http.ListenAndServe("localhost:1234",nil); err != nil { 18 | log.Fatal("ListenAndServe:",err) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /chapter01/1.1/helloworld/hello: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottAI/book/5851b283d7dbfb91b42f5f4f1da4fbe6aec3acb4/chapter01/1.1/helloworld/hello -------------------------------------------------------------------------------- /chapter01/1.1/helloworld/hello.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println("Hello,World!") 7 | } 8 | -------------------------------------------------------------------------------- /chapter01/1.2/iota/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type data int 6 | 7 | 8 | const ( 9 | Zero data = iota 10 | One 11 | Two 12 | Three 13 | Four 14 | ) 15 | 16 | func main() { 17 | 18 | fmt.Println(Zero) 19 | fmt.Println(One) 20 | fmt.Println(Two) 21 | fmt.Println(Three) 22 | fmt.Println(Four) 23 | } -------------------------------------------------------------------------------- /chapter01/1.2/pointer/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | m := 1 7 | selfPlusPointer(&m) 8 | fmt.Println(m) 9 | fmt.Println(*selfPlus(1)) 10 | } 11 | 12 | func selfPlusPointer(n *int){ 13 | *n++ 14 | } 15 | 16 | func selfPlus(n int) *int { 17 | t := n+1 18 | return &t 19 | } -------------------------------------------------------------------------------- /chapter01/1.2/var/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | ) 7 | 8 | 9 | func main() { 10 | //多个变量一起通过类型声明 11 | var i,j,k int 12 | fmt.Printf("i:%d,j:%d,k:%d",i,j,k) 13 | fmt.Println() 14 | //多个变量一起通过表达式声明 15 | var a,b,c = 1,"s",true 16 | fmt.Printf("a:%d,b:%s,c:%t",a,b,c) 17 | fmt.Println() 18 | //声明赋值的缩写 19 | f := rand.Float64()*100 20 | fmt.Printf("f:%g",f) 21 | } 22 | -------------------------------------------------------------------------------- /chapter01/1.4/loop.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | for i:=0;i<10;i++{ 7 | if i%2 == 0{ 8 | continue 9 | } 10 | fmt.Print(i," ") 11 | } 12 | fmt.Println() 13 | i := 5 14 | for{ 15 | if i<1 { 16 | break 17 | } 18 | fmt.Print(i," ") 19 | i-- 20 | } 21 | 22 | fmt.Println() 23 | arr := []int{1,2,3,4,5} 24 | for i,v := range arr{ 25 | fmt.Println("index:",i,"value:",v) 26 | } 27 | } 28 | --------------------------------------------------------------------------------