├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── custom.md │ └── feature_request.md ├── .gitignore ├── 0000000.png ├── 14356536-39f8cf0c8c477958.png ├── 14356536-8d8e59539d37adbf.png ├── 14356536-c6687f7ef8ca3278.png ├── BootstrapTest ├── README.md ├── allCss.html ├── allJs.html ├── foot.html ├── head.html ├── index.html ├── index_text.html ├── layout.html ├── nav.html ├── text-left.html ├── text-right.html ├── text_center_article.html └── text_center_index.html ├── CONTRIBUTING.md ├── EXPLAIN.md ├── README.md ├── SQLTest ├── CRUD.sql ├── README.md ├── SELECT.sql ├── join.jpeg ├── mysql.sql └── pro.sql ├── a.png ├── alipay.jpeg ├── alipay1.jpeg ├── b.png ├── books.png ├── c.png ├── computergold.md ├── crawler └── chinaCity.csv ├── dart └── README.md ├── docker └── README.md ├── donate.png ├── files-logo.png ├── godemo ├── closureExplain │ └── closureExplain.go ├── !!!论接口和实体数据的断言更深了解.go ├── 10分钟学会go的数据库 │ └── main.go ├── 10分钟开发一个网站 │ ├── index.html │ ├── index.js │ ├── install.sh │ ├── log-post.html │ ├── log.html │ ├── main.go │ ├── upload-get.html │ └── uploadfile.html ├── LICENSE ├── Parallelism │ ├── Parallelism.go │ ├── number.go │ └── plus.go ├── ProducerConsumerModel │ └── README.md ├── README.md ├── RESTful │ └── RESTful.go ├── SortMap-map的排序.go ├── assert │ └── assert.go ├── blockchain_demo-blockworld │ └── main.go ├── channel │ └── channel.go ├── crawler │ ├── crawler.go │ ├── crawler_test.go │ └── p5 │ │ └── main.go ├── defers │ └── defers.go ├── doc │ ├── A6EF733E-AC56-4E33-9D2B-C3A6980007BB.png │ ├── attentions.md │ ├── basic.md │ ├── golang-run.png │ └── spec.md ├── func │ └── func.go ├── gin-session-cookie │ └── main.go ├── go+mysql实现注册登陆功能 │ ├── README.md │ ├── controller │ │ └── main.go │ ├── data │ │ └── datebase.text │ ├── main.go │ ├── model │ │ ├── helper.go │ │ └── main.go │ ├── static │ │ └── te.md │ ├── text │ └── view │ │ ├── layout.html │ │ ├── login.html │ │ └── logon.html ├── go_testing_examples │ ├── reverse.go │ └── reverse_test.go ├── goruntime │ └── goruntime.go ├── go中defer和return的执行过程.md ├── go对象(struct结构体)总结.go ├── go编译器内部真实处理的三种方式.go ├── hashsha1等hash加密方式的基本加密方式.go ├── hideInterface │ ├── hideInterface.go │ └── hideInterface.md ├── httpServer │ └── httpServer.go ├── inheritMethod │ └── inhertMethod.go ├── init的执行顺序.go ├── interfaceS │ ├── interface │ ├── interface.go │ ├── interface.md │ └── interface2.go ├── localStorge_demo.html ├── machine_lione.go ├── main │ └── main.go ├── maopao │ └── index.go ├── map │ ├── map.go │ └── map2.go ├── method │ └── method.go ├── newTon │ └── newTon.go ├── pachong │ └── pachong.go ├── pointer │ └── pointer.go ├── queue-队列.md ├── queue │ ├── 1.1.go │ ├── 1.2.go │ ├── 1.go │ ├── 2.1.go │ ├── 2.2.go │ ├── 2.go │ ├── 3.1.go │ ├── 3.2.go │ ├── 3.go │ └── README.md ├── rang │ └── rang.go ├── readFileFromLocation从本地读取文件并输出.go ├── recover-panic-String的使用方式.go ├── recover恢复机制的使用条件.go ├── rpc_gob_micro │ ├── gob.go │ └── rpc.go ├── runtime的WaitGroup这个函数的写法以及知道在运行中的协程并没有顺序可言.go ├── salt │ ├── salt.go │ └── salt_test.go ├── select │ └── select.go ├── select和done提醒者模式的结合.go ├── server-client.go ├── slice │ └── moreSlice.go ├── strings │ ├── srings.go │ └── stringsHasPreFix_plus.md ├── struct │ ├── orgin.go │ ├── struct.go │ └── structPluss.go ├── switchNil │ └── switchNil.go ├── sync.Pool │ └── README.md ├── time │ └── time.go ├── time包中的tick和After函数的运用.go ├── tour_go_stringer_example.go ├── twoGive │ └── twoGive.go ├── typeFuc │ └── typeFuc.go ├── waitGroup-chan-context-time.After.md ├── web-test │ ├── web │ └── web.go ├── web │ └── web.go ├── 一种接口变量不是空但是传入的类型却是空的一个不太容易感觉到的小技巧或者很容易出错的地方.go ├── 互斥锁的简单应用.go ├── 使用go获取跟curl简单功能相同的功能.go ├── 使用json.go ├── 使用map和json和os包快速生成json文件.go ├── 使用readLine进行读写数据.go ├── 关于匿名函数的几点.go ├── 关于引用类型和实体类型的零值问题.go ├── 关于循环变量的三种情况.go ├── 关于结构体对象和接口的一些总结.go ├── 关于闭包协程的三种方式的异同以及实现.go ├── 冒泡法bad-good.go ├── 几种ok模式.go ├── 函数式编程.go ├── 创建命令.go ├── 利用slice和sort包来解决map的无序问题.go ├── 十分钟学会session_cookie │ └── main.go ├── 去除相邻的重复值.go ├── 在编译期间检查某类型是否实现了某个接口.go ├── 处理字符串.go ├── 多返回值的用法.go ├── 如何辨别两个字符串的每一个字符_字符相同顺序可以不同的判断方法.go ├── 对于select的初步认识.go ├── 工厂模式(看起来最简洁最解耦的模式).go ├── 工厂模式.go ├── 并发和并行的一系类实例 │ ├── add │ │ ├── add.go │ │ ├── add_example.go │ │ ├── add_test.go │ │ └── data.go │ ├── bubbleSort │ │ ├── bubbleSort.go │ │ ├── bubbleSort_test.go │ │ └── data.go │ ├── context │ │ ├── README.md │ │ ├── cancel │ │ │ └── main.go │ │ ├── deadline │ │ │ └── main.go │ │ ├── timeout │ │ │ └── main.go │ │ └── waitgroup │ │ │ ├── main.go │ │ │ └── main_test.go │ └── readFile │ │ ├── data.go │ │ ├── readfile.go │ │ └── readfile_test.go ├── 并行和为什么出现死锁的原因两块知识.go ├── 惰性生成器.go ├── 探秘局部变量的逃逸问题.go ├── 探究闭包在go里的应用.go ├── 操作字符串的最佳选择.go ├── 洗牌算法 │ └── README.md ├── 消除string中多余的空格只留一个(或者其它上面东西).go ├── 生产者消费者模式经典案例.go ├── 简单超时模式.go ├── 统计字符书目.go ├── 缓存技术.go ├── 论go的new是谁的语法糖-论本来就是指针类型和取实体类型的指针.go ├── 论出现指针赋值的时候出现空指针的原因.go ├── 证明所有类型都可以实现一个接口.go ├── 读写文件并且更改文件中的部分bytebyte.go ├── 调用本机命令行.go ├── 返回相反的slice顺序.go ├── 递归系列---尾递归的基本阐述.go ├── 递归系列---普通递归处理深度问题使用golang.org_x_net_htm包来处理html结构问题_也可以用到爬虫上的技术.go ├── 闭包中的变量问题的清晰证明以及接口变量的一些问题.go ├── 闭包测试1.go ├── 高级用法_信号量_go异步写法.go └── 高级用法_工厂模式_go的通道协程异步问题.go ├── gop_homework ├── README.md ├── ch1 │ ├── dup1 │ │ └── main.go │ ├── dup2 │ │ └── main.go │ ├── dup3 │ │ └── main.go │ ├── echo1 │ │ └── main.go │ ├── echo2 │ │ └── main.go │ ├── echo3 │ │ └── main.go │ ├── fetch │ │ └── main.go │ ├── fetchall │ │ └── main.go │ ├── helloworld │ │ └── main.go │ ├── lissajous │ │ └── main.go │ ├── server1 │ │ └── main.go │ ├── server2 │ │ └── main.go │ ├── server3 │ │ └── main.go │ └── 第一章练习题 │ │ ├── 练习1.1 │ │ └── main.go │ │ ├── 练习1.10 │ │ └── main.go │ │ ├── 练习1.11 │ │ └── main.go │ │ ├── 练习1.12 │ │ └── main.go │ │ ├── 练习1.2 │ │ └── main.go │ │ ├── 练习1.3 │ │ └── main.go │ │ ├── 练习1.4 │ │ ├── main.go │ │ ├── test.txt │ │ ├── test1.txt │ │ └── test2.txt │ │ ├── 练习1.5 │ │ ├── main.go │ │ └── tt.gif │ │ ├── 练习1.6 │ │ ├── main.go │ │ └── tt.gif │ │ ├── 练习1.7 │ │ └── main.go │ │ ├── 练习1.8 │ │ └── main.go │ │ └── 练习1.9 │ │ └── main.go ├── ch10 │ ├── cross │ │ └── main.go │ ├── homework │ │ ├── test10.1 │ │ │ ├── dd.jpeg │ │ │ ├── dd.png │ │ │ ├── gif.gif │ │ │ ├── main.go │ │ │ └── t.zip │ │ ├── test10.2 │ │ │ ├── gif.gif │ │ │ ├── main.go │ │ │ ├── t.tar │ │ │ └── t.zip │ │ ├── test10.3 │ │ │ └── main.go │ │ └── test10.4 │ │ │ └── main.go │ └── jpeg │ │ └── main.go ├── ch11 │ ├── echo │ │ ├── echo.go │ │ └── echo_test.go │ ├── homework │ │ ├── test11.1 │ │ │ ├── main.go │ │ │ └── main_test.go │ │ ├── test11.2 │ │ │ ├── intset.go │ │ │ └── intset_test.go │ │ ├── test11.3 │ │ │ └── t_test.go │ │ ├── test11.4 │ │ │ └── main.go │ │ ├── test11.5 │ │ │ └── main.go │ │ ├── test11.6 │ │ │ └── main.go │ │ └── test11.7 │ │ │ └── main.go │ ├── storage1 │ │ └── storage.go │ ├── storage2 │ │ ├── quota_test.go │ │ └── storage.go │ ├── word1 │ │ ├── word.go │ │ └── word_test.go │ └── word2 │ │ ├── word.go │ │ └── word_test.go ├── ch12 │ ├── display │ │ ├── display.go │ │ └── display_test.go │ ├── format │ │ ├── format.go │ │ └── format_test.go │ ├── methods │ │ ├── methods.go │ │ └── methods_test.go │ ├── params │ │ └── params.go │ ├── search │ │ └── main.go │ └── sexpr │ │ ├── decode.go │ │ ├── encode.go │ │ ├── pretty.go │ │ └── sexpr_test.go ├── ch13 │ ├── bzip-print │ │ ├── bzip2.c │ │ ├── bzip2.go │ │ └── bzip2_test.go │ ├── bzip │ │ ├── bzip2.c │ │ ├── bzip2.go │ │ └── bzip2_test.go │ ├── bzipper │ │ └── main.go │ ├── equal │ │ ├── equal.go │ │ └── equal_test.go │ └── unsafeptr │ │ └── main.go ├── ch2 │ ├── boiling │ │ └── main.go │ ├── cf │ │ └── main.go │ ├── echo4 │ │ └── main.go │ ├── ftoc │ │ └── main.go │ ├── popcount │ │ ├── main.go │ │ └── popcount_test.go │ ├── tempconv │ │ ├── conv.go │ │ └── tempconv.go │ ├── tempconv0 │ │ ├── celsius.go │ │ └── tempconv_test.go │ └── 第二章练习题 │ │ ├── 练习2.1 │ │ └── main.go │ │ ├── 练习2.2 │ │ └── main.go │ │ ├── 练习2.3 │ │ ├── popcount.go │ │ └── popcount_test.go │ │ ├── 练习2.4 │ │ ├── main.go │ │ └── main_test.go │ │ └── 练习2.5 │ │ ├── main.go │ │ └── main_test.go ├── ch3 │ ├── basename1 │ │ └── main.go │ ├── basename2 │ │ └── main.go │ ├── comma │ │ └── main.go │ ├── mandelbrot │ │ └── main.go │ ├── netflag │ │ └── netflag.go │ ├── printints │ │ └── main.go │ ├── surface │ │ └── main.go │ └── 第三章练习题 │ │ ├── 练习3.1 │ │ └── main.go │ │ ├── 练习3.10 │ │ ├── main.go │ │ ├── main_test.go │ │ └── test.txt │ │ ├── 练习3.11 │ │ ├── main.go │ │ └── main_test.go │ │ ├── 练习3.12 │ │ ├── example_test.go │ │ ├── main.go │ │ └── main_test.go │ │ ├── 练习3.13 │ │ └── main.go │ │ ├── 练习3.2 │ │ └── main.go │ │ ├── 练习3.3 │ │ └── main.go │ │ ├── 练习3.4 │ │ └── main.go │ │ ├── 练习3.5 │ │ ├── main.go │ │ └── tt.png │ │ ├── 练习3.6 │ │ └── main.go │ │ ├── 练习3.7 │ │ └── main.go │ │ ├── 练习3.8 │ │ ├── main.go │ │ └── main_test.go │ │ └── 练习3.9 │ │ └── main.go ├── ch4 │ ├── append │ │ └── main.go │ ├── autoescape │ │ └── main.go │ ├── charcount │ │ └── main.go │ ├── dedup │ │ └── main.go │ ├── embed │ │ └── main.go │ ├── github │ │ ├── github.go │ │ └── search.go │ ├── graph │ │ └── main.go │ ├── homework │ │ ├── test4.1 │ │ │ └── main.go │ │ ├── test4.10 │ │ │ └── main.go │ │ ├── test4.11 │ │ │ └── main.go │ │ ├── test4.12 │ │ │ └── main.go │ │ ├── test4.13 │ │ │ ├── main.go │ │ │ ├── text.md │ │ │ └── text.png │ │ ├── test4.14 │ │ │ ├── 1.2.html │ │ │ ├── 2.html │ │ │ ├── alipay.jpeg │ │ │ ├── alipay1.jpeg │ │ │ ├── client │ │ │ │ └── main.go │ │ │ ├── coastroad.net.crt │ │ │ ├── coastroad.net.key │ │ │ ├── data.go │ │ │ ├── donate.html │ │ │ ├── favicon.ico │ │ │ ├── main.go │ │ │ ├── search.html │ │ │ ├── transfer │ │ │ │ └── main.go │ │ │ ├── wechat.png │ │ │ └── wechat1.png │ │ ├── test4.2 │ │ │ └── main.go │ │ ├── test4.3 │ │ │ └── main.go │ │ ├── test4.4 │ │ │ └── main.go │ │ ├── test4.5 │ │ │ └── main.go │ │ ├── test4.6 │ │ │ └── main.go │ │ ├── test4.7 │ │ │ └── main.go │ │ ├── test4.8 │ │ │ └── main.go │ │ └── test4.9 │ │ │ ├── main.go │ │ │ ├── test4.9 │ │ │ └── tt.txt │ ├── issues │ │ └── main.go │ ├── issueshtml │ │ └── main.go │ ├── issuesreport │ │ └── main.go │ ├── movie │ │ └── main.go │ ├── nonempty │ │ └── main.go │ ├── rev │ │ └── main.go │ ├── sha256 │ │ └── main.go │ └── treesort │ │ ├── sort.go │ │ └── sort_test.go ├── ch5 │ ├── defer1 │ │ └── defer.go │ ├── defer2 │ │ └── defer.go │ ├── fetch │ │ └── main.go │ ├── findlinks1 │ │ └── main.go │ ├── findlinks2 │ │ └── main.go │ ├── findlinks3 │ │ └── findlinks.go │ ├── homework │ │ ├── test5.1 │ │ │ ├── main.go │ │ │ └── main_test.go │ │ ├── test5.10 │ │ │ └── main.go │ │ ├── test5.11 │ │ │ └── main.go │ │ ├── test5.12 │ │ │ └── main.go │ │ ├── test5.13 │ │ │ └── main.go │ │ ├── test5.14 │ │ │ └── main.go │ │ ├── test5.15 │ │ │ ├── main.go │ │ │ └── main_test.go │ │ ├── test5.16 │ │ │ ├── main.go │ │ │ └── main_test.go │ │ ├── test5.17 │ │ │ └── main.go │ │ ├── test5.18 │ │ │ ├── donate │ │ │ └── main.go │ │ ├── test5.19 │ │ │ └── main.go │ │ ├── test5.2 │ │ │ └── main.go │ │ ├── test5.3 │ │ │ └── main.go │ │ ├── test5.4 │ │ │ └── main.go │ │ ├── test5.5 │ │ │ ├── data.go │ │ │ ├── main.go │ │ │ └── main_test.go │ │ ├── test5.6 │ │ │ ├── main.go │ │ │ └── tt.svg │ │ ├── test5.7 │ │ │ ├── main.go │ │ │ └── main_test.go │ │ ├── test5.8 │ │ │ └── main.go │ │ └── test5.9 │ │ │ └── main.go │ ├── links │ │ └── links.go │ ├── outline │ │ └── main.go │ ├── outline2 │ │ └── outline.go │ ├── squares │ │ └── main.go │ ├── sum │ │ └── main.go │ ├── title1 │ │ └── title.go │ ├── title2 │ │ └── title.go │ ├── title3 │ │ └── title.go │ ├── toposort │ │ └── main.go │ ├── trace │ │ └── main.go │ └── wait │ │ └── wait.go ├── ch6 │ ├── coloredpoint │ │ └── main.go │ ├── geometry │ │ └── geometry.go │ ├── homework │ │ ├── test6.1 │ │ │ ├── main.go │ │ │ └── main_test.go │ │ ├── test6.2 │ │ │ └── main.go │ │ ├── test6.3 │ │ │ └── main.go │ │ ├── test6.4 │ │ │ └── main.go │ │ └── test6.5 │ │ │ └── main.go │ ├── intset │ │ ├── intset.go │ │ └── intset_test.go │ └── urlvalues │ │ └── main.go ├── ch7 │ ├── bytecounter │ │ └── main.go │ ├── eval │ │ ├── ast.go │ │ ├── check.go │ │ ├── coverage_test.go │ │ ├── eval.go │ │ ├── eval_test.go │ │ ├── parse.go │ │ └── print.go │ ├── homework │ │ ├── test7.1 │ │ │ └── main.go │ │ ├── test7.10 │ │ │ └── main.go │ │ ├── test7.11 │ │ │ └── main.go │ │ ├── test7.12 │ │ │ └── main.go │ │ ├── test7.13 │ │ │ └── main.go │ │ ├── test7.14 │ │ │ └── main.go │ │ ├── test7.15 │ │ │ └── main.go │ │ ├── test7.16 │ │ │ ├── main.go │ │ │ └── main.html │ │ ├── test7.17 │ │ │ └── main.go │ │ ├── test7.18 │ │ │ └── main.go │ │ ├── test7.2 │ │ │ └── main.go │ │ ├── test7.3 │ │ │ ├── main.go │ │ │ └── main_test.go │ │ ├── test7.4 │ │ │ └── main.go │ │ ├── test7.5 │ │ │ └── main.go │ │ ├── test7.6 │ │ │ └── main.go │ │ ├── test7.7 │ │ │ └── main.go │ │ ├── test7.8 │ │ │ └── main.go │ │ └── test7.9 │ │ │ └── main.go │ ├── http1 │ │ └── main.go │ ├── http2 │ │ └── main.go │ ├── http3 │ │ └── main.go │ ├── http3a │ │ └── main.go │ ├── http4 │ │ └── main.go │ ├── sleep │ │ └── sleep.go │ ├── sorting │ │ └── main.go │ ├── surface │ │ └── surface.go │ ├── tempconv │ │ ├── tempconv.go │ │ └── tempconv.go.~master~ │ ├── tempflag │ │ └── tempflag.go │ └── xmlselect │ │ └── main.go ├── ch8 │ ├── cake │ │ ├── cake.go │ │ └── cake_test.go │ ├── chat │ │ ├── chat.go │ │ └── chat.go.~master~ │ ├── clock1 │ │ └── clock.go │ ├── clock2 │ │ └── clock.go │ ├── countdown1 │ │ └── countdown.go │ ├── countdown2 │ │ └── countdown.go │ ├── countdown3 │ │ └── countdown.go │ ├── crawl1 │ │ └── findlinks.go │ ├── crawl2 │ │ └── findlinks.go │ ├── crawl3 │ │ └── findlinks.go │ ├── du1 │ │ └── main.go │ ├── du2 │ │ └── main.go │ ├── du3 │ │ └── main.go │ ├── du4 │ │ └── main.go │ ├── homework │ │ ├── test8.1 │ │ │ ├── main.go │ │ │ └── w │ │ │ │ └── wall.go │ │ ├── test8.10 │ │ │ └── main.go │ │ ├── test8.11 │ │ │ └── main.go │ │ ├── test8.12 │ │ │ └── main.go │ │ ├── test8.13 │ │ │ └── main.go │ │ ├── test8.14 │ │ │ └── main.go │ │ ├── test8.15 │ │ │ └── main.go │ │ ├── test8.2 │ │ │ └── main.go │ │ ├── test8.3 │ │ │ └── main.go │ │ ├── test8.4 │ │ │ └── main.go │ │ ├── test8.5 │ │ │ └── main.go │ │ ├── test8.6 │ │ │ └── main.go │ │ ├── test8.7 │ │ │ └── main.go │ │ ├── test8.8 │ │ │ └── main.go │ │ └── test8.9 │ │ │ └── main.go │ ├── netcat1 │ │ └── netcat.go │ ├── netcat2 │ │ └── netcat.go │ ├── netcat3 │ │ └── netcat.go │ ├── pipeline1 │ │ └── main.go │ ├── pipeline2 │ │ └── main.go │ ├── pipeline3 │ │ └── main.go │ ├── reverb1 │ │ └── reverb.go │ ├── reverb2 │ │ └── reverb.go │ ├── spinner │ │ └── main.go │ └── thumbnail │ │ ├── main.go │ │ ├── thumbnail.go │ │ └── thumbnail_test.go └── ch9 │ ├── bank1 │ ├── bank.go │ └── bank_test.go │ ├── bank2 │ ├── bank.go │ └── bank_test.go │ ├── bank3 │ ├── bank.go │ └── bank_test.go │ ├── homework │ ├── test9.1 │ │ └── main.go │ ├── test9.2 │ │ └── main.go │ ├── test9.3 │ │ └── main.go │ ├── test9.4 │ │ └── main.go │ ├── test9.5 │ │ └── main.go │ └── test9.6 │ │ ├── data.go │ │ ├── main.go │ │ └── main_test.go │ ├── memo │ ├── memo.go │ └── memo_test.go │ ├── memo2 │ ├── memo.go │ └── memo_test.go │ ├── memo3 │ ├── memo.go │ └── memo_test.go │ ├── memo4 │ ├── memo.go │ └── memo_test.go │ ├── memo5 │ ├── memo.go │ └── memo_test.go │ └── memotest │ └── memotest.go ├── helloC └── README.md ├── helloDart ├── README.md ├── hello.dart └── main.go ├── helloPython └── README.md ├── helloShellScript ├── README.md └── restart │ ├── README.md │ └── restart.sh ├── huihuilovemetoo.md ├── ilovehuihui.md ├── joinMyGroup.png ├── joinPublic.png ├── mymy.png ├── pluspro.png ├── reviewJavaScript └── README.md ├── wechat1.png └── 正则.md /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/custom.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Custom issue template 3 | about: Describe this issue template's purpose here. 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.idea 2 | *.mod 3 | *.sum 4 | .DS_Store 5 | -------------------------------------------------------------------------------- /0000000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/0000000.png -------------------------------------------------------------------------------- /14356536-39f8cf0c8c477958.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/14356536-39f8cf0c8c477958.png -------------------------------------------------------------------------------- /14356536-8d8e59539d37adbf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/14356536-8d8e59539d37adbf.png -------------------------------------------------------------------------------- /14356536-c6687f7ef8ca3278.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/14356536-c6687f7ef8ca3278.png -------------------------------------------------------------------------------- /BootstrapTest/README.md: -------------------------------------------------------------------------------- 1 | # Bootstrap 练习 2 | -------------------------------------------------------------------------------- /BootstrapTest/allCss.html: -------------------------------------------------------------------------------- 1 | {{define "allcss"}} 2 | 5 | {{end}} -------------------------------------------------------------------------------- /BootstrapTest/allJs.html: -------------------------------------------------------------------------------- 1 | {{define "allJs"}} 2 | 5 | {{end}} -------------------------------------------------------------------------------- /BootstrapTest/foot.html: -------------------------------------------------------------------------------- 1 | {{define "foot"}} 2 |
3 |
4 | 5 |
6 |
7 | {{end}} -------------------------------------------------------------------------------- /BootstrapTest/index.html: -------------------------------------------------------------------------------- 1 | {{define "index"}} 2 | {{template "nav"}} 3 | {{template "text"}} 4 | {{template "foot"}} 5 | {{end}} -------------------------------------------------------------------------------- /BootstrapTest/index_text.html: -------------------------------------------------------------------------------- 1 | {{define "text"}} 2 |
3 |
4 |
5 | {{template "text_left"}} 6 |
7 |
8 |
9 | {{template "text_right"}} 10 |
11 |
12 |
13 | {{end}} -------------------------------------------------------------------------------- /BootstrapTest/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{template "head"}} 5 | {{template "allcss"}} 6 | 7 | 8 | {{ template "index"}} 9 | 10 | {{template "allcss"}} 11 | -------------------------------------------------------------------------------- /BootstrapTest/nav.html: -------------------------------------------------------------------------------- 1 | {{define "nav"}} 2 |
3 |
4 | 5 |
6 |
7 | {{end}} -------------------------------------------------------------------------------- /BootstrapTest/text-left.html: -------------------------------------------------------------------------------- 1 | {{define "text_left"}} 2 | {{end}} -------------------------------------------------------------------------------- /BootstrapTest/text-right.html: -------------------------------------------------------------------------------- 1 | {{define "text_right"}} 2 | {{end}} -------------------------------------------------------------------------------- /BootstrapTest/text_center_article.html: -------------------------------------------------------------------------------- 1 | {{define "text_center"}} 2 | {{end}} -------------------------------------------------------------------------------- /BootstrapTest/text_center_index.html: -------------------------------------------------------------------------------- 1 | {{define "text_center"}} 2 | {{end}} -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | [[googege](https://github.com/googege)](mailto://imgoogege@gmail.com) 2 | -------------------------------------------------------------------------------- /SQLTest/CRUD.sql: -------------------------------------------------------------------------------- 1 | -- 增删改 insert delete update 2 | -- INSERT 3 | INSERT table_name SET name='fsdf',year=1; -- 往 values 表插入 name和year的数据,数据的实际值是 "12" 1908 4 | -- 多批次增加Insert 5 | ("1",12), 6 | ("2",3), 7 | ("3",23); -- primary key 也就是主键不用写出啦了,它自己会增加,另外有默认值的也可以不写,但是没有默认值并且不能为null的一定要写出来。 8 | -- update 9 | UPDATE table_name SET name='1',year=1 WHERE id >10; 10 | --- update的计算 11 | UPDATE values SET name=name +1 WHERE id>10 AND id <5; 12 | -- ⚠️ 13 | UPDATE values SET name="1";-- 像这种没有WHERE的语句,非常的危险,容易更新全部的信息。 14 | -- Delete 15 | DELETE FROM values WHERE id=12; 16 | -- ⚠️ 17 | DELETE FROM values --这样就删掉了全部,很危险 18 | -- INNER INTO 和SELECT结合,也就是将values的值用SELECT的值来代替了。 19 | INNER INTO coastroad(name,id) SELECT r.name,r,id FROM room r WHERE id>10; 20 | // 删除。 21 | DELETE FROM userinfo WHERE uid=? 22 | // INSERT 23 | INSERT userinfo SET username=?,department=?,created=? 24 | 25 | -------------------------------------------------------------------------------- /SQLTest/README.md: -------------------------------------------------------------------------------- 1 | # sql -mysql 练习 2 | - [basic-SELECT sql](./SELECT.sql) 3 | - [basic-CRUD sql](./CRUD.sql) 4 | - [sql技巧,sql安全等进阶 sql](./pro.sql) 5 | 6 | -------------------------------------------------------------------------------- /SQLTest/join.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/SQLTest/join.jpeg -------------------------------------------------------------------------------- /SQLTest/mysql.sql: -------------------------------------------------------------------------------- 1 | -- 关于mysql本身 2 | 3 | -- 创建一个数据库 CREAT DATABASE [databasename] 4 | CREATE DATABASE coastroad; 5 | -- 切换到这个数据库 6 | USE coastroad; 7 | -- 删除一个数据库 8 | DROP DATABASE coastroad; 9 | -- 显示 :显示出所有的数据库 显示出所有的表 10 | SHOW DATABASES ; SHOW TABLES; 11 | --- 断开client和server的连接。 12 | EXIT; 13 | --- 事务 14 | SET TRANSACTION ISOLATION LEVEL REPEATABLE READ ; 15 | BEGIN ;-- 开始内容 16 | INNER INTO values(id ,name n)values (99,92); 17 | COMMIT ;-- 停止 18 | 19 | -------------------------------------------------------------------------------- /a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/a.png -------------------------------------------------------------------------------- /alipay.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/alipay.jpeg -------------------------------------------------------------------------------- /alipay1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/alipay1.jpeg -------------------------------------------------------------------------------- /b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/b.png -------------------------------------------------------------------------------- /books.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/books.png -------------------------------------------------------------------------------- /c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/c.png -------------------------------------------------------------------------------- /computergold.md: -------------------------------------------------------------------------------- 1 | # 计算机黄金--- 计算机里的小技巧 2 | 3 | - 如何判断系统是32位或者是64位 4 | ```go 5 | const IS64 = 32 << (^uint(0) >> 63) // 判断是否是64位平台。// 这样就可以照顾是32和64位系统了。 6 | //使用这么个常量,可以很好的解决问题。 7 | ``` 8 | - 在godoc中也就是其实是gofmt中的一些小技巧 9 | 10 | 1. 使用`/*ff*/`这种题头的注释才会出现在godoc.org的题头 `///`是不行的 11 | 12 | 2. 使用 Func ExampleSomthing 才会有那种example 13 | -------------------------------------------------------------------------------- /crawler/chinaCity.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/crawler/chinaCity.csv -------------------------------------------------------------------------------- /dart/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/dart/README.md -------------------------------------------------------------------------------- /docker/README.md: -------------------------------------------------------------------------------- 1 | ## docker 入门 2 | ### docker 常用命令 3 | ```bash 4 | 5 | ``` -------------------------------------------------------------------------------- /donate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/donate.png -------------------------------------------------------------------------------- /files-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/files-logo.png -------------------------------------------------------------------------------- /godemo/closureExplain/closureExplain.go: -------------------------------------------------------------------------------- 1 | //本包主要是为了测试**闭包**这个特性 2 | 3 | package closureExplain 4 | 5 | import ( 6 | "fmt" 7 | ) 8 | 9 | func run() func(x int) int {// 注意 这个地方返回一个函数 10 | sum := 0 11 | return func(x int) int{//注意返回值,单个不需要括号,如果是多个是需要括号的。 12 | sum += x 13 | return sum 14 | } 15 | } 16 | 17 | func init() { 18 | a, b := run(), run()// run运行后返回一个func x 19 | 20 | a1 := a(10)// x 再次执行,返回一个sum 21 | b1 := b(12) 22 | //这里我们就发现了,a b 接收到的两个run执行的返回值,也就是能绑定两个变量。 23 | fmt.Print(a1,b1) 24 | } 25 | 26 | -------------------------------------------------------------------------------- /godemo/10分钟开发一个网站/install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | go run ./main.go 3 | -------------------------------------------------------------------------------- /godemo/10分钟开发一个网站/log-post.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CoastRoad 考研社区 6 | 13 | 14 | 15 |

将在5秒后返回主Home

16 | 17 |

18 | ThomasHuke就是🐂 😁 。 19 |

20 | 21 |

显示的内容是

22 | 用户名是:{{.username}} 23 |
24 | 密码是: {{.password}} 25 | 26 | {{range $nu,$in := .interesting}} 27 | 最喜欢的公司有 28 |
  • 第{{$nu}}个:{{$in}}
  • 29 |
    30 | {{end}} 31 | 最爱的apple笔记本是:{{.type}} 32 | 33 | 34 | -------------------------------------------------------------------------------- /godemo/10分钟开发一个网站/log.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | CoastRoad 考研社区 7 | 8 | 9 | 您的登录页面应该在主页面HOME 10 | 11 | 12 | -------------------------------------------------------------------------------- /godemo/10分钟开发一个网站/upload-get.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | coastroad 考研社区 6 | 7 | 8 |
    9 |

    10 | 请选择您的文件 11 |

    12 | 13 | 14 | 15 | 16 |
    17 | 18 | 19 | -------------------------------------------------------------------------------- /godemo/10分钟开发一个网站/uploadfile.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CoastRoad 考研社区 6 | 7 | 8 | {{.}} 9 | 10 | 11 | -------------------------------------------------------------------------------- /godemo/Parallelism/Parallelism.go: -------------------------------------------------------------------------------- 1 | //这个包内详细介绍了 golang的并发和并行。之前golang还只能并发,如今,golang可以实现真正的并行 2 | package Parallelism 3 | 4 | 5 | 6 | import ( 7 | "fmt" 8 | "runtime" 9 | ) 10 | 11 | func run(value string) { 12 | for i := 0; i<=10; i++ { 13 | runtime.Gosched()//让CPU将时间片段让给别人。下次再执行 14 | fmt.Println(value) 15 | } 16 | } 17 | 18 | func init() { 19 | go run("ThomasHuke") 20 | run("Hello") 21 | } 22 | 23 | // Hello 24 | // ThomasHuke 25 | // Hello 26 | // Hello 27 | // ThomasHuke 28 | // Hello 29 | // ThomasHuke 30 | // Hello 31 | // ThomasHuke 32 | // Hello 33 | // ThomasHuke 34 | // Hello 35 | // ThomasHuke 36 | // Hello 37 | // ThomasHuke 38 | // Hello 39 | // ThomasHuke 40 | // Hello 41 | // ThomasHuke 42 | // Hello 43 | // ThomasHuke 44 | // ThomasHuke -------------------------------------------------------------------------------- /godemo/Parallelism/number.go: -------------------------------------------------------------------------------- 1 | package Parallelism 2 | 3 | import "fmt" 4 | 5 | func init() { 6 | c := make(chan int, 2) 7 | c <- 1 8 | c <- 2 9 | fmt.Print(<-c) 10 | fmt.Print(<-c) 11 | } 12 | -------------------------------------------------------------------------------- /godemo/Parallelism/plus.go: -------------------------------------------------------------------------------- 1 | package Parallelism 2 | 3 | 4 | 5 | import "fmt" 6 | //首先如果是并行处理的话,那么每一个go都会开启一个协程 7 | //协程之间通信使用chanel 来通信。也就是简称的chan来通信。 8 | 9 | func run (c chan int, d []int) { 10 | a := 0 11 | for _, value := range d { 12 | a += value 13 | } 14 | c <- a 15 | } 16 | 17 | func init() { 18 | a := []int{1, 2, 3 ,4 ,5 ,5} 19 | c := make(chan int) 20 | go run(c, a) 21 | go run(c, a) 22 | go run(c, a) 23 | go run(c, a) 24 | go run(c, a) 25 | go run(c, a) 26 | go run(c, a) 27 | go run(c, a) 28 | go run(c, a) 29 | go run(c, a) 30 | go run(c, a) 31 | go run(c, a) 32 | x, y, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10 := <-c, <-c, <-c, <-c, <-c, <-c, <-c, <-c, <-c, <-c, <-c, <-c 33 | fmt.Print(x, y, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, ) 34 | } -------------------------------------------------------------------------------- /godemo/ProducerConsumerModel/README.md: -------------------------------------------------------------------------------- 1 | ## 生产者和消费者模式 2 | 3 | ```go 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "time" 9 | ) 10 | 11 | func main() { 12 | x(c()) 13 | 14 | } 15 | 16 | 17 | func c() chan int{ 18 | ch := make(chan int) 19 | go func() { 20 | for i := 0; i < 10; i++ { 21 | ch <- i // 生产者 22 | } 23 | }() 24 | return ch 25 | } 26 | 27 | func x(c chan int){ 28 | 29 | Loop: 30 | for { //消费者。 31 | select { // 所以最好的方式就是直接使用select然后不close这样就完美了,使用了select close了,然后select中在不ok判断就会一直 32 | // 输出一个chan后面类型的零值。 如果使用range就必须close,但是你不知道万一有些不知道什么时候要close的时候呢? 33 | 34 | // 所以综上 应该使用 select然后不close。也不用再selec中判断ok。这是最好的选择 35 | case h := <-c: 36 | fmt.Println(h) 37 | case <-time.After(time.Second): 38 | break Loop 39 | 40 | } 41 | } 42 | fmt.Println("生产者消费者模式搞定") 43 | 44 | } 45 | ``` 46 | -------------------------------------------------------------------------------- /godemo/README.md: -------------------------------------------------------------------------------- 1 | # 有关 go的各种练习demo 包括了goruntine 异步并行channel等。 2 | -------------------------------------------------------------------------------- /godemo/RESTful/RESTful.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/http" 7 | 8 | "github.com/julienschmidt/httprouter" 9 | ) 10 | 11 | func number1(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { 12 | fmt.Fprint(w, "

    恭喜你来到了主页。

    ") 13 | } 14 | func number2(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { 15 | fmt.Fprintf(w, "你好尊敬的 %s 先生", ps.ByName("y")) 16 | } 17 | 18 | func main() { 19 | router := httprouter.New() 20 | router.GET("/", number1) 21 | router.GET("/index/:y", number2) 22 | log.Fatal(http.ListenAndServe(":8080", router)) 23 | } 24 | 25 | // 运算符就是简单的 & 和 * 一个取地址、一个解析地址。 26 | -------------------------------------------------------------------------------- /godemo/SortMap-map的排序.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | ) 7 | 8 | func main() { 9 | var j = 0 10 | re := make([]string, 1000) // 这里设置1000 是忘了 这个slice到底设置多少 11 | abc := map[string]string{ 12 | "cook": "可乐", 13 | "peisi": "百世可乐", 14 | "dddd": "fdsfds", 15 | "ffs2d": "fds", 16 | "iowq": "23", 17 | } 18 | for i := range abc { 19 | re[[]byte(i)[0]] = i 20 | j++ 21 | } 22 | sort.Strings(re) 23 | newRe := re[len(re)-len(abc)-1:] 24 | fmt.Println(newRe) 25 | } 26 | 27 | 28 | 29 | ####- 30 | 31 | [ cook dddd ffs2d iowq peisi] 32 | -------------------------------------------------------------------------------- /godemo/assert/assert.go: -------------------------------------------------------------------------------- 1 | package assert 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type inter interface{} 8 | 9 | type huamn struct { 10 | name string 11 | age int 12 | } 13 | 14 | type list []inter 15 | func init() { 16 | 17 | list := make(list,3) 18 | list[0] = 1 19 | list[1] = huamn{"dd", 2} 20 | list[2] = "ddfdfd" 21 | for index, element := range list { 22 | switch value := element.(type) { 23 | case int // 24 | case string// 25 | case huamn// 26 | default 27 | } 28 | } 29 | 30 | } 31 | 32 | -------------------------------------------------------------------------------- /godemo/blockchain_demo-blockworld/main.go: -------------------------------------------------------------------------------- 1 | //main.go 提供了本项目的主要入口接口。 2 | package main 3 | func main(){ 4 | fmt.println("hello this is blockworld") 5 | } 6 | -------------------------------------------------------------------------------- /godemo/channel/channel.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // 主要目的是为了测试并发的channel模块 4 | 5 | import ( 6 | "fmt" 7 | ) 8 | 9 | func sum(a []int, c chan int) { 10 | var sum int 11 | for _, value := range a { 12 | sum += value 13 | } 14 | c <- sum 15 | 16 | } 17 | 18 | func main() { 19 | a := []int{ 20 | 1, 21 | 2, 22 | 3, 23 | 4, 24 | 5, 25 | } 26 | 27 | c := make(chan int, 112) 28 | 29 | go sum(a[:len(a)/2], c) 30 | go sum(a[len(a)/2:], c) 31 | x, y := <-c, <-c 32 | fmt.Println(x, y) 33 | } 34 | -------------------------------------------------------------------------------- /godemo/crawler/crawler_test.go: -------------------------------------------------------------------------------- 1 | package crawler 2 | 3 | import "testing" 4 | 5 | func TestAll(t *testing.T) { 6 | Crawler() 7 | } 8 | -------------------------------------------------------------------------------- /godemo/doc/A6EF733E-AC56-4E33-9D2B-C3A6980007BB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/godemo/doc/A6EF733E-AC56-4E33-9D2B-C3A6980007BB.png -------------------------------------------------------------------------------- /godemo/doc/attentions.md: -------------------------------------------------------------------------------- 1 | # 这里面都是一些要特别注意的关键点。 2 | 3 | ### 使用指针 4 | 5 | 定义的时候是指针,但是当你实际上使用的时候并不需要使用`a := &nice{1, 3}`这种样式,你只需要使用 `a := nice{1, 3}` 系统会自动识别。 6 | 7 | ### 指针使用的优点: 8 | 9 | 1. 可以操作一个源文件不需要操作一个复制值 10 | 2. 快速高效 -------------------------------------------------------------------------------- /godemo/doc/golang-run.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/godemo/doc/golang-run.png -------------------------------------------------------------------------------- /godemo/doc/spec.md: -------------------------------------------------------------------------------- 1 | # 测试 2 | -------------------------------------------------------------------------------- /godemo/func/func.go: -------------------------------------------------------------------------------- 1 | package func 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func run() {//这里就类似于脚本语言了,比如js 是可以使用这种函数传递给变量的形式的。 8 | a := func() float64 { 9 | return 3.1425 10 | } 11 | fmt.Print(a()) 12 | } -------------------------------------------------------------------------------- /godemo/gin-session-cookie/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | r := gin.Default() 4 | store := cookie.NewStore([]byte("testCookie")) // 这个就是cookie的名字而已。 5 | r.Use(sessions.Sessions("mysession", store)) // 这个就是 将这个store传递给了sessions中然后再选个mysession然后就ok了。 6 | r.GET("/", func(c *gin.Context) { 7 | session := sessions.Default(c) // sessions.Default(c) 8 | var count int 9 | v := session.Get("count") 10 | if v == nil { 11 | count = 0 12 | } else { 13 | count = v.(int) 14 | count++ 15 | } 16 | session.Set("count", count) /// set count 就是在这个sessions的session的value。 17 | session.Save() 18 | c.JSON(200, gin.H{"count": count}) 19 | }) 20 | r.Run(":8000") 21 | -------------------------------------------------------------------------------- /godemo/go+mysql实现注册登陆功能/README.md: -------------------------------------------------------------------------------- 1 | CREATE TABLE `userinfo`( 2 | `uid INT(10) NOT NULL AUTO_INCERMENT`, 3 | `username` VARCHAR(64) NULL DEFAULT NULL, 4 | `password` VARCHAR(64) NULL DEFAULT NULL, 5 | PRIMARY KEY (`uid`) 6 | ) 7 | -------------------------------------------------------------------------------- /godemo/go+mysql实现注册登陆功能/data/datebase.text: -------------------------------------------------------------------------------- 1 | CREATE TABLE `userinfo` ( 2 | `uid` INT(10) NOT NULL AUTO_INCREMENT, 3 | `username` VARCHAR(64) NULL DEFAULT NULL, 4 | `password` VARCHAR(64) NULL DEFAULT NULL, 5 | PRIMARY KEY (`uid`) 6 | ); 7 | -------------------------------------------------------------------------------- /godemo/go+mysql实现注册登陆功能/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | "self/text/controller" 7 | 8 | "github.com/astaxie/beego" 9 | ) 10 | 11 | func main() { 12 | // 设置静态服务器的访问 13 | f, _ := filepath.Abs(filepath.Dir(os.Args[0])) 14 | f += "/static" 15 | beego.SetStaticPath("/static", f) 16 | //注册 17 | beego.Router("/login", &controller.MainController{}, "Get:Login") 18 | // 登陆 19 | beego.Router("/logon", &controller.MainController{}, "Get:Logon") 20 | beego.Router("/logonplus", &controller.MainController{}, "Post:Logonplus") 21 | // 注册后处理 22 | beego.Router("/deal", &controller.MainController{}, "*:Deal") 23 | beego.Run() 24 | } 25 | -------------------------------------------------------------------------------- /godemo/go+mysql实现注册登陆功能/model/helper.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "runtime" 7 | ) 8 | 9 | // Where 函数 查找错误地址的函数,标准化在ifelse中使用 10 | func Where(err interface{}) { 11 | _, file, line, _ := runtime.Caller(1) 12 | log.Printf("发生错误的文件名是%s,它的错误在这%d一行", file, line) 13 | fmt.Println("打印的错误信息是:", err) 14 | } 15 | 16 | // WherePlus 代替了if err != nil 直接在err后直接调用即可。 17 | // 没有返回值 return就省略了就行,因为函数运行完就会自动释放了。 18 | func WherePlus(err interface{}) { 19 | if err != nil { 20 | Where(err) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /godemo/go+mysql实现注册登陆功能/static/te.md: -------------------------------------------------------------------------------- 1 | fdf 2 | -------------------------------------------------------------------------------- /godemo/go+mysql实现注册登陆功能/text: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/godemo/go+mysql实现注册登陆功能/text -------------------------------------------------------------------------------- /godemo/go+mysql实现注册登陆功能/view/layout.html: -------------------------------------------------------------------------------- 1 | {{define "layout"}} 2 | 3 | 4 | 5 | 6 | this is the test coding|login & logon 7 | 8 | 9 | {{template "container"}} 10 | 11 | 12 | {{end}} 13 | -------------------------------------------------------------------------------- /godemo/go+mysql实现注册登陆功能/view/login.html: -------------------------------------------------------------------------------- 1 | {{define "container"}} 2 |
    3 | 请输入您的名字 4 | 请输入你的密码 5 | 6 |
    7 | {{end}} 8 | -------------------------------------------------------------------------------- /godemo/go+mysql实现注册登陆功能/view/logon.html: -------------------------------------------------------------------------------- 1 | {{define "container"}} 2 |

    这是显示的结果:

    3 |

    这是返回的结果:

    4 |
    5 | 6 | 7 | 8 |
    9 | 10 | 11 | 12 | {{end}} 13 | -------------------------------------------------------------------------------- /godemo/go_testing_examples/reverse.go: -------------------------------------------------------------------------------- 1 | package reverse 2 | 3 | func Reverse(s string) string { 4 | runes := []rune(s) 5 | n, h := len(runes), len(runes)/2 6 | for i := 0; i < h; i++ { 7 | runes[i], runes[n-1-i] = runes[n-1-i], runes[i] 8 | } 9 | return string(runes) 10 | } 11 | 12 | 13 | -------------------------------------------------------------------------------- /godemo/go_testing_examples/reverse_test.go: -------------------------------------------------------------------------------- 1 | package reverse 2 | 3 | import "testing" 4 | 5 | type between struct { 6 | in string 7 | out string 8 | } 9 | 10 | 11 | func TestReverse(t *testing.T) { 12 | 13 | c := []*between{ 14 | &between{ 15 | "bta", 16 | "atb", 17 | }, 18 | &between{ 19 | "ttyu", 20 | "uytd", 21 | }, 22 | } 23 | 24 | for k,v := range c { 25 | s := Reverse(v.in) 26 | if s != v.out { 27 | t.Log("这个选项测试错误:,错误值是:,期望值是:",k,s,v.out) 28 | t.Fail() 29 | } 30 | } 31 | } 32 | 33 | func BenchmarkReverse(b *testing.B) { 34 | for i := 0; i < b.N; i ++ { 35 | Reverse("bta") 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /godemo/goruntime/goruntime.go: -------------------------------------------------------------------------------- 1 | package goruntime 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func say(s string) { 9 | for i := 0; i < 5; i++ { 10 | time.Sleep(100 * time.Microsecond) 11 | fmt.Println(s) 12 | } 13 | } 14 | 15 | func init() { 16 | go say("world") 17 | say("hello") 18 | } 19 | -------------------------------------------------------------------------------- /godemo/go对象(struct结构体)总结.go: -------------------------------------------------------------------------------- 1 | //struct 结构体总结: 2 | //这种对象的方式,在go中是独一无二的,因为在对象中的指针对象无序* 就可以去得到真实值, 3 | //这是仅在struct中可以实现的功能,所以在struct(对象)中尽管定义指针类型,压根不用考虑* 就可以去得到值 4 | //map就不行。 5 | 6 | package main 7 | 8 | import "fmt" 9 | 10 | type aty struct { 11 | b *b 12 | } 13 | type b struct { 14 | str string 15 | } 16 | 17 | func main() { 18 | ttt := "d" 19 | a := map[string]*string{ 20 | "d": &ttt, 21 | } 22 | fmt.Println(*a["d"])//d 23 | fmt.Println(a["d"])//0xc0000601c0 24 | 25 | //------ 但是使用对象就没问题 26 | 27 | ttttt := &aty{// 即便这里是 &aty,下面取值的时候直接 ttttt 即可 无需使用 (*tttt) 用也可以,因为 这就是对象的语法糖的实质。 28 | &b{ 29 | "12", 30 | }, 31 | } 32 | fmt.Println(ttttt.b.str)//12 这里没有用 *(tttt.b)就直接可以取得 str 33 | 34 | 35 | } 36 | -------------------------------------------------------------------------------- /godemo/hashsha1等hash加密方式的基本加密方式.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/md5" 5 | "fmt" 6 | ) 7 | 8 | func main() { 9 | hash := md5.New() //返回的是一个已经实现过接口的了的struct,所以才可以直接使用。 10 | b := []byte{} 11 | n, err := hash.Write([]byte("666")) 12 | if n != 3 || err != nil { 13 | fmt.Println(err) 14 | } 15 | value := hash.Sum(b) 16 | hashString := fmt.Sprintf("%x\n", value) 17 | fmt.Println("输出的结果是:", hashString) 18 | 19 | } 20 | -------------------------------------------------------------------------------- /godemo/hideInterface/hideInterface.go: -------------------------------------------------------------------------------- 1 | package hideInterface 2 | 3 | import "fmt" 4 | 5 | type Student interface { 6 | method() string 7 | } 8 | 9 | type name struct { 10 | name string 11 | age int 12 | } 13 | 14 | func (n name) method() string { 15 | return "zer" 16 | } 17 | 18 | func run(s Student) { 19 | fmt.Println(s.method()) 20 | } 21 | 22 | func main() { 23 | var a name 24 | a.name = "aa" 25 | a.age = 12 26 | 27 | run(a) 28 | } 29 | -------------------------------------------------------------------------------- /godemo/httpServer/httpServer.go: -------------------------------------------------------------------------------- 1 | package httpServer 2 | 3 | 4 | 5 | import ( 6 | "io" 7 | "net/http" 8 | ) 9 | 10 | func run(h http.ResponseWriter, v *http.Request) { 11 | io.WriteString(h, "dfdfd") 12 | } 13 | 14 | func init() { 15 | http.HandleFunc("/", run) 16 | http.ListenAndServe(":4000",nil) 17 | } 18 | 19 | -------------------------------------------------------------------------------- /godemo/inheritMethod/inhertMethod.go: -------------------------------------------------------------------------------- 1 | //method的继承案例 2 | package inheritMethod 3 | 4 | import ( 5 | "fmt" 6 | 7 | ) 8 | 9 | type human struct { 10 | height int 11 | name string 12 | age int 13 | } 14 | 15 | type students struct { 16 | human 17 | class int 18 | teacherName string 19 | } 20 | 21 | type teacher struct { 22 | human 23 | class int 24 | studentName string 25 | } 26 | 27 | func (h *human) sayHi(value string) bool {//这里使用的是指针。 28 | fmt.Print("这个人的名字是%s,今年是%c岁了,职业是%s", h.name, h.age, value) 29 | return true 30 | } 31 | 32 | func init() { 33 | xiaoming := students{human{110, "xm", 12}, 1, "王娟"} 34 | wangjuan := teacher{human{170, "wj", 27}, 1, "xiaoming"} 35 | xiaoming.sayHi("学生") 36 | //这里就是集成,因为xiaoming和wangjuan并没有sayhi这个method却可以引用,原因就是因为,human属于 37 | // teacher 和 stuents 所以后两者就可以集成包含在huan中的方法。 38 | wangjuan.sayHi("老师") 39 | } 40 | 41 | -------------------------------------------------------------------------------- /godemo/init的执行顺序.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | var t int 6 | 7 | func main() { 8 | d() 9 | fmt.Println("谁先开始main") 10 | } 11 | func init() { // 在这个函数里预先经很多函数先预执行很不错的选择。 12 | t = 12 13 | fmt.Println("谁先开始:init") 14 | } 15 | 16 | func d() { 17 | fmt.Println(t) 18 | } 19 | 20 | ### 21 | 22 | 谁先开始:init 23 | 12 24 | 谁先开始main 25 | -------------------------------------------------------------------------------- /godemo/interfaceS/interface: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/godemo/interfaceS/interface -------------------------------------------------------------------------------- /godemo/interfaceS/interface.md: -------------------------------------------------------------------------------- 1 | # 提示 2 | 3 | 最后,任意的类型都实现了空interface(我们这样定义:interface{}),也就是包含0个method的interface。 4 | 5 | 一个函数把interface{}作为参数,那么他可以接受任意类型的值作为参数,如果一个函数返回interface{},那么也就可以返回任意类型的值 6 | 7 | Go 语言中的接口都很简短,通常它们会包含 0 个、最多 3 个方法] 8 | 9 | http://localhost:4000 10 | -------------------------------------------------------------------------------- /godemo/interfaceS/interface2.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // 本页面是为了测试 6 | 7 | type Student struct { 8 | name string 9 | } 10 | 11 | type Teacher struct { 12 | name string 13 | } 14 | 15 | func (s Student) method() string { 16 | return s.name 17 | } 18 | 19 | func (t Teacher) method() string { 20 | return t.name 21 | } 22 | 23 | type me interface { 24 | method() string 25 | } 26 | 27 | func run(m me) { 28 | 29 | fmt.Printf(me.method()) 30 | } 31 | 32 | func main() { 33 | var a []me 34 | 35 | a[0] = Student{"student"} 36 | a[1] = Teacher{"teacher"} 37 | 38 | run(a[0]) 39 | run(a[1]) 40 | 41 | } 42 | -------------------------------------------------------------------------------- /godemo/localStorge_demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | test 6 | 7 | 8 |
    9 | 10 |
    11 | 12 | 13 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /godemo/main/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func run(a []int, b chan int) { 6 | total := 0 7 | for _, value := range a { 8 | total += value 9 | } 10 | b <- total 11 | } 12 | 13 | func big() { 14 | c := make(chan int, 3) 15 | c <- 1 16 | c <- 2 17 | c <- 3 18 | fmt.Println(<-c) 19 | fmt.Println(<-c) 20 | fmt.Println(<-c) 21 | } 22 | func main() { 23 | big() 24 | b := make(chan int) 25 | a := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} 26 | go run(a[:len(a)/2], b) 27 | go run(a[len(a)/2:], b) 28 | go run(a[:len(a)/2], b) 29 | go run(a[len(a)/2:], b) 30 | go run(a[:len(a)/2], b) 31 | go run(a[len(a)/2:], b) 32 | 33 | x, y, a1, b1, c, d := <-b, <-b, <-b, <-b, <-b, <-b 34 | fmt.Print(x, y, a1, b1, c, d) 35 | } 36 | -------------------------------------------------------------------------------- /godemo/maopao/index.go: -------------------------------------------------------------------------------- 1 | package maopao 2 | // 冒泡排序并输出结果。 3 | func numb(a []int64){ 4 | for i := 0; i < len(a) -1; i ++ { 5 | c := false 6 | for j := 0; j < len(a)-1-i;j ++ { 7 | if a[j] >= a [j+1] { 8 | a[j+1],a[j] = a[j],a[j+1] 9 | c = true 10 | } 11 | } 12 | if !c { /// 证明某次冒泡,全员不需要冒泡了,那么就证明已经排序OK了,就可以退出了。 13 | break 14 | } 15 | } 16 | for _,value := range a { 17 | fmt.Println(value) 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /godemo/map/map.go: -------------------------------------------------------------------------------- 1 | //测试 2 | package map 3 | 4 | import "fmt" 5 | 6 | type huam struct { 7 | name string 8 | age int 9 | } 10 | 11 | var number1 map[string]huam 12 | func init() { 13 | number1["dfdfd"] = huam{ 14 | "dfd" 15 | 12 16 | } 17 | fmt.Print(number1["dfdfd"]) 18 | } 19 | 20 | -------------------------------------------------------------------------------- /godemo/map/map2.go: -------------------------------------------------------------------------------- 1 | package map 2 | 3 | import ( 4 | "fmt" 5 | 6 | ) 7 | type huamn struct { 8 | huamn int 9 | age string 10 | } 11 | 12 | func init() { 13 | var a = map[string]huamn{//这里出现的human意思是整个这个map是 huamn的集合。 14 | "humber1": huamn{//这里的huamn是可以省略的。 15 | huamn:1, age:"hujiaqi" 16 | }, 17 | "numer2": huamn{ 18 | 2, "fdffd" 19 | }, 20 | }//这里是直接定义并且赋值值的那种方式,所以a不是nil这种方式是允许的。 21 | // 这里的huamn 22 | 23 | 省略版本 24 | 25 | var a = map[string]huamn{//这里出现的human意思是整个这个map是 huamn的集合。 26 | "humber1": {//这里的huamn是可以省略的。 27 | 1, "hujiaqi"//这里面才是真正要表达的 struct中的东西,其实这个map js中也有 28 | }, 29 | "numer2": { 30 | 2, "fdffd" 31 | }, 32 | } 33 | 34 | a["humber1"] //这样调用就好。 35 | } 36 | 37 | // 调用 38 | 39 | -------------------------------------------------------------------------------- /godemo/method/method.go: -------------------------------------------------------------------------------- 1 | package method 2 | //type相当于构建了一个模型,到调用函数的时候需要初始化 3 | //引入包 4 | import "fmt" 5 | 6 | //制定常量 7 | 8 | const ( 9 | PI = 3.1415926 10 | ) 11 | 12 | type Human struct { 13 | name string 14 | age int 15 | phoneNumber float64 16 | 17 | } 18 | func (hu Human) run(value int) (int, float64) { 19 | return value + hu.age, PI 20 | } 21 | 22 | func (hu *Human) Run(value int) string{ 23 | return "nice" 24 | } 25 | 26 | 27 | func init() { 28 | hu := Human{"dd", 17, 554.333} 29 | //不初始化是没有值的 30 | a:= hu.Run(12)//这里虽然并没有使用&hu但是系统会自动取& 31 | fmt.Print(a) 32 | } 33 | -------------------------------------------------------------------------------- /godemo/newTon/newTon.go: -------------------------------------------------------------------------------- 1 | //使用牛顿法求去平方根 2 | package newTon 3 | import ( 4 | "fmt" 5 | ) 6 | func newTown(x float64) float64 { 7 | x1 := x /2 8 | var c = 1.0 9 | 10 | for { 11 | 12 | c = ( x1 + x / x1 ) / 2 13 | if x1 - c <= 0.00001 { 14 | return c 15 | } 16 | x1 = c 17 | } 18 | 19 | } 20 | func init() { 21 | fmt.Print(newTown(12.3)) 22 | } -------------------------------------------------------------------------------- /godemo/pointer/pointer.go: -------------------------------------------------------------------------------- 1 | package pointer 2 | 3 | type huamn struct { 4 | huamn int 5 | age int 6 | } 7 | func run() { 8 | //就说明了,通过直接操作指针,可以直接操作变量指向的那唯一的内容 9 | a := huamn{12, 2} 10 | p := &a 11 | //当然你也可以直接使用: 12 | b := &huamn{12,34} 13 | //效果是一样的。 14 | p.huamn = 2222 15 | fmt.Print(a) 16 | } 17 | 18 | 19 | func run1() { 20 | //在a传递给p时候,传递是值,已经是另一个东西了,所以当p改变后 a病没有什么变化 21 | a := huamn{12, 2} 22 | p := a 23 | p.huamn = 2222 24 | fmt.Print(a) 25 | } 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /godemo/queue-队列.md: -------------------------------------------------------------------------------- 1 | ## 使用go实现队列 2 | ```go 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "sync" 8 | ) 9 | 10 | type A struct { 11 | lock sync.Mutex 12 | value []interface{} 13 | } 14 | 15 | func NewA(length int) *A { 16 | return &A{ 17 | value: make([]interface{}, length), 18 | } 19 | } 20 | func (a *A) Get(key int) interface{} { 21 | a.lock.Lock() 22 | defer a.lock.Unlock() 23 | return a.value[key] 24 | } 25 | 26 | func (a *A) Set(key int, value interface{}) { 27 | a.lock.Lock() 28 | a.value[key] = value 29 | defer a.lock.Unlock() 30 | 31 | } 32 | 33 | func (a *A) Delete(key int) { 34 | a.lock.Lock() 35 | a.value = append(a.value[:key], a.value[key:]...) 36 | defer a.lock.Unlock() 37 | } 38 | 39 | 40 | func main(){ 41 | t := NewA(12) 42 | t.Set(1,"12") 43 | fmt.Println(t.Get(1)) 44 | } 45 | ``` 46 | -------------------------------------------------------------------------------- /godemo/queue/1.1.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | ) 7 | 8 | func main() { 9 | t := NewThing() 10 | t.In("12") 11 | t.In("13") 12 | t.In("14") 13 | t.In("15") 14 | t.Out() 15 | fmt.Println(t.value) 16 | } 17 | 18 | type thing struct { 19 | lock sync.Mutex 20 | value []interface{} 21 | } 22 | 23 | func NewThing() *thing { 24 | return &thing{ 25 | value:make([]interface{}, 0), 26 | } 27 | } 28 | 29 | func (t *thing) In(v interface{}) { 30 | t.lock.Lock() 31 | defer t.lock.Unlock() 32 | t.value = append(t.value, v) 33 | } 34 | 35 | func (t *thing) Out() interface{} { 36 | t.lock.Lock() 37 | defer t.lock.Unlock() 38 | t.value = t.value[1:] 39 | return t.value[0] 40 | } 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /godemo/queue/1.2.go: -------------------------------------------------------------------------------- 1 | package main 2 | -------------------------------------------------------------------------------- /godemo/queue/1.go: -------------------------------------------------------------------------------- 1 | // 顺序队列 2 | 3 | package main 4 | 5 | import "fmt" 6 | 7 | func main() { 8 | t := NewThing() 9 | t.In("12") 10 | t.In("13") 11 | t.In("14") 12 | t.In("15") 13 | t.Out() 14 | fmt.Println(t.value) 15 | } 16 | 17 | type thing struct { 18 | value []interface{} 19 | } 20 | 21 | func NewThing() *thing { 22 | return &thing{ 23 | make([]interface{}, 0), 24 | } 25 | } 26 | 27 | func (t *thing) In(v interface{}) { 28 | t.value = append(t.value, v) 29 | } 30 | 31 | func (t *thing) Out() interface{} { 32 | t.value = t.value[1:] 33 | return t.value[0] 34 | } 35 | 36 | // 如何实现线程安全。 37 | 38 | //开始迭代 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /godemo/queue/2.2.go: -------------------------------------------------------------------------------- 1 | package main 2 | -------------------------------------------------------------------------------- /godemo/queue/3.2.go: -------------------------------------------------------------------------------- 1 | package main 2 | -------------------------------------------------------------------------------- /godemo/rang/rang.go: -------------------------------------------------------------------------------- 1 | // range 这个全局的函数的意义就是对于slice和map进行迭代。就类似于 js中的for(let i of a ){ 2 | 3 | //} 4 | package rang 5 | 6 | import ( 7 | "fmt" 8 | ) 9 | 10 | func run() { 11 | var a []int 12 | b := append(a, 1, 2, 3, 4, 5) 13 | for i, v := range b { 14 | fmt.Print(i, v)//i 就是key v 就是value 15 | } 16 | } -------------------------------------------------------------------------------- /godemo/readFileFromLocation从本地读取文件并输出.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "io" 7 | "os" 8 | ) 9 | 10 | func main() { 11 | file, err := os.Open("hello.go") //将读取的open传入newReader的读取流 12 | if err != nil { 13 | fmt.Println(err) 14 | } 15 | defer file.Close() 16 | reader := bufio.NewReader(file) 17 | for { 18 | inputString, readerError := reader.ReadString('\n') 19 | fmt.Printf("The input was: %s", inputString)// 20 | if readerError == io.EOF { 21 | return 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /godemo/recover-panic-String的使用方式.go: -------------------------------------------------------------------------------- 1 | //1)在包内部,总是应该从 panic 中 recover:不允许显式的超出包范围的 panic() 2 | //2)向包的调用者返回错误值(而不是 panic)。 3 | 4 | // recover panic String的一个练习 5 | package main 6 | 7 | import ( 8 | "errors" 9 | "fmt" 10 | ) 11 | 12 | type ParseError struct { 13 | Index int 14 | Word string 15 | Err error 16 | } 17 | 18 | func (p *ParseError) String() string { 19 | return fmt.Sprintf("包的错误是:%q", p.Word) 20 | } 21 | func Parse() (errValue error) {//"向包的调用者返回错误值(而不是 panic)。" 返回的是err而不是直接panic. 22 | defer func() { 23 | if err := recover(); err != nil { 24 | errValue = fmt.Errorf("返回的是:%v", err) 25 | } 26 | }() 27 | therFunc() 28 | return 29 | } 30 | func OtherFunc() error { 31 | panic(&ParseError{12, "222", errors.New("ceshi")}) 32 | 33 | } 34 | func main() { 35 | fmt.Println(Parse()) 36 | } 37 | 38 | //返回的是:包的错误是:"222" 这个是返回值。 39 | -------------------------------------------------------------------------------- /godemo/recover恢复机制的使用条件.go: -------------------------------------------------------------------------------- 1 | //说明一下,recover只能在defer中使用也就是defer然后来一个匿名函数,这样在里层栈中的panic在dd中发现了这个panic然后再defer中恢复即可。 2 | //恢复了以后tt就可以继续进行了 3 | package main 4 | 5 | import "fmt" 6 | 7 | func main() { 8 | dd(tt) 9 | fmt.Println("可以继续使用吗main")//恢复了以后这个逻辑就可以执行了。 10 | } 11 | 12 | func tt() { 13 | panic("测试")//只要有panic这个函数不论是否recover这个函数后面的东西都不会执行了。这个函数就废了。 14 | fmt.Println("可以继续使用吗tt") 15 | } 16 | 17 | func dd(f func()) { 18 | defer func() { 19 | if err := recover(); err != nil { 20 | fmt.Println("恢复机制开始:", err) 21 | } 22 | }() 23 | f() 24 | fmt.Println("保护机制开始") 25 | } 26 | 27 | //## 28 | //恢复机制开始: 测试 29 | //可以继续使用吗main 30 | 31 | // 事实证明:恢复是"可以的不过不能讲那个panic的函数恢复了,恢复的是忽略这个函数然后继续执行后面的逻辑"这个意思 32 | 33 | //也就是说在哪一层恢复就哪一级别的逻辑可以继续执行,底层的逻辑这个recover管不了不然 那个 fmt.Println("可以继续使用吗tt")就可以执行了,事实上不能执行 34 | //也就是验证了我说的。“哪一层恢复就哪一级别的逻辑可以继续执行,底层的逻辑这个recover管不了” 35 | -------------------------------------------------------------------------------- /godemo/rpc_gob_micro/gob.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "encoding/gob" 6 | "fmt" 7 | ) 8 | 9 | var ( 10 | a = []int{ 11 | 1,2,3,4, 12 | } 13 | 14 | ) 15 | 16 | type tt struct { 17 | 18 | Td *string 19 | } 20 | func main(){ 21 | aa := make([]int,0) 22 | yy := tt{} 23 | b := bytes.Buffer{} 24 | enc := gob.NewEncoder(&b) 25 | dec := gob.NewDecoder(&b) 26 | enc.Encode(a) 27 | uio := "1222" 28 | enc.Encode(&tt{&uio}) 29 | dec.Decode(&aa) 30 | dec.Decode(&yy) 31 | fmt.Println(aa) 32 | fmt.Println(*yy.Td) 33 | } 34 | 35 | -------------------------------------------------------------------------------- /godemo/rpc_gob_micro/rpc.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/rpc" 4 | 5 | func tt(){ 6 | rpc.Client{}.Call() 7 | } 8 | -------------------------------------------------------------------------------- /godemo/salt/salt_test.go: -------------------------------------------------------------------------------- 1 | package salt 2 | 3 | import ( 4 | "github.com/googege/goo" 5 | "testing" 6 | ) 7 | 8 | 9 | func TestSalt(t *testing.T) { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /godemo/select/select.go: -------------------------------------------------------------------------------- 1 | package selectt 2 | 3 | // select 的测试 4 | 5 | import ( 6 | "fmt" 7 | ) 8 | 9 | func run(c, a chan int) { 10 | x, y := 0, 1 11 | for { 12 | select { 13 | case c <- x: 14 | x, y = y, x+y 15 | case <-a: 16 | fmt.Println("quit") 17 | return 18 | } 19 | } 20 | } 21 | 22 | func main() { 23 | c := make(chan int) 24 | a := make(chan int) 25 | go func() { 26 | for i := 0; i < 10; i++ { 27 | fmt.Println(<-c) 28 | } 29 | a <- 0 30 | }() 31 | run(c, a) 32 | } 33 | -------------------------------------------------------------------------------- /godemo/select和done提醒者模式的结合.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | ) 7 | 8 | func tel(ch chan int, done chan bool) { 9 | for i := 0; i < 15; i++ { 10 | ch <- i 11 | } 12 | done <- true// 当ch已经传递完成了就开启done。 13 | } 14 | 15 | func main() { 16 | var ok = true 17 | ch := make(chan int) 18 | done := make(chan bool) 19 | go tel(ch, done) 20 | for ok { 21 | select {// 接受两个线程,当接收到done的时候直接退出。 22 | case v := <-ch: 23 | fmt.Println(v) 24 | case <-done: 25 | os.Exit(0) 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /godemo/slice/moreSlice.go: -------------------------------------------------------------------------------- 1 | package slice 2 | 3 | import "fmt" 4 | 5 | func run() { 6 | a := []int{1, 2, 3, 4} 7 | a1 := a[1:3]//表示从2到3的数字 8 | a2 := append(a, 1, 2, 3, 3)//这里说的就是说我们将 1233 传入给a的复制品然后返回一个新的切片。 9 | fmt.Print(a2, a1) 10 | 11 | } -------------------------------------------------------------------------------- /godemo/strings/srings.go: -------------------------------------------------------------------------------- 1 | // 目的是为了测试系统定义的String这个接口,因为是系统定义的,所以并不需要制定出来,系统会在使用fmt.printf时候自动调用string这个 2 | //方法。 3 | 4 | package strings 5 | 6 | import ( 7 | "fmt" 8 | ) 9 | 10 | type name struct { 11 | name string 12 | age int 13 | } 14 | 15 | func (p name) String() string { 16 | return fmt.Sprintf("%v (%v years)", p.name, p.age) 17 | } 18 | 19 | func init() { 20 | a := name{"dd", 12} 21 | b := name{"ddddd", 34} 22 | fmt.Print(a, b) 23 | } 24 | -------------------------------------------------------------------------------- /godemo/struct/orgin.go: -------------------------------------------------------------------------------- 1 | package struct 2 | 3 | 4 | 5 | import ( 6 | "fmt" 7 | ) 8 | 9 | 10 | type humans struct { 11 | name string 12 | age int 13 | } 14 | 15 | func init() { 16 | fmt.Print(humans{"MR", 12}) 17 | } -------------------------------------------------------------------------------- /godemo/struct/struct.go: -------------------------------------------------------------------------------- 1 | // struc的解释example 2 | package struct 3 | 4 | import "fmt" 5 | 6 | type person struct { 7 | name string 8 | age int 9 | } 10 | func run(value person, value2 int) (int, int){ 11 | if value.age > value2 { 12 | return value.age, value2 13 | } 14 | return "错误的","决定" 15 | } 16 | func init() { 17 | bob := person{"hujiaqi", 12} 18 | var bob1 person 19 | bob1.string = "ddd" 20 | bob1.age = 123 21 | mary := person{age:1234, name:"thomas"} 22 | date1, date2 := run(bob, 22) 23 | date3,date4 := run(bob1, 23) 24 | date5, date6 := run(mary, 233) 25 | fmt.Print("内容是 %d", date1) 26 | fmt.Print("内容是 %d", date2) 27 | fmt.Print("内容是 %d", date3) 28 | fmt.Print("内容是 %d", date4) 29 | fmt.Print("内容是 %d", date5) 30 | fmt.Print("内容是 %d", date6) 31 | } 32 | -------------------------------------------------------------------------------- /godemo/struct/structPluss.go: -------------------------------------------------------------------------------- 1 | // struct deep example 2 | //中文: 此案例详细讲些了关于struct的具体用法。 3 | package struct 4 | 5 | import ( 6 | "fmt" 7 | ) 8 | type skills []string// another type 9 | type humme struct {//struct 10 | name string 11 | age int 12 | number int 13 | } 14 | type all struct {//all 15 | humme 16 | skills 17 | number int 18 | } 19 | func run1 (){ 20 | dd := all{humme{name:"hu", age:12, number:229292},number:1222} 21 | dd.skills = []string{"dddageto"} 22 | dd.skills = append(dd.stills, "dd", 12, "fewfef") 23 | fmt.Println("内容就是:", dd.name, dd.age, dd.number, dd.humme.number,dd.skills) 24 | } 25 | -------------------------------------------------------------------------------- /godemo/switchNil/switchNil.go: -------------------------------------------------------------------------------- 1 | //主要是为了测试 switch {} 2 | package switchNil 3 | 4 | import "fmt" 5 | 6 | func run () { 7 | 8 | switch {//当我们使用空switch时候,我们的意思就要说 switch a(a是boolean类型)然后有三个选项 9 | // true false 或者是 其实类型的东西,也就是等于 switch true {} 10 | case 1 > 0: 11 | fmt.Print("您输出的数据是100") 12 | case 1 > 10: 13 | fmt.Print("您输出的数据是20") 14 | default: 15 | fmt.Print("enen") 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /godemo/sync.Pool/README.md: -------------------------------------------------------------------------------- 1 | ## Sync.Pool 's demo 2 | 3 | ```go 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "sync" 9 | "time" 10 | ) 11 | 12 | // 一个[]byte的对象池,每个对象为一个[]byte 13 | var bytePool = sync.Pool{ 14 | New: func() interface{} { 15 | b := make([]byte, 1024) 16 | return &b 17 | }, 18 | } 19 | 20 | func main() { 21 | a := time.Now().Unix() 22 | // 不使用对象池 23 | var obj []byte 24 | for i := 0; i < 100000000; i++ { 25 | obj = make([]byte, 1024) 26 | } 27 | fmt.Println(obj) 28 | b := time.Now().Unix() 29 | // 使用对象池 30 | for i := 0; i < 100000000; i++ { 31 | obj := bytePool.Get().(*[]byte) 32 | _ = obj 33 | bytePool.Put(obj) 34 | } 35 | fmt.Println(obj) 36 | c := time.Now().Unix() 37 | fmt.Println("without pool ", b-a, "s") 38 | fmt.Println("with pool ", c-b, "s") 39 | } 40 | 41 | ``` 42 | -------------------------------------------------------------------------------- /godemo/time/time.go: -------------------------------------------------------------------------------- 1 | //本包主要是为了switch和time的官方包的示例 2 | package time 3 | 4 | import ( 5 | "time" 6 | "fmt" 7 | ) 8 | 9 | func showTime() { 10 | ti := time.Now().Weekday() 11 | switch time.Now() 12 | case ti : 13 | fmt.Println("周六") 14 | case ti + 1 : 15 | fmt.Println("周日") 16 | case ti + 2 : 17 | fmt.Println("周一") 18 | case ti + 3 : 19 | fmt.Println("周二") 20 | case ti + 4 : 21 | fmt.Println("周三") 22 | case ti + 5 : 23 | fmt.Println("周四") 24 | case ti + 6 : 25 | fmt.Println("周五") 26 | } -------------------------------------------------------------------------------- /godemo/time包中的tick和After函数的运用.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "time" 7 | ) 8 | 9 | func main() { 10 | stop := time.After(1e9)// 它只能运行一次所以当它出现的时候可以设置为只要他出现就停止的这种选项 11 | tick := time.Tick(1e8)// 可以出现很多次而且是每隔设置的时间就出现一次。可以设置为报时器。 12 | for { 13 | select { 14 | case <-tick: 15 | fmt.Println(".") 16 | case <-stop: 17 | fmt.Println("boom") 18 | os.Exit(0) 19 | default: 20 | fmt.Println(".") 21 | time.Sleep(3e8) 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /godemo/tour_go_stringer_example.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type IPAddr [4]byte //array 6 | 7 | // TODO: Add a "String() string" method to IPAddr. 8 | 9 | func (i *IPAddr) String() string { 10 | var result string = "" 11 | for k, _ := range *i { 12 | str := fmt.Sprint(i[k]) 13 | if k < len(i)-1 { 14 | result = result + str + "." 15 | } else { 16 | result = result + str 17 | } 18 | 19 | } 20 | return result 21 | } 22 | 23 | func main() { 24 | hosts := map[string]*IPAddr{ 25 | "loopback": {127, 0, 0, 1}, 26 | "googleDNS": {8, 8, 8, 8}, 27 | } 28 | for name, ip := range hosts { 29 | fmt.Printf("%v: %v\n", name, ip) 30 | } 31 | } 32 | // 就是将String() string 重写即可。 33 | -------------------------------------------------------------------------------- /godemo/twoGive/twoGive.go: -------------------------------------------------------------------------------- 1 | package twoGive 2 | 3 | import "fmt" 4 | 5 | func run() { 6 | 7 | a := make(map[string]int) 8 | a["hujiaqi"] = 1 9 | a["huhuihui"] = 2 10 | // b := a["hujiaqi"] 11 | // delete(a, "hujiaqi") 12 | _, ok := a["hujiaqi"]//判断是否有这个值,ok是true就是有,否则就是false就是没有并且value为零值也就是nil 13 | fmt.Print(ok) 14 | } -------------------------------------------------------------------------------- /godemo/typeFuc/typeFuc.go: -------------------------------------------------------------------------------- 1 | // 测试 函数类型,这种写法就类似编译语言例如js了,不过,稍微复杂一点点 2 | package typeFuc 3 | 4 | import ( 5 | "fmt" 6 | ) 7 | func runGoing(number1 exampleType, number2 exampleType){ 8 | if number1(110) && number2(999) { 9 | fmt.Print("t!") 10 | } else { 11 | fmt.Print("bad)") 12 | } 13 | } 14 | type exampleType func (int) bool 15 | func over(value int) bool { 16 | // 判断是否大于100的函数 17 | if value > 100 { 18 | return true 19 | } 20 | return false 21 | } 22 | func less(value int) bool { 23 | //判断是否小于 1000 的函数 24 | if value < 1000 { 25 | return true 26 | } 27 | return false 28 | } 29 | func init() { 30 | runGoing(over, less) 31 | } -------------------------------------------------------------------------------- /godemo/web-test/web: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/godemo/web-test/web -------------------------------------------------------------------------------- /godemo/web-test/web.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/http" 7 | "strings" 8 | ) 9 | 10 | func helloName(w http.ResponseWriter, r *http.Request) { 11 | r.ParseForm() 12 | fmt.Println(r.Form) 13 | fmt.Println(r.URL.Path) 14 | fmt.Println(r.URL.Scheme) 15 | fmt.Println(r.Form["url_long"]) 16 | for k, v := range r.Form { 17 | fmt.Println("key:", k) 18 | fmt.Println("val:", strings.Join(v, "")) 19 | } 20 | fmt.Fprintln(w, "

    中华人民共和国是最厉害的国家!

    ") 21 | } 22 | 23 | func main() { 24 | http.HandleFunc("/", helloName) 25 | err := http.ListenAndServe(":9090", nil) 26 | if err != nil { 27 | log.Fatal(err) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /godemo/web/web.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/http" 7 | ) 8 | 9 | type Hello struct{} 10 | 11 | func (h Hello) ServeHTTP(w http.ResponseWriter, r *http.Request) { 12 | fmt.Fprint(w, "hello world") 13 | } 14 | 15 | func main() { 16 | var h Hello 17 | err := http.ListenAndServe("localhost:4000", h) 18 | if err != nil { 19 | log.Fatal(err) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /godemo/一种接口变量不是空但是传入的类型却是空的一个不太容易感觉到的小技巧或者很容易出错的地方.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io" 7 | ) 8 | 9 | const debug = false 10 | 11 | func main() { 12 | var buf *bytes.Buffer 13 | if debug { 14 | buf = new(bytes.Buffer) // enable collection of output 15 | } 16 | fmt.Println(buf == nil) 17 | f(buf) // NOTE: subtly incorrect! 18 | fmt.Println(buf.String()) 19 | if debug { 20 | // ...use buf... 21 | } 22 | } 23 | 24 | // If out is non-nil, output will be written to it. 25 | func f(out io.Writer) { 26 | // ...do something... 27 | if out != nil { 28 | out.Write([]byte("done!\n")) 29 | } 30 | } 31 | // 当 debug 是false的时候,那么 buf就是一个 以buffer类型的一个nil值,但是它赋予了io.Writer,并且buffer类型实现了io.Writer 32 | // 所以是可以实现继承的,但是它的值却是一个nil,但是与此同时 这个out变量的值可不是nil 它是一个 有着类型但是指向是nil的一个非nil使用的时候肯定是会 33 | //报bug的。 34 | -------------------------------------------------------------------------------- /godemo/互斥锁的简单应用.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "sync" 4 | 5 | func main() { 6 | title(map[string]string{ 7 | "1": "1", 8 | }) 9 | 10 | } 11 | 12 | var lock sync.Mutex 13 | 14 | func title(k map[string]string) map[string]string { 15 | lock.Lock() 16 | defer lock.Unlock() 17 | return k 18 | } 19 | 20 | // 说明几点:1,互斥锁可以在不同的线程中打开和关闭,例如在a线程中打开在b线程中关闭,这是可以的。2,普通的map在多线程中是有访问冲突的,需要使用互斥锁, 21 | //或者你可以使用sync.map这个是sync包实现的map估计实现原理就跟一般的map加锁差不多。3有关互斥锁,file html访问这种情境下一般而言都要使用defer,这样 22 | //结构更清晰也更好用。 23 | -------------------------------------------------------------------------------- /godemo/使用go获取跟curl简单功能相同的功能.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "io" 7 | "net/http" 8 | "os" 9 | "strings" 10 | ) 11 | 12 | func main() { 13 | file, err := os.Create("./tt.io") 14 | if err != nil { 15 | fmt.Println(err) 16 | } 17 | err = os.Rename("./tt.io", "./tt.ploop") 18 | if err != nil { 19 | fmt.Println("在改名的时候发生了错误:", err) 20 | } 21 | writer := bufio.NewWriter(file) 22 | for _, url := range os.Args[1:] { 23 | if url == "" { 24 | fmt.Println("您尚未输入任何路径,请重试") 25 | os.Exit(1) 26 | } 27 | if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") { 28 | url = "http://" + url 29 | } 30 | resp, err := http.Get(url) 31 | if err != nil { 32 | fmt.Println("获取url发生了错误,错误代码是:", err) 33 | } 34 | fmt.Println("打印url:", url) 35 | fmt.Println("打印状态码:", resp.StatusCode) 36 | _, err = io.Copy(writer, resp.Body) 37 | resp.Body.Close() 38 | if err != nil { 39 | fmt.Println("读取body的时候发生了错误", err) 40 | } 41 | 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /godemo/使用map和json和os包快速生成json文件.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "os" 7 | ) 8 | 9 | func main() { 10 | 11 | a := map[string]string{ 12 | "a": "a", 13 | "b": "b", 14 | }//数据来源使用map是很爽的选择 15 | file, _ := os.OpenFile("./test.txt", os.O_WRONLY|os.O_CREATE, 0666)//创建生成文件file 16 | defer file.Close() 17 | err := json.NewEncoder(file).Encode(a) 18 | if err != nil { 19 | fmt.Println(err) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /godemo/使用readLine进行读写数据.go: -------------------------------------------------------------------------------- 1 | //读写数据,记住,写入数据的时候要flush一下。不然不会被写入的。 2 | package main 3 | 4 | import ( 5 | "bufio" 6 | "fmt" 7 | "io" 8 | "os" 9 | ) 10 | 11 | func main() { 12 | testI := 0 13 | inputFile, _ := os.Open("./test.txt") 14 | outputFile, _ := os.OpenFile("./储存.txt", os.O_WRONLY|os.O_CREATE, 0666) 15 | defer inputFile.Close() 16 | defer outputFile.Close() 17 | inputReader := bufio.NewReader(inputFile) 18 | outputWriter := bufio.NewWriter(outputFile) 19 | for { 20 | inputString, _, readerError := inputReader.ReadLine() 21 | if readerError == io.EOF { 22 | fmt.Println("EOF") 23 | break 24 | } 25 | outputString := string(inputString) + "\r\n" 26 | _, err := outputWriter.WriteString(outputString) 27 | if err != nil { 28 | fmt.Println(err) 29 | return 30 | } 31 | testI++ 32 | } 33 | outputWriter.Flush() 34 | fmt.Println("Conversion done", testI) 35 | } 36 | -------------------------------------------------------------------------------- /godemo/关于引用类型和实体类型的零值问题.go: -------------------------------------------------------------------------------- 1 | //map类型的零值是nil,也就是没有引用任何哈希表。 2 | //slice 的零值也是nil 非引用类型的零值不是nil 例如 int 3 | //零值就是0 float 是 0.0 string 是 “” 为什么引用类型的零值是nil呢? 4 | //因为 它底层需要指向一个实体,但是并没有分配,所以它只能指向nil了。 5 | //而实体声明的时候就直接有了一个初始零值,而且这个值肯定是分配内存了, 6 | //以为其它 引用类型也是分配内存了,指它本身,但是因为它指向的东西没有分配 7 | //所以就需要使用make来分配了至于new它就是 *的一个语法糖罢了。 8 | 9 | package main 10 | 11 | import ( 12 | "fmt" 13 | ) 14 | 15 | func main() { 16 | var a []int 17 | fmt.Println(a == nil) 18 | var b int 19 | fmt.Println(b) 20 | } 21 | 22 | //true 证明引用类型的初始值是零值 23 | //0 证明实体类型的零值是一个实实在在的值 用new的话只不过 是 分配了一个指向实体值的指针 是一个语法🍬 24 | 25 | -------------------------------------------------------------------------------- /godemo/关于循环变量的三种情况.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | const T = 10 6 | 7 | func main() { 8 | a := make([]func(), 0) 9 | // 第一种情况 10 | for i := 0; i < 10; i++ { 11 | a = append(a, func() { fmt.Println(i) }) 12 | } 13 | for _, v := range a { 14 | v() 15 | } 16 | // 第二种情况 17 | 18 | for i := 0; i < 10; i++ { 19 | func() { 20 | fmt.Println(i) 21 | }() 22 | } 23 | 24 | // 第三种情况 25 | 26 | b := make([]func(), 0) 27 | // 第一种情况 28 | for i := 0; i < 10; i++ { 29 | t := i 30 | b = append(b, func() { fmt.Println(t) }) 31 | } 32 | for _, v := range b { 33 | v() 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /godemo/关于结构体对象和接口的一些总结.go: -------------------------------------------------------------------------------- 1 | // 关于结构体对象 借口的一些总结。 2 | package main 3 | 4 | import "fmt" 5 | 6 | type a struct { 7 | t string 8 | } 9 | 10 | func main() { 11 | // 对象的初始化一定要用new 引用的初始化一定要用make。空指针是nil只有在使出来对象的方法的时候才能使用但是会出错,不要用 12 | // 实现接口,是指针对象实现的还是值对象实现的不一样,是谁实现的就用谁不能混用。使用 var a1 *a a1是nil。 13 | //虽然可以使用 a1.TT 但是会出现bug不能使用 t对象,所以 var a1 *a 只能当做声明,而 var a1 a 就是可以真正的分配了内存了。 14 | //对于方法也是,是指针类型就用指针是值就用值,因为在没有接口的时候可以乱用但是在有接口的时候就不能了,所以要守规矩是谁的就用谁 15 | //就ok了。 16 | a1 := new(a) 17 | var dd ttt// 接口对象永远不能用指针类型。否则报错。 18 | dd = a1 19 | dd.TT() 20 | } 21 | 22 | func (a1 *a) TT() { 23 | fmt.Println(a1.t) 24 | fmt.Println("d") 25 | } 26 | 27 | type ttt interface { 28 | TT() 29 | } 30 | -------------------------------------------------------------------------------- /godemo/关于闭包协程的三种方式的异同以及实现.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | var testValue = [5]int{1, 2, 3, 4, 5} 9 | 10 | func main() { 11 | //A: 12 | for v := range testValue { 13 | go func() { 14 | fmt.Println(v) 15 | }() 16 | } 17 | time.Sleep(1e5) 18 | //B: 19 | for v := range testValue { 20 | func() { 21 | fmt.Println(v) 22 | }() 23 | } 24 | //C: 25 | for v := range testValue { 26 | go func(x int) { 27 | fmt.Println(x) 28 | }(v) 29 | } 30 | 31 | } 32 | 33 | 34 | /* 35 | 4 都是4的原因是 协程是并发,所以有可能当for都执行完了 那些个协程还没正式运行,所以到最后就都是4(for执行速度快得很。) 36 | 4 37 | 4 38 | 4 39 | 40 | 41 | 0 因为是闭包,不过每次for循环都是立即执行,所以每次都能讲本次的值执行出来。 42 | 1 43 | 2 44 | 3 45 | 46 | 4 这种方式虽然跟第一种类似不过每个协程都有唯一的一个赋值,()这里面不是赋值了嘛,所以说它打印出来的数据就很正常喽。 47 | 0 48 | 2 49 | 1 50 | 3 51 | */ 52 | -------------------------------------------------------------------------------- /godemo/函数式编程.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | mapFunc(name, 12, 12, 33, 23) 7 | } 8 | 9 | type fun func(el int) int 10 | 11 | func name(el int) int {// 符合func 其实就是 函数头符合 func(int)int即可。 12 | return el * 10 13 | } 14 | func mapFunc(fn fun, el ...int) { 15 | for _, v := range el { 16 | fmt.Println(fn(v)) 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /godemo/创建命令.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "os/exec" 4 | 5 | func main() { 6 | cad := exec.Command("grep","hello")// 这个其实是创建一个命令 7 | cad.Start() 8 | cad.Wait() 9 | } 10 | -------------------------------------------------------------------------------- /godemo/利用slice和sort包来解决map的无序问题.go: -------------------------------------------------------------------------------- 1 | // 将map的k 赋值给一个slice,然后对这个slice的值进行排序(sort排序的是值不是k,因为slice的k是数字没有必要排序) 2 | // 然后将根据这个map以此变量并且取map得值,因为slice的range是有序的,并且 使用sort的时候其实是赋值给了一个新的slice。 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "sort" 8 | ) 9 | 10 | func main() { 11 | a := make(map[string]string) 12 | a["tr"] = "23" 13 | a["dd"] = "dd" 14 | rangeSliceValue := sortMap(a) 15 | for _, v := range rangeSliceValue { 16 | fmt.Println(a[v]) 17 | } 18 | 19 | } 20 | 21 | func sortMap(ma map[string]string) []string { 22 | var t []string 23 | for k, _ := range ma { 24 | t = append(t, k) 25 | } 26 | sort.Strings(t) 27 | return t 28 | } 29 | -------------------------------------------------------------------------------- /godemo/十分钟学会session_cookie/main.go: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/godemo/十分钟学会session_cookie/main.go -------------------------------------------------------------------------------- /godemo/去除相邻的重复值.go: -------------------------------------------------------------------------------- 1 | // 去除相邻的重复值 2 | package main 3 | 4 | import "fmt" 5 | 6 | func main() { 7 | fmt.Println(tt("11111111111111fewfefd44334434343434")) 8 | } 9 | func tt(str string) string { 10 | result := make([]byte, 0) 11 | byteStr := []byte(str) 12 | for i := 0; i < len(byteStr)-1; i++ { 13 | if byteStr[i+1] == byteStr[i] {// 只要前后一样那么就continue 14 | continue 15 | } else { 16 | result = append(result, byteStr[i])// 一旦不一样了就把这个数字append给result slice。 17 | } 18 | } 19 | return string(append(result,byteStr[len(byteStr)-1:]...)) 20 | // 因为最后一个数字是无法处理的,并且最后一个数字无论如果都是要加上的,所以直接 21 | //添加上即可。 22 | } 23 | -------------------------------------------------------------------------------- /godemo/在编译期间检查某类型是否实现了某个接口.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | ) 7 | 8 | func main() { 9 | var _ io.Writer = (*bytes.Buffer)(nil) // 它的目的就是在编译期间检查前面那个类型是否实现了前面的接口。 10 | } 11 | //解释一下为什么这么做,首先 *byte.buffer 是一个指针类型,然后我们要看它是否继承了这个接口, 12 | // 所以接口前面的白能量省略了,只需要声明即可,然后我们要用我们的类型将另一个类型转化为我们这个类型,当然 13 | //使用nil即可,因为转化需要底层一样,但是 一个nil的话就不需要这个规定,所以这么写的话就可以观察出来 并且 14 | //是在编译期间看出来是否继承了这个接口。 15 | -------------------------------------------------------------------------------- /godemo/多返回值的用法.go: -------------------------------------------------------------------------------- 1 | // go的多返回值,可以直接将另一个函数的多返回值直接利用。 2 | package main 3 | 4 | func main() { 5 | 6 | } 7 | 8 | 9 | func one()(string,string,string){ 10 | return "!","1","1" 11 | } 12 | 13 | func two()(string,string,string){ 14 | return one() 15 | } 16 | -------------------------------------------------------------------------------- /godemo/如何辨别两个字符串的每一个字符_字符相同顺序可以不同的判断方法.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | ) 7 | 8 | func main() { 9 | if ok := IsRight("12345 ", "12344 "); ok != nil { 10 | fmt.Println("您输入的两个字符串并不是同一个字符串", ok) 11 | } else { 12 | fmt.Println("👌") 13 | } 14 | } 15 | 16 | //IsRight 判断s1和s2 是否是同一个字符串(字符相同但是顺序可以不一样) 17 | func IsRight(s1, s2 string) error { 18 | var testValueY int 19 | if len(s1) != len(s2) { 20 | return errors.New("个数不同,不是同一个字符串") 21 | } 22 | byteS1, byteS2, le := []byte(s1), []byte(s2), len(s1) 23 | for i := 0; i < le; i++ { 24 | testValueX := 0 25 | for j := 0; j < le; j++ { 26 | if byteS1[i] != byteS2[j] { 27 | testValueX++ 28 | } 29 | } 30 | if testValueX == le { 31 | return errors.New("存在不一样的字符码数") 32 | } 33 | testValueY++ 34 | } 35 | if testValueY == le { 36 | return nil 37 | } else { 38 | return errors.New("存在不一样的字符码数") 39 | } 40 | return errors.New("未知错误") 41 | } 42 | 43 | 44 | -------------------------------------------------------------------------------- /godemo/对于select的初步认识.go: -------------------------------------------------------------------------------- 1 | // 开始测试select 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "time" 8 | ) 9 | 10 | func main() { 11 | Suck() 12 | time.Sleep(1e9) 13 | } 14 | 15 | func Sum1() chan int { 16 | ch := make(chan int) 17 | go func() { 18 | for i := 0; i < 1000; i++ { 19 | 20 | ch <- i 21 | } 22 | }() 23 | return ch 24 | } 25 | 26 | func Sum2() chan int { 27 | ch := make(chan int) 28 | go func() { 29 | for i := 0; i < 1000; i++ { 30 | 31 | ch <- i 32 | } 33 | }() 34 | return ch 35 | } 36 | 37 | func Suck() { 38 | ch1 := Sum1()// 这个地方的线程其实就是main线程(因为一会要导入到main中。所以可以统称就是main线程中的一部分。) 39 | ch2 := Sum2() 40 | go func() {// 这才是开启了一个新的线程。 41 | for { 42 | select { 43 | case v := <-ch1: 44 | fmt.Println("这是ch1:", v) 45 | case v := <-ch2: 46 | fmt.Println("这是ch2", v) 47 | } 48 | } 49 | }() 50 | } 51 | -------------------------------------------------------------------------------- /godemo/工厂模式(看起来最简洁最解耦的模式).go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func main() { 9 | fmt.Println("程序正式开始") 10 | dealEr() 11 | fmt.Println("你看我测试的最后结果成功的出来了吧") 12 | } 13 | 14 | func Sum() chan float64 { 15 | ch := make(chan float64) 16 | go func() { 17 | for i := 0.0; i < 10000000; i++ { 18 | ch <- i 19 | } 20 | }() 21 | return ch 22 | } 23 | 24 | func Suck(ch chan float64, done chan bool) { 25 | go func() { 26 | for { 27 | fmt.Println(<-ch) 28 | } 29 | done <- true 30 | }() 31 | 32 | } 33 | 34 | func sieve() { 35 | go func() { 36 | done := make(chan bool) 37 | ch := Sum() 38 | Suck(ch, done) 39 | <-done 40 | }() 41 | 42 | } 43 | func dealEr() { 44 | var t interface{} 45 | defer func() { 46 | if t = recover(); t != nil { 47 | fmt.Println("程序已经恢复", t) 48 | } 49 | }() 50 | sieve() 51 | time.Sleep(20 * 1e9) 52 | fmt.Println("panic 恢复正式开始", t) 53 | } 54 | -------------------------------------------------------------------------------- /godemo/并发和并行的一系类实例/add/add.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "runtime" 6 | "sync" 7 | "sync/atomic" 8 | ) 9 | 10 | func add(n []int) int64 { 11 | var result int64 12 | 13 | for _, v := range n { 14 | result += int64(v) 15 | } 16 | return result 17 | } 18 | 19 | func nadd(goruntimes int, n []int) int64 { 20 | var tt int64 21 | totalNumber := len(n) // 计算一共的量 22 | perNum := totalNumber / goruntimes // 计算每一个应该分多少 23 | var sy sync.WaitGroup 24 | sy.Add(goruntimes) 25 | for i := 0; i < goruntimes; i++ { 26 | go func(i int) { 27 | start := perNum * i 28 | end := perNum + start 29 | if i == goruntimes-1 { 30 | end = totalNumber 31 | } 32 | var t int64 33 | for _, v := range n[start:end] { 34 | t += int64(v) 35 | } 36 | atomic.AddInt64(&tt, int64(t)) 37 | sy.Done() 38 | }(i) 39 | } 40 | sy.Wait() 41 | return tt 42 | } 43 | 44 | func main(){ 45 | fmt.Println(add(num)) 46 | fmt.Println(nadd(runtime.NumCPU(),num)) 47 | } 48 | -------------------------------------------------------------------------------- /godemo/并发和并行的一系类实例/add/add_example.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func ExampleAdd(){ 4 | 5 | } 6 | -------------------------------------------------------------------------------- /godemo/并发和并行的一系类实例/add/add_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "runtime" 6 | "testing" 7 | ) 8 | 9 | 10 | func TestAdd(t *testing.T) { 11 | t.Log(add(num)) 12 | } 13 | 14 | func TestNadd(t *testing.T) { 15 | t.Log(nadd(runtime.NumCPU(),num)) 16 | } 17 | 18 | 19 | func BenchmarkAdd(b *testing.B) { 20 | for i := 0; i < b.N; i++ { 21 | add(num) 22 | } 23 | fmt.Println(len(num))// 经过计算 len是 24 | } 25 | 26 | func BenchmarkNadd(b *testing.B) { 27 | for i := 0; i < b.N; i++ { 28 | nadd(runtime.NumCPU(),num) 29 | } 30 | fmt.Println(len(num)) 31 | } 32 | 33 | 34 | // 只有这种数量级的时候才能战胜单线程。 也就是 150k的时候 并发性能更好,如果是数量级非常小 比如 几千几万的时候 并发(并发什么时候都是不行的, 35 | // 因为这是cpu bound)并行也是不行的。只有数量级非常大并且非常消耗计算量的时候 并行很厉害,但是也不会是跨越数量级的厉害。 36 | 37 | //综上所述 cpu型 bound 并行 > 顺序执行 > 并发 -------------------------------------------------------------------------------- /godemo/并发和并行的一系类实例/add/data.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | var num = []int{ // 这里有 180k的测试数据,已经测试完毕,经测试很多数据并发会比单行更快,但是不明显,但是并行是顺序执行几乎一倍的速度。 4 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 7 | } 8 | -------------------------------------------------------------------------------- /godemo/并发和并行的一系类实例/bubbleSort/bubbleSort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func main() { 9 | start := time.Now() 10 | bubbleSort(num) 11 | end := time.Now() 12 | 13 | fmt.Println(end.Sub(start)) 14 | start1 := time.Now() 15 | bubbleSort1(num) 16 | end1 := time.Now() 17 | 18 | fmt.Println(end1.Sub(start1)) 19 | } 20 | // 冒泡法的意思就是 把最大的或者是 最小的 往后挤压。就可以了 所以 他的 i 圈的循环次数一样。 j圈的循环次数也是一样的。 21 | func bubbleSort(num []int) { 22 | for i := 0; i < len(num)-1; i++ { 23 | for j := 0; j < len(num)-i-1; j++ {// 这是 前面大后面小的排列方法 24 | if num[j]>num[j+1]{ 25 | num[j+1],num[j] = num[j],num[j+1] 26 | } 27 | } 28 | } 29 | } 30 | 31 | func bubbleSort1(num []int) { 32 | for i := 0; i < len(num)-1; i++ { 33 | for j := 0; j < len(num)-i-1; j++ {// 这是 前面大后面小的排列方法 34 | if num[j],{0 },&{0 },&{0 } 26 | //这个时候再看a的值: &{0 } 27 | //a的用途就是这样,是一种声明,不能直接赋值,因为它原本就是一个指针啊 ,一把钥匙而已,系统没有分给他房间,它当然不能打开门了 28 | -------------------------------------------------------------------------------- /godemo/论出现指针赋值的时候出现空指针的原因.go: -------------------------------------------------------------------------------- 1 | // 根据这个可以延伸一下,之前经常出错或者是经常困惑的东西其实并不是引用类型例如slice map chan 2 | // 其实一直以来经常出错或者是经常困惑的是指针。指针空的时候不能取*。跟引用类型没有一毛钱关系,引用类型的实体也是一个实体值。 3 | package main 4 | 5 | import "fmt" 6 | 7 | 8 | type a struct { 9 | a2 string 10 | b1 *b 11 | } 12 | type b struct { 13 | c string 14 | } 15 | 16 | func TestValue() { 17 | var a1 a// 原因就是在于 a1.b1是个nil,指针的初始化就是nil,但是用nil是无法获取真实的内存地址的,所以就是出现提示nil pointer dereference. 18 | a1.b1 = &b{// 这个时候要做的就是给这个nil一个真实的内存地址即可。 19 | "", 20 | } 21 | a1.b1.c = "12"// 因为这个时候它已经被初始化了,不会是 nil 了。 22 | fmt.Println(a1.b1) 23 | } 24 | 25 | func main() { 26 | TestValue() 27 | } 28 | -------------------------------------------------------------------------------- /godemo/证明所有类型都可以实现一个接口.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type a int 6 | 7 | func (a1 a) get() { 8 | 9 | } 10 | 11 | type b interface { 12 | get() 13 | } 14 | 15 | func main() { 16 | var a1 a 17 | var b1 b 18 | b1 = a1 19 | fmt.Println(b1) 20 | b1.get() 21 | } 22 | 23 | // 证明了 所有类型都可以实现接口,甚至是 接口类型。(只需要这个接口和那个接口定义的方法一直,就可以直接赋值,不过 24 | // 没什么意义)。但 指针类型不可以,因为 指针类型不能作为 type后面的底层,所以它就无法实现接口了。 25 | -------------------------------------------------------------------------------- /godemo/读写文件并且更改文件中的部分bytebyte.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "io" 7 | "os" 8 | ) 9 | 10 | func main() { 11 | var i int // 测试的次数 12 | value := "💪" 13 | var byteValue = []byte(value) 14 | file, _ := os.Open("./go.mod") 15 | file2, err := os.OpenFile("./dd.txt", os.O_WRONLY|os.O_CREATE, 0666) // 这里一定要写成这个是以为 os.O_WRONLY|os.O_CREATE 没有就建一个这个关键点 16 | if err != nil { 17 | fmt.Println("在创建要写入的文件的时候出错", err) 18 | } 19 | defer file.Close() 20 | defer file2.Close() 21 | reader := bufio.NewReader(file) // 读文件 22 | writeer := bufio.NewWriter(file2) 23 | for { 24 | byte, err := reader.ReadByte() // 将reader具体解析为byte类型 25 | if err == io.EOF { 26 | break 27 | } 28 | fmt.Println(byte) 29 | byteValue = append(byteValue, byte) 30 | i++ 31 | } 32 | fmt.Println("运行的次数:", i) 33 | for _, v := range byteValue { 34 | writeer.WriteByte(v) 35 | } 36 | writeer.Flush() 37 | } 38 | -------------------------------------------------------------------------------- /godemo/调用本机命令行.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "os/exec" 7 | "syscall" 8 | ) 9 | 10 | func main() { 11 | bi, _ := exec.LookPath("ls")// 查看 命令的位置 12 | fmt.Println(bi) 13 | env := os.Environ()//本机环境变量 14 | fmt.Println(env) 15 | arg := []string{"ls", "/usr/bin", "-i"}// 真正的命令 16 | syscall.Exec(bi, arg, env)// 开始调用 17 | } 18 | -------------------------------------------------------------------------------- /godemo/返回相反的slice顺序.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | for k, v := range Reave([]int{1, 2, 3, 4, 5, 6}) { 7 | fmt.Println(k, v) 8 | } 9 | } 10 | 11 | // Reave 返回顺序相反的一个slice。 12 | func Reave(sli []int) []int { 13 | for i, j := 0, len(sli)-1; i < len(sli)/2; i, j = i+1, j-1 { 14 | sli[i], sli[j] = sli[j], sli[i] 15 | fmt.Println(sli[i]) 16 | } 17 | return sli 18 | } 19 | -------------------------------------------------------------------------------- /godemo/递归系列---尾递归的基本阐述.go: -------------------------------------------------------------------------------- 1 | // go语言中的递归,这里是 递归效率最高的递归--- 尾递归 2 | package main 3 | 4 | import ( 5 | "fmt" 6 | "time" 7 | ) 8 | 9 | func main() { 10 | start := time.Now() 11 | // 测试 尾递归调用 4000k ! 是极限值。 12 | a := testWEI(100, 0) 13 | end := time.Now() 14 | fmt.Println("花费了多久:", end.Sub(start), a) 15 | // 这里就可以证明返回的最后的结果是最下层的那个函数层级的函数。 16 | // 尾递归跟递归的不同,因为它运行的栈不需要记录地址,而且也不会出现爆栈的现象,因为它一直在一条线上运行,结尾就是调用自己,而且只有 17 | //一个结尾,所以只调用一次,永远都是1.所以尾递归是单线结构。 18 | } 19 | 20 | func testWEI(n int, sum int) func(n int) { 21 | if n == 0 { 22 | fmt.Println(n, sum) 23 | return nil 24 | } 25 | sum += n 26 | fmt.Println(n) 27 | return testWEI(n-1, sum) 28 | } 29 | -------------------------------------------------------------------------------- /godemo/高级用法_信号量_go异步写法.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func countNumber(in, count int, out chan int) { 8 | for i := 0; i < count; i++ { 9 | out <- in 10 | in = in + count 11 | } 12 | close(out) 13 | } 14 | 15 | func Done(in chan int, done chan bool) { 16 | for v := range in { 17 | fmt.Println(v) 18 | } 19 | done <- true 20 | } 21 | 22 | func main() { 23 | a1 := make(chan int) 24 | b1 := make(chan bool) 25 | go countNumber(0, 20, a1) 26 | go Done(a1, b1) 27 | //time.Sleep(1e9)//设置阻塞也可以,只不过不知道设置多长时间,所以使用这种<-b1的方式,是让他自己阻塞然后听命令结束。 28 | <-b1 //设置它的目的就是告诉main你已经完成任务了不用再阻塞了。不然没有这个的话,main直接结束自己 上面两个线程都没有机会运行。 29 | fmt.Println("1") 30 | } 31 | -------------------------------------------------------------------------------- /godemo/高级用法_工厂模式_go的通道协程异步问题.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func main() { 9 | ch1 := dd() 10 | go suck(ch1) 11 | time.Sleep(1e9) 12 | } 13 | 14 | func suck(ch chan int) { 15 | for { 16 | fmt.Println(<-ch) 17 | } 18 | } 19 | 20 | func dd() chan int { 21 | ch := make(chan int) 22 | go func() { 23 | for i := 0; ; i++ { 24 | ch <- i 25 | } 26 | }() 27 | return ch 28 | } 29 | -------------------------------------------------------------------------------- /gop_homework/README.md: -------------------------------------------------------------------------------- 1 | # The Go Programming Language 2 | 3 | 前几章的练习题都在每章的叫做 “练习题"的那个文件夹 后面几章我使用了 homework” 4 | 5 | ### 更新 6 | 7 | 2019-1-11 8 | 9 | 基本上所有的联系都搞定了,除了 一些我认为不重要或者我懒得写的,当然貌似有一个是我还没想到的,完成率估计 > 95% 10 | -------------------------------------------------------------------------------- /gop_homework/ch1/dup1/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 8. 5 | //!+ 6 | 7 | // Dup1 prints the text of each line that appears more than 8 | // once in the standard input, preceded by its count. 9 | package main 10 | 11 | import ( 12 | "bufio" 13 | "fmt" 14 | "os" 15 | ) 16 | 17 | func main() { 18 | counts := make(map[string]int) 19 | input := bufio.NewScanner(os.Stdin) 20 | for input.Scan() { 21 | counts[input.Text()]++ 22 | } 23 | // NOTE: ignoring potential errors from input.Err() 24 | for line, n := range counts { 25 | if n > 1 { 26 | fmt.Printf("%d\t%s\n", n, line) 27 | } 28 | } 29 | } 30 | 31 | //!- 32 | -------------------------------------------------------------------------------- /gop_homework/ch1/dup3/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 12. 5 | 6 | //!+ 7 | 8 | // Dup3 prints the count and text of lines that 9 | // appear more than once in the named input files. 10 | package main 11 | 12 | import ( 13 | "fmt" 14 | "io/ioutil" 15 | "os" 16 | "strings" 17 | ) 18 | 19 | func main() { 20 | counts := make(map[string]int) 21 | for _, filename := range os.Args[1:] { 22 | data, err := ioutil.ReadFile(filename) 23 | if err != nil { 24 | fmt.Fprintf(os.Stderr, "dup3: %v\n", err) 25 | continue 26 | } 27 | for _, line := range strings.Split(string(data), "\n") { 28 | counts[line]++ 29 | } 30 | } 31 | for line, n := range counts { 32 | if n > 1 { 33 | fmt.Printf("%d\t%s\n", n, line) 34 | } 35 | } 36 | } 37 | 38 | //!- 39 | -------------------------------------------------------------------------------- /gop_homework/ch1/echo1/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 4. 5 | //!+ 6 | 7 | // Echo1 prints its command-line arguments. 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | "os" 13 | ) 14 | 15 | func main() { 16 | var s, sep string 17 | for i := 1; i < len(os.Args); i++ { 18 | s += sep + os.Args[i] 19 | sep = " " 20 | } 21 | fmt.Println(s) 22 | } 23 | 24 | //!- 25 | -------------------------------------------------------------------------------- /gop_homework/ch1/echo2/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 6. 5 | //!+ 6 | 7 | // Echo2 prints its command-line arguments. 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | "os" 13 | ) 14 | 15 | func main() { 16 | s, sep := "", "" 17 | for _, arg := range os.Args[1:] { 18 | s += sep + arg 19 | sep = " " 20 | } 21 | fmt.Println(s) 22 | } 23 | 24 | //!- 25 | -------------------------------------------------------------------------------- /gop_homework/ch1/echo3/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 8. 5 | 6 | // Echo3 prints its command-line arguments. 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | "os" 12 | "strings" 13 | ) 14 | 15 | //!+ 16 | func main() { 17 | fmt.Println(strings.Join(os.Args[1:], " ")) 18 | } 19 | 20 | //!- 21 | -------------------------------------------------------------------------------- /gop_homework/ch1/fetch/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 16. 5 | //!+ 6 | 7 | // Fetch prints the content found at each specified URL. 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | "io/ioutil" 13 | "net/http" 14 | "os" 15 | ) 16 | 17 | func main() { 18 | for _, url := range os.Args[1:] { 19 | resp, err := http.Get(url) 20 | if err != nil { 21 | fmt.Fprintf(os.Stderr, "fetch: %v\n", err) 22 | os.Exit(1) 23 | } 24 | b, err := ioutil.ReadAll(resp.Body) 25 | resp.Body.Close() 26 | if err != nil { 27 | fmt.Fprintf(os.Stderr, "fetch: reading %s: %v\n", url, err) 28 | os.Exit(1) 29 | } 30 | fmt.Printf("%s", b) 31 | } 32 | } 33 | 34 | //!- 35 | -------------------------------------------------------------------------------- /gop_homework/ch1/helloworld/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 1. 5 | 6 | // Helloworld is our first Go program. 7 | //!+ 8 | package main 9 | 10 | import "fmt" 11 | 12 | func main() { 13 | fmt.Println("Hello, 世界") 14 | } 15 | 16 | //!- 17 | -------------------------------------------------------------------------------- /gop_homework/ch1/server1/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 19. 5 | //!+ 6 | 7 | // Server1 is a minimal "echo" server. 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | "log" 13 | "net/http" 14 | ) 15 | 16 | func main() { 17 | http.HandleFunc("/", handler) // each request calls handler 18 | log.Fatal(http.ListenAndServe("localhost:8000", nil)) 19 | } 20 | 21 | // handler echoes the Path component of the requested URL. 22 | func handler(w http.ResponseWriter, r *http.Request) { 23 | fmt.Fprintf(w, "URL.Path = %q\n", r.URL.Path) 24 | } 25 | 26 | //!- 27 | -------------------------------------------------------------------------------- /gop_homework/ch1/server2/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 20. 5 | //!+ 6 | 7 | // Server2 is a minimal "echo" and counter server. 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | "log" 13 | "net/http" 14 | "sync" 15 | ) 16 | 17 | var mu sync.Mutex 18 | var count int 19 | 20 | func main() { 21 | http.HandleFunc("/", handler) 22 | http.HandleFunc("/count", counter) 23 | log.Fatal(http.ListenAndServe("localhost:8000", nil)) 24 | } 25 | 26 | // handler echoes the Path component of the requested URL. 27 | func handler(w http.ResponseWriter, r *http.Request) { 28 | mu.Lock() 29 | count++ 30 | mu.Unlock() 31 | fmt.Fprintf(w, "URL.Path = %q\n", r.URL.Path) 32 | } 33 | 34 | // counter echoes the number of calls so far. 35 | func counter(w http.ResponseWriter, r *http.Request) { 36 | mu.Lock() 37 | fmt.Fprintf(w, "Count %d\n", count) 38 | mu.Unlock() 39 | } 40 | 41 | //!- 42 | -------------------------------------------------------------------------------- /gop_homework/ch1/server3/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 21. 5 | 6 | // Server3 is an "echo" server that displays request parameters. 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | "log" 12 | "net/http" 13 | ) 14 | 15 | func main() { 16 | http.HandleFunc("/", handler) 17 | log.Fatal(http.ListenAndServe("localhost:8000", nil)) 18 | } 19 | 20 | //!+handler 21 | // handler echoes the HTTP request. 22 | func handler(w http.ResponseWriter, r *http.Request) { 23 | fmt.Fprintf(w, "%s %s %s\n", r.Method, r.URL, r.Proto) 24 | for k, v := range r.Header { 25 | fmt.Fprintf(w, "Header[%q] = %q\n", k, v) 26 | } 27 | fmt.Fprintf(w, "Host = %q\n", r.Host) 28 | fmt.Fprintf(w, "RemoteAddr = %q\n", r.RemoteAddr) 29 | if err := r.ParseForm(); err != nil { 30 | log.Print(err) 31 | } 32 | for k, v := range r.Form { 33 | fmt.Fprintf(w, "Form[%q] = %q\n", k, v) 34 | } 35 | } 36 | 37 | //!-handler 38 | -------------------------------------------------------------------------------- /gop_homework/ch1/第一章练习题/练习1.1/main.go: -------------------------------------------------------------------------------- 1 | //练习 1.1: 修改echo程序,使其能够打印os.Args[0],即被执行命令本身的名字。 2 | package main 3 | 4 | import ( 5 | "fmt" 6 | "os" 7 | ) 8 | 9 | func main() { 10 | var s, sep string 11 | for i := 0; i < len(os.Args); i++ { // Args[0]就是执行的命令本身。 12 | s += sep + os.Args[i] 13 | sep = " " 14 | } 15 | fmt.Println("打印结果:", s) 16 | } 17 | // go run main.go 56 12 14 18 | ///var/folders/x7/dfv542p515dd6h37f69d506c0000gn/T/go-build524123334/b001/exe/main 56 12 14 19 | 20 | //可以看出 go run 的命令,会生成一个临时的文件。 21 | -------------------------------------------------------------------------------- /gop_homework/ch1/第一章练习题/练习1.11/main.go: -------------------------------------------------------------------------------- 1 | //练习 1.11: 在fetchall中尝试使用长一些的参数列表, 2 | //比如使用在alexa.com的上百万网站里排名靠前的。如果一个网站没有回应, 3 | //程序将采取怎样的行为?(Section8.9 描述了在这种情况下的应对机制)。 4 | package main 5 | 6 | func main() { 7 | 8 | } 9 | 10 | 11 | //Get https://google.com: dial tcp [2404:6800:4008:802::200e]:443: i/o timeout 12 | //30.01s elapsed -------------------------------------------------------------------------------- /gop_homework/ch1/第一章练习题/练习1.2/main.go: -------------------------------------------------------------------------------- 1 | //练习 1.2: 修改echo程序,使其打印每个参数的索引和值,每个一行。 2 | package main 3 | 4 | import ( 5 | "fmt" 6 | "os" 7 | ) 8 | 9 | func main() { 10 | 11 | for i := 1; i < len(os.Args); i++ { 12 | fmt.Println(i, ":", os.Args[i]) 13 | } 14 | 15 | } 16 | 17 | //go run main.go 12 23 123 18 | //1 : 12 19 | //2 : 23 20 | //3 : 123 21 | -------------------------------------------------------------------------------- /gop_homework/ch1/第一章练习题/练习1.4/test.txt: -------------------------------------------------------------------------------- 1 | 1 2 | 1 3 | 1 4 | 1 5 | 1 6 | 1 7 | 1 8 | 1 9 | 1 10 | 1 11 | 12 | 1 13 | 1 14 | 1 15 | 1 16 | 11 17 | 1 18 | 11 19 | 1 20 | 21 | 11 22 | 1 23 | 1 24 | -------------------------------------------------------------------------------- /gop_homework/ch1/第一章练习题/练习1.4/test1.txt: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | 3 4 | 4 5 | 5 6 | 6 7 | 7 8 | 8 9 | -------------------------------------------------------------------------------- /gop_homework/ch1/第一章练习题/练习1.4/test2.txt: -------------------------------------------------------------------------------- 1 | a 2 | s 3 | d 4 | f 5 | g 6 | h 7 | ja 8 | k 9 | l 10 | u 11 | y 12 | tr 13 | er 14 | we 15 | qe 16 | 17 | -------------------------------------------------------------------------------- /gop_homework/ch1/第一章练习题/练习1.5/tt.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/gop_homework/ch1/第一章练习题/练习1.5/tt.gif -------------------------------------------------------------------------------- /gop_homework/ch1/第一章练习题/练习1.6/tt.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/gop_homework/ch1/第一章练习题/练习1.6/tt.gif -------------------------------------------------------------------------------- /gop_homework/ch1/第一章练习题/练习1.7/main.go: -------------------------------------------------------------------------------- 1 | //练习 1.7: 函数调用io.Copy(dst, src)会从src中读取内容,并将读到的结果写入到dst中, 2 | //使用这个函数替代掉例子中的ioutil.ReadAll来拷贝响应结构体到os.Stdout,避免申请一个缓冲区(例子中的b)来存储。 3 | //记得处理io.Copy返回结果中的错误。 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "io" 9 | "log" 10 | "net/http" 11 | "os" 12 | ) 13 | 14 | func main() { 15 | arg := os.Args[1:] 16 | if len(arg) == 0 { 17 | 18 | fmt.Println("请输入url") 19 | log.Fatal("范例: go run main.go https://coastroad.net") 20 | } 21 | for _, url := range arg { 22 | resp, err := http.Get(url) 23 | if err != nil { 24 | fmt.Fprintf(os.Stderr, "fetch: %v\n", err) 25 | os.Exit(1) 26 | } 27 | w, err := io.Copy(os.Stdout, resp.Body) 28 | resp.Body.Close() 29 | if err != nil { 30 | fmt.Fprintf(os.Stderr, "fetch: reading %s: %v\n", url, err) 31 | os.Exit(1) 32 | } 33 | fmt.Println("打印一下copy的字节数", w) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /gop_homework/ch1/第一章练习题/练习1.8/main.go: -------------------------------------------------------------------------------- 1 | //练习 1.8: 修改fetch这个范例,如果输入的url参数没有 http:// 前缀的话, 2 | // 为这个url加上该前缀。你可能会用到strings.HasPrefix这个函数。 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "io" 8 | "log" 9 | "net/http" 10 | "os" 11 | "strings" 12 | ) 13 | 14 | func main() { 15 | arg := os.Args[1:] 16 | if len(arg) == 0 { 17 | 18 | fmt.Println("请输入url") 19 | log.Fatal("范例: go run main.go https://coastroad.net") 20 | } 21 | for _, url := range arg { 22 | if !strings.HasPrefix(url, "http://") { 23 | url = "http://" + url 24 | } 25 | resp, err := http.Get(url) 26 | if err != nil { 27 | fmt.Fprintf(os.Stderr, "fetch: %v\n", err) 28 | os.Exit(1) 29 | } 30 | w, err := io.Copy(os.Stdout, resp.Body) 31 | resp.Body.Close() 32 | if err != nil { 33 | fmt.Fprintf(os.Stderr, "fetch: reading %s: %v\n", url, err) 34 | os.Exit(1) 35 | } 36 | fmt.Println("打印一下copy的字节数", w) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /gop_homework/ch1/第一章练习题/练习1.9/main.go: -------------------------------------------------------------------------------- 1 | //练习 1.9: 修改fetch打印出HTTP协议的状态码,可以从resp.Status变量得到该状态码。 2 | package main 3 | 4 | import ( 5 | "fmt" 6 | "io" 7 | "log" 8 | "net/http" 9 | "os" 10 | ) 11 | 12 | func main() { 13 | arg := os.Args[1:] 14 | if len(arg) == 0 { 15 | 16 | fmt.Println("请输入url") 17 | log.Fatal("范例: go run main.go https://coastroad.net") 18 | } 19 | for _, url := range arg { 20 | resp, err := http.Get(url) 21 | if err != nil { 22 | fmt.Fprintf(os.Stderr, "fetch: %v\n", err) 23 | os.Exit(1) 24 | } 25 | w, err := io.Copy(os.Stdout, resp.Body) 26 | resp.Body.Close() 27 | if err != nil { 28 | fmt.Fprintf(os.Stderr, "fetch: reading %s: %v\n", url, err) 29 | os.Exit(1) 30 | } 31 | fmt.Println("打印一下copy的字节数", w) 32 | fmt.Println("打印一下 HTTP协议状态码:", resp.Status) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /gop_homework/ch10/cross/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 295. 5 | 6 | // The cross command prints the values of GOOS and GOARCH for this target. 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | "runtime" 12 | ) 13 | 14 | //!+ 15 | func main() { 16 | fmt.Println(runtime.GOOS, runtime.GOARCH) 17 | } 18 | 19 | //!- 20 | -------------------------------------------------------------------------------- /gop_homework/ch10/homework/test10.1/dd.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/gop_homework/ch10/homework/test10.1/dd.jpeg -------------------------------------------------------------------------------- /gop_homework/ch10/homework/test10.1/dd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/gop_homework/ch10/homework/test10.1/dd.png -------------------------------------------------------------------------------- /gop_homework/ch10/homework/test10.1/gif.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/gop_homework/ch10/homework/test10.1/gif.gif -------------------------------------------------------------------------------- /gop_homework/ch10/homework/test10.1/t.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/gop_homework/ch10/homework/test10.1/t.zip -------------------------------------------------------------------------------- /gop_homework/ch10/homework/test10.2/gif.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/gop_homework/ch10/homework/test10.2/gif.gif -------------------------------------------------------------------------------- /gop_homework/ch10/homework/test10.2/main.go: -------------------------------------------------------------------------------- 1 | //练习 10.2: 设计一个通用的压缩文件读取框架,用来读取ZIP(archive/zip)和POSIX tar(archive/tar) 2 | // 格式压缩的文档。使用类似上面的注册技术来扩展支持不同的压缩格式,然后根据需要通过匿名导入选择导入要支持的压缩格式的驱动包。 3 | package main 4 | 5 | import ( 6 | "archive/zip" 7 | "archive/tar" 8 | "fmt" 9 | "os" 10 | ) 11 | 12 | func main(){ 13 | t := make([]byte,1000) 14 | rc,err := zip.OpenReader("./t.zip") 15 | if err != nil { 16 | fmt.Println(err) 17 | } 18 | defer rc.Close() 19 | fmt.Println(*rc.File[0]) 20 | fmt.Println(rc.File[0]) 21 | file,err := os.Open("./t.tar") 22 | if err != nil { 23 | fmt.Println(err) 24 | } 25 | tar.NewReader(file).Read(t) 26 | fmt.Println(t) 27 | } -------------------------------------------------------------------------------- /gop_homework/ch10/homework/test10.2/t.tar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/gop_homework/ch10/homework/test10.2/t.tar -------------------------------------------------------------------------------- /gop_homework/ch10/homework/test10.2/t.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/gop_homework/ch10/homework/test10.2/t.zip -------------------------------------------------------------------------------- /gop_homework/ch10/homework/test10.3/main.go: -------------------------------------------------------------------------------- 1 | //练习 10.3: 从 http://gopl.io/ch1/helloworld?go-get=1 获取内容, 2 | // 查看本书的代码的真实托管的网址(go get请求HTML页面时包含了go-get参数,以区别普通的浏览器请求)。 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "io/ioutil" 8 | "net/http" 9 | ) 10 | 11 | func main(){ 12 | res,err := http.Get("http://gopl.io/ch1/helloworld?go-get=1") 13 | if err != nil { 14 | fmt.Println(err) 15 | } 16 | data,err := ioutil.ReadAll(res.Body) 17 | if err != nil { 18 | fmt.Println(err) 19 | } 20 | fmt.Println(string(data)) 21 | } 22 | 23 | 24 | -------------------------------------------------------------------------------- /gop_homework/ch11/echo/echo.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 308. 5 | //!+ 6 | 7 | // Echo prints its command-line arguments. 8 | package main 9 | 10 | import ( 11 | "flag" 12 | "fmt" 13 | "io" 14 | "os" 15 | "strings" 16 | ) 17 | 18 | var ( 19 | n = flag.Bool("n", false, "omit trailing newline") 20 | s = flag.String("s", " ", "separator") 21 | ) 22 | 23 | var out io.Writer = os.Stdout // modified during testing 24 | 25 | func main() { 26 | flag.Parse() 27 | if err := echo(!*n, *s, flag.Args()); err != nil { 28 | fmt.Fprintf(os.Stderr, "echo: %v\n", err) 29 | os.Exit(1) 30 | } 31 | } 32 | 33 | func echo(newline bool, sep string, args []string) error { 34 | fmt.Fprint(out, strings.Join(args, sep)) 35 | if newline { 36 | fmt.Fprintln(out) 37 | } 38 | return nil 39 | } 40 | 41 | //!- 42 | -------------------------------------------------------------------------------- /gop_homework/ch11/homework/test11.1/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "testing" 4 | 5 | func TestTT(t *testing.T) { 6 | TT() 7 | } 8 | -------------------------------------------------------------------------------- /gop_homework/ch11/homework/test11.2/intset_test.go: -------------------------------------------------------------------------------- 1 | package intset 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | var intS = new(IntSet) 9 | 10 | func init() { 11 | intS = &IntSet{ 12 | []uint64{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 13 | } 14 | } 15 | 16 | func TestHas(t *testing.T) { 17 | var result uint64 18 | intS.Add(1) 19 | fmt.Println(intS.words) 20 | for _, v := range intS.words { 21 | result += v 22 | } 23 | if result != 57 { 24 | t.Error("验证失败,结果不是66") 25 | } 26 | 27 | } 28 | 29 | func TestAdd(t *testing.T) { 30 | if !intS.Has(0) { 31 | t.Error("验证失败,没有0") 32 | } 33 | } 34 | 35 | func TestUnionWith(t *testing.T) { 36 | intS.UnionWith(intS) 37 | } 38 | -------------------------------------------------------------------------------- /gop_homework/ch11/homework/test11.4/main.go: -------------------------------------------------------------------------------- 1 | //修改randomPalindrome函数,以探索IsPalindrome是否对标点和空格做了正确处理。 2 | package main 3 | 4 | import ( 5 | "math/rand" 6 | "strings" 7 | ) 8 | 9 | func randomPalindrome(rng *rand.Rand) string { 10 | n := rng.Intn(25) // random length up to 24 11 | runes := make([]rune, n) 12 | for i := 0; i < (n+1)/2; i++ { 13 | r := rune(rng.Intn(0x1000)) // random rune up to '\u0999' 14 | runes[i] = r 15 | runes[n-1-i] = r 16 | } 17 | return string(runes) 18 | } 19 | 20 | func IsPalindrome(s string) bool { 21 | s = strings.Trim(s, ",") 22 | s = strings.Trim(s, " ") 23 | for i := range s { 24 | if s[i] != s[len(s)-1-i] { 25 | return false 26 | } 27 | } 28 | return true 29 | } 30 | -------------------------------------------------------------------------------- /gop_homework/ch11/homework/test11.5/main.go: -------------------------------------------------------------------------------- 1 | //练习11.5: 用表格驱动的技术扩展TestSplit测试,并打印期望的输出结果。 2 | package main 3 | 4 | import ( 5 | "strings" 6 | "testing" 7 | ) 8 | 9 | func TestSplit(t *testing.T) { 10 | s, sep := "a:b:c", ":" 11 | words := strings.Split(s, sep) 12 | if got, want := len(words), 3; got != want { 13 | t.Errorf("Split(%q, %q) returned %d words, want %d", 14 | s, sep, got, want) 15 | } 16 | // ... 17 | } 18 | -------------------------------------------------------------------------------- /gop_homework/ch11/homework/test11.6/main.go: -------------------------------------------------------------------------------- 1 | //练习 11.6: 为2.6.2节的练习2.4和练习2.5的PopCount函数编写基准测试。看看基于表格算法在不同情况下对提升性能会有多大帮助。 2 | package main 3 | -------------------------------------------------------------------------------- /gop_homework/ch11/homework/test11.7/main.go: -------------------------------------------------------------------------------- 1 | //练习 11.7: 为*IntSet(§6.5)的Add、UnionWith和其他方法编写基准测试, 2 | // 使用大量随机输入。你可以让这些方法跑多快?选择字的大小对于性能的影响如何?IntSet和基于内建map的实现相比有多快? 3 | package main 4 | -------------------------------------------------------------------------------- /gop_homework/ch11/word1/word.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 303. 5 | //!+ 6 | 7 | // Package word provides utilities for word games. 8 | package word 9 | 10 | // IsPalindrome reports whether s reads the same forward and backward. 11 | // (Our first attempt.) 12 | func IsPalindrome(s string) bool { 13 | for i := range s { 14 | if s[i] != s[len(s)-1-i] { 15 | return false 16 | } 17 | } 18 | return true 19 | } 20 | 21 | //!- 22 | -------------------------------------------------------------------------------- /gop_homework/ch11/word2/word.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 305. 5 | //!+ 6 | 7 | // Package word provides utilities for word games. 8 | package word 9 | 10 | import "unicode" 11 | 12 | // IsPalindrome reports whether s reads the same forward and backward. 13 | // Letter case is ignored, as are non-letters. 14 | func IsPalindrome(s string) bool { 15 | var letters []rune 16 | for _, r := range s { 17 | if unicode.IsLetter(r) { 18 | letters = append(letters, unicode.ToLower(r)) 19 | } 20 | } 21 | for i := range letters { 22 | if letters[i] != letters[len(letters)-1-i] { 23 | return false 24 | } 25 | } 26 | return true 27 | } 28 | 29 | //!- 30 | -------------------------------------------------------------------------------- /gop_homework/ch12/format/format_test.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package format_test 5 | 6 | import ( 7 | "fmt" 8 | "testing" 9 | "time" 10 | 11 | "gopl.io/ch12/format" 12 | ) 13 | 14 | func Test(t *testing.T) { 15 | // The pointer values are just examples, and may vary from run to run. 16 | //!+time 17 | var x int64 = 1 18 | var d time.Duration = 1 * time.Nanosecond 19 | fmt.Println(format.Any(x)) // "1" 20 | fmt.Println(format.Any(d)) // "1" 21 | fmt.Println(format.Any([]int64{x})) // "[]int64 0x8202b87b0" 22 | fmt.Println(format.Any([]time.Duration{d})) // "[]time.Duration 0x8202b87e0" 23 | //!-time 24 | } 25 | -------------------------------------------------------------------------------- /gop_homework/ch12/methods/methods.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 351. 5 | 6 | // Package methods provides a function to print the methods of any value. 7 | package methods 8 | 9 | import ( 10 | "fmt" 11 | "reflect" 12 | "strings" 13 | ) 14 | 15 | //!+print 16 | // Print prints the method set of the value x. 17 | func Print(x interface{}) { 18 | v := reflect.ValueOf(x) 19 | t := v.Type() 20 | fmt.Printf("type %s\n", t) 21 | 22 | for i := 0; i < v.NumMethod(); i++ { 23 | methType := v.Method(i).Type() 24 | fmt.Printf("func (%s) %s%s\n", t, t.Method(i).Name, 25 | strings.TrimPrefix(methType.String(), "func")) 26 | } 27 | } 28 | 29 | //!-print 30 | -------------------------------------------------------------------------------- /gop_homework/ch13/bzip-print/bzip2.c: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 362. 5 | // This is the version that appears in print, 6 | // but it does not comply with the proposed 7 | // rules for passing pointers between Go and C. 8 | // (https://github.com/golang/proposal/blob/master/design/12416-cgo-pointers.md) 9 | // See gopl.io/ch13/bzip for an updated version. 10 | 11 | //!+ 12 | /* This file is gopl.io/ch13/bzip/bzip2.c, */ 13 | /* a simple wrapper for libbzip2 suitable for cgo. */ 14 | #include 15 | 16 | int bz2compress(bz_stream *s, int action, 17 | char *in, unsigned *inlen, char *out, unsigned *outlen) { 18 | s->next_in = in; 19 | s->avail_in = *inlen; 20 | s->next_out = out; 21 | s->avail_out = *outlen; 22 | int r = BZ2_bzCompress(s, action); 23 | *inlen -= s->avail_in; 24 | *outlen -= s->avail_out; 25 | return r; 26 | } 27 | 28 | //!- 29 | -------------------------------------------------------------------------------- /gop_homework/ch13/bzipper/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 365. 5 | 6 | //!+ 7 | 8 | // Bzipper reads input, bzip2-compresses it, and writes it out. 9 | package main 10 | 11 | import ( 12 | "io" 13 | "log" 14 | "os" 15 | 16 | "gopl.io/ch13/bzip" 17 | ) 18 | 19 | func main() { 20 | w := bzip.NewWriter(os.Stdout) 21 | if _, err := io.Copy(w, os.Stdin); err != nil { 22 | log.Fatalf("bzipper: %v\n", err) 23 | } 24 | if err := w.Close(); err != nil { 25 | log.Fatalf("bzipper: close: %v\n", err) 26 | } 27 | } 28 | 29 | //!- 30 | -------------------------------------------------------------------------------- /gop_homework/ch13/unsafeptr/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 357. 5 | 6 | // Package unsafeptr demonstrates basic use of unsafe.Pointer. 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | "unsafe" 12 | ) 13 | 14 | func main() { 15 | //!+main 16 | var x struct { 17 | a bool 18 | b int16 19 | c []int 20 | } 21 | 22 | // equivalent to pb := &x.b 23 | pb := (*int16)(unsafe.Pointer( 24 | uintptr(unsafe.Pointer(&x)) + unsafe.Offsetof(x.b))) 25 | *pb = 42 26 | 27 | fmt.Println(x.b) // "42" 28 | //!-main 29 | } 30 | 31 | /* 32 | //!+wrong 33 | // NOTE: subtly incorrect! 34 | tmp := uintptr(unsafe.Pointer(&x)) + unsafe.Offsetof(x.b) 35 | pb := (*int16)(unsafe.Pointer(tmp)) 36 | *pb = 42 37 | //!-wrong 38 | */ 39 | -------------------------------------------------------------------------------- /gop_homework/ch2/boiling/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 29. 5 | //!+ 6 | 7 | // Boiling prints the boiling point of water. 8 | package main 9 | 10 | import "fmt" 11 | 12 | const boilingF = 212.0 13 | 14 | func main() { 15 | var f = boilingF 16 | var c = (f - 32) * 5 / 9 17 | fmt.Printf("boiling point = %g°F or %g°C\n", f, c) 18 | // Output: 19 | // boiling point = 212°F or 100°C 20 | } 21 | 22 | //!- 23 | -------------------------------------------------------------------------------- /gop_homework/ch2/cf/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 43. 5 | //!+ 6 | 7 | // Cf converts its numeric argument to Celsius and Fahrenheit. 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | "os" 13 | "strconv" 14 | 15 | "gopl.io/ch2/tempconv" 16 | ) 17 | 18 | func main() { 19 | for _, arg := range os.Args[1:] { 20 | t, err := strconv.ParseFloat(arg, 64) 21 | if err != nil { 22 | fmt.Fprintf(os.Stderr, "cf: %v\n", err) 23 | os.Exit(1) 24 | } 25 | f := tempconv.Fahrenheit(t) 26 | c := tempconv.Celsius(t) 27 | fmt.Printf("%s = %s, %s = %s\n", 28 | f, tempconv.FToC(f), c, tempconv.CToF(c)) 29 | } 30 | } 31 | 32 | //!- 33 | -------------------------------------------------------------------------------- /gop_homework/ch2/echo4/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 33. 5 | //!+ 6 | 7 | // Echo4 prints its command-line arguments. 8 | package main 9 | 10 | import ( 11 | "flag" 12 | "fmt" 13 | "strings" 14 | ) 15 | 16 | var n = flag.Bool("n", false, "omit trailing newline") 17 | var sep = flag.String("s", " ", "separator") 18 | 19 | func main() { 20 | flag.Parse() 21 | fmt.Print(strings.Join(flag.Args(), *sep)) 22 | if !*n { 23 | fmt.Println() 24 | } 25 | } 26 | 27 | //!- 28 | -------------------------------------------------------------------------------- /gop_homework/ch2/ftoc/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 29. 5 | //!+ 6 | 7 | // Ftoc prints two Fahrenheit-to-Celsius conversions. 8 | package main 9 | 10 | import "fmt" 11 | 12 | func main() { 13 | const freezingF, boilingF = 32.0, 212.0 14 | fmt.Printf("%g°F = %g°C\n", freezingF, fToC(freezingF)) // "32°F = 0°C" 15 | fmt.Printf("%g°F = %g°C\n", boilingF, fToC(boilingF)) // "212°F = 100°C" 16 | } 17 | 18 | func fToC(f float64) float64 { 19 | return (f - 32) * 5 / 9 20 | } 21 | 22 | //!- 23 | -------------------------------------------------------------------------------- /gop_homework/ch2/popcount/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 45. 5 | 6 | // (Package doc comment intentionally malformed to demonstrate golint.) 7 | //!+ 8 | package popcount 9 | 10 | // pc[i] is the population count of i. 11 | var pc [256]byte 12 | 13 | func init() { 14 | for i := range pc { 15 | pc[i] = pc[i/2] + byte(i&1) 16 | } 17 | } 18 | 19 | // PopCount returns the population count (number of set bits) of x. 20 | func PopCount(x uint64) int { 21 | return int(pc[byte(x>>(0*8))] + 22 | pc[byte(x>>(1*8))] + 23 | pc[byte(x>>(2*8))] + 24 | pc[byte(x>>(3*8))] + 25 | pc[byte(x>>(4*8))] + 26 | pc[byte(x>>(5*8))] + 27 | pc[byte(x>>(6*8))] + 28 | pc[byte(x>>(7*8))]) 29 | } 30 | 31 | //!- 32 | -------------------------------------------------------------------------------- /gop_homework/ch2/tempconv/conv.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 41. 5 | 6 | //!+ 7 | 8 | package tempconv 9 | 10 | // CToF converts a Celsius temperature to Fahrenheit. 11 | func CToF(c Celsius) Fahrenheit { return Fahrenheit(c*9/5 + 32) } 12 | 13 | // FToC converts a Fahrenheit temperature to Celsius. 14 | func FToC(f Fahrenheit) Celsius { return Celsius((f - 32) * 5 / 9) } 15 | 16 | //!- 17 | -------------------------------------------------------------------------------- /gop_homework/ch2/tempconv/tempconv.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | //!+ 5 | 6 | // Package tempconv performs Celsius and Fahrenheit conversions. 7 | package tempconv 8 | 9 | import "fmt" 10 | 11 | type Celsius float64 12 | type Fahrenheit float64 13 | 14 | const ( 15 | AbsoluteZeroC Celsius = -273.15 16 | FreezingC Celsius = 0 17 | BoilingC Celsius = 100 18 | ) 19 | 20 | func (c Celsius) String() string { return fmt.Sprintf("%g°C", c) } 21 | func (f Fahrenheit) String() string { return fmt.Sprintf("%g°F", f) } 22 | 23 | //!- 24 | -------------------------------------------------------------------------------- /gop_homework/ch2/tempconv0/celsius.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 39. 5 | //!+ 6 | 7 | // Package tempconv performs Celsius and Fahrenheit temperature computations. 8 | package tempconv 9 | 10 | import "fmt" 11 | 12 | type Celsius float64 13 | type Fahrenheit float64 14 | 15 | const ( 16 | AbsoluteZeroC Celsius = -273.15 17 | FreezingC Celsius = 0 18 | BoilingC Celsius = 100 19 | ) 20 | 21 | func CToF(c Celsius) Fahrenheit { return Fahrenheit(c*9/5 + 32) } 22 | 23 | func FToC(f Fahrenheit) Celsius { return Celsius((f - 32) * 5 / 9) } 24 | 25 | //!- 26 | 27 | func (c Celsius) String() string { return fmt.Sprintf("%g°C", c) } 28 | -------------------------------------------------------------------------------- /gop_homework/ch2/第二章练习题/练习2.3/popcount.go: -------------------------------------------------------------------------------- 1 | //练习 2.3: 重写PopCount函数,用一个循环代替单一的表达式。比较两个版本的性能。(11.4节将展示如何系统地比较两个不同实现的性能。) 2 | package main 3 | 4 | import "fmt" 5 | 6 | // pc[i] is the population count of i. 7 | var pc [256]byte 8 | 9 | func init() { 10 | for i := range pc { 11 | pc[i] = pc[i/2] + byte(i&1) 12 | } 13 | } 14 | 15 | // PopCount returns the population count (number of set bits) of x. 16 | func PopCount(x uint64) int { 17 | return int(pc[byte(x>>(0*8))] + 18 | pc[byte(x>>(1*8))] + 19 | pc[byte(x>>(2*8))] + 20 | pc[byte(x>>(3*8))] + 21 | pc[byte(x>>(4*8))] + 22 | pc[byte(x>>(5*8))] + 23 | pc[byte(x>>(6*8))] + 24 | pc[byte(x>>(7*8))]) 25 | } 26 | 27 | func PopCountCycle(x uint64) int { 28 | result := byte(0) 29 | for i := 0; i < 7; i++ { 30 | var t uint8 = uint8(i) 31 | result += pc[byte(x>>(t*8))] 32 | } 33 | return int(result) 34 | 35 | } 36 | 37 | func main(){ 38 | fmt.Println(PopCountCycle(1000)) 39 | fmt.Println(PopCount(1000)) 40 | } -------------------------------------------------------------------------------- /gop_homework/ch2/第二章练习题/练习2.3/popcount_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "testing" 4 | 5 | func BenchmarkPopCount(b *testing.B) { 6 | for i := 0; i < b.N; i++ { 7 | PopCount(1000) 8 | } 9 | } 10 | 11 | func BenchmarkPopCountCycle(b *testing.B) { 12 | for i := 0; i < b.N; i++ { 13 | PopCountCycle(1000) 14 | } 15 | } 16 | 17 | //go test -cpu=4 -bench=. 18 | //goos: darwin 19 | //goarch: amd64 20 | //pkg: github.com/googege/gopl_homework/ch2/第二章练习题/练习2.3 21 | //BenchmarkPopCount-4 2000000000 0.37 ns/op 22 | //BenchmarkPopCountCycle-4 100000000 18.8 ns/op 23 | //PASS 24 | //ok github.com/googege/gopl_homework/ch2/第二章练习题/练习2.3 2.698s 25 | -------------------------------------------------------------------------------- /gop_homework/ch2/第二章练习题/练习2.4/main.go: -------------------------------------------------------------------------------- 1 | //练习 2.4: 用移位算法重写PopCount函数,每次测试最右边的1bit,然后统计总数。比较和查表算法的性能差异。 2 | package main 3 | 4 | // pc[i] is the population count of i. 5 | var pc [256]byte 6 | 7 | func init() { 8 | for i := range pc { 9 | pc[i] = pc[i/2] + byte(i&1) 10 | } 11 | } 12 | 13 | // PopCount returns the population count (number of set bits) of x. 14 | func PopCount(x uint64) int { 15 | return int(pc[byte(x>>(0*8))] + 16 | pc[byte(x>>(1*8))] + 17 | pc[byte(x>>(2*8))] + 18 | pc[byte(x>>(3*8))] + 19 | pc[byte(x>>(4*8))] + 20 | pc[byte(x>>(5*8))] + 21 | pc[byte(x>>(6*8))] + 22 | pc[byte(x>>(7*8))]) 23 | } 24 | 25 | func PopCountRewrite2(x uint64) int { 26 | var count int 27 | for i := 0; i < 64; i++ { 28 | count += int(x >> uint(i) & 1) 29 | } 30 | return count 31 | } -------------------------------------------------------------------------------- /gop_homework/ch2/第二章练习题/练习2.4/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "testing" 4 | 5 | func BenchmarkPopCount(b *testing.B) { 6 | for i := 0; i < b.N; i++ { 7 | PopCount(600) 8 | } 9 | } 10 | 11 | func BenchmarkPopCount2(b *testing.B) { 12 | for i := 0; i < b.N; i++ { 13 | PopCountRewrite2(600) 14 | } 15 | } 16 | //pkg: github.com/googege/gopl_homework/ch2/第二章练习题/练习2.4 17 | //BenchmarkPopCount-4 2000000000 0.37 ns/op 18 | //BenchmarkPopCount2-4 20000000 69.7 ns/op 19 | //PASS 20 | //ok github.com/googege/gopl_homework/ch2/第二章练习题/练习2.4 2.267s 21 | -------------------------------------------------------------------------------- /gop_homework/ch2/第二章练习题/练习2.5/main.go: -------------------------------------------------------------------------------- 1 | //练习 2.5: 表达式x&(x-1)用于将x的最低的一个非零的bit位清零。使用这个算法重写PopCount函数,然后比较性能。 2 | package main 3 | 4 | // pc[i] is the population count of i. 5 | var pc [256]byte 6 | 7 | func init() { 8 | for i := range pc { 9 | pc[i] = pc[i/2] + byte(i&1) 10 | } 11 | } 12 | 13 | // PopCount returns the population count (number of set bits) of x. 14 | func PopCount(x uint64) int { 15 | return int(pc[byte(x>>(0*8))] + 16 | pc[byte(x>>(1*8))] + 17 | pc[byte(x>>(2*8))] + 18 | pc[byte(x>>(3*8))] + 19 | pc[byte(x>>(4*8))] + 20 | pc[byte(x>>(5*8))] + 21 | pc[byte(x>>(6*8))] + 22 | pc[byte(x>>(7*8))]) 23 | } 24 | 25 | func PopCountRewrite3(x uint64) int { 26 | var count int 27 | for x != 0 { 28 | count++ 29 | x &= x - 1 30 | } 31 | return count 32 | } 33 | -------------------------------------------------------------------------------- /gop_homework/ch2/第二章练习题/练习2.5/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | 4 | 5 | 6 | 7 | import "testing" 8 | 9 | func BenchmarkPopCount(b *testing.B) { 10 | for i := 0; i < b.N; i++ { 11 | PopCount(600) 12 | } 13 | } 14 | 15 | func BenchmarkPopCount2(b *testing.B) { 16 | for i := 0; i < b.N; i++ { 17 | PopCountRewrite3(600) 18 | } 19 | } 20 | 21 | 22 | //go test -bench=. -cpu=4 23 | //goos: darwin 24 | //goarch: amd64 25 | //pkg: github.com/googege/gopl_homework/ch2/第二章练习题/练习2.5 26 | //BenchmarkPopCount-4 2000000000 0.38 ns/op 27 | //BenchmarkPopCount2-4 200000000 7.86 ns/op 28 | //PASS 29 | //ok github.com/googege/gopl_homework/ch2/第二章练习题/练习2.5 3.168s -------------------------------------------------------------------------------- /gop_homework/ch3/basename2/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 72. 5 | 6 | // Basename2 reads file names from stdin and prints the base name of each one. 7 | package main 8 | 9 | import ( 10 | "bufio" 11 | "fmt" 12 | "os" 13 | "strings" 14 | ) 15 | 16 | func main() { 17 | input := bufio.NewScanner(os.Stdin) 18 | for input.Scan() { 19 | fmt.Println(basename(input.Text())) 20 | } 21 | // NOTE: ignoring potential errors from input.Err() 22 | } 23 | 24 | // basename removes directory components and a trailing .suffix. 25 | // e.g., a => a, a.go => a, a/b/c.go => c, a/b.c.go => b.c 26 | //!+ 27 | func basename(s string) string { 28 | slash := strings.LastIndex(s, "/") // -1 if "/" not found 29 | s = s[slash+1:] 30 | if dot := strings.LastIndex(s, "."); dot >= 0 { 31 | s = s[:dot] 32 | } 33 | return s 34 | } 35 | 36 | //!- 37 | -------------------------------------------------------------------------------- /gop_homework/ch3/comma/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 73. 5 | 6 | // Comma prints its argument numbers with a comma at each power of 1000. 7 | // 8 | // Example: 9 | // $ go build gopl.io/ch3/comma 10 | // $ ./comma 1 12 123 1234 1234567890 11 | // 1 12 | // 12 13 | // 123 14 | // 1,234 15 | // 1,234,567,890 16 | // 17 | package main 18 | 19 | import ( 20 | "fmt" 21 | "os" 22 | ) 23 | 24 | func main() { 25 | for i := 1; i < len(os.Args); i++ { 26 | fmt.Printf(" %s\n", comma(os.Args[i])) 27 | } 28 | } 29 | 30 | //!+ 31 | // comma inserts commas in a non-negative decimal integer string. 32 | func comma(s string) string { 33 | n := len(s) 34 | if n <= 3 { 35 | return s 36 | } 37 | return comma(s[:n-3]) + "," + s[n-3:] 38 | } 39 | 40 | //!- 41 | -------------------------------------------------------------------------------- /gop_homework/ch3/netflag/netflag.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 77. 5 | 6 | // Netflag demonstrates an integer type used as a bit field. 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | . "net" 12 | ) 13 | 14 | //!+ 15 | func IsUp(v Flags) bool { return v&FlagUp == FlagUp } 16 | func TurnDown(v *Flags) { *v &^= FlagUp } 17 | func SetBroadcast(v *Flags) { *v |= FlagBroadcast } 18 | func IsCast(v Flags) bool { return v&(FlagBroadcast|FlagMulticast) != 0 } 19 | 20 | func main() { 21 | var v Flags = FlagMulticast | FlagUp 22 | fmt.Printf("%b %t\n", v, IsUp(v)) // "10001 true" 23 | TurnDown(&v) 24 | fmt.Printf("%b %t\n", v, IsUp(v)) // "10000 false" 25 | SetBroadcast(&v) 26 | fmt.Printf("%b %t\n", v, IsUp(v)) // "10010 false" 27 | fmt.Printf("%b %t\n", v, IsCast(v)) // "10010 true" 28 | } 29 | 30 | //!- 31 | -------------------------------------------------------------------------------- /gop_homework/ch3/printints/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 74. 5 | 6 | // Printints demonstrates the use of bytes.Buffer to format a string. 7 | package main 8 | 9 | import ( 10 | "bytes" 11 | "fmt" 12 | ) 13 | 14 | //!+ 15 | // intsToString is like fmt.Sprint(values) but adds commas. 16 | func intsToString(values []int) string { 17 | var buf bytes.Buffer 18 | buf.WriteByte('[') 19 | for i, v := range values { 20 | if i > 0 { 21 | buf.WriteString(", ") 22 | } 23 | fmt.Fprintf(&buf, "%d", v) 24 | } 25 | buf.WriteByte(']') 26 | return buf.String() 27 | } 28 | 29 | func main() { 30 | fmt.Println(intsToString([]int{1, 2, 3})) // "[1, 2, 3]" 31 | } 32 | 33 | //!- 34 | -------------------------------------------------------------------------------- /gop_homework/ch3/第三章练习题/练习3.10/main.go: -------------------------------------------------------------------------------- 1 | //练习 3.10: 编写一个非递归版本的comma函数,使用bytes.Buffer代替字符串链接操作。 2 | package main 3 | 4 | import ( 5 | "bytes" 6 | "fmt" 7 | ) 8 | 9 | func main() { 10 | t := []string{"111", "2222277777"} 11 | for i := 0; i < len(t); i++ { 12 | fmt.Printf(" %s\n", comma(t[i])) 13 | fmt.Println("2:::", commaBuffer([]byte(t[i]))) 14 | } 15 | 16 | } 17 | 18 | //!+ 速度慢是因为递归。 19 | // comma inserts commas in a non-negative decimal integer string. 20 | func comma(s string) string { 21 | n := len(s) 22 | if n <= 3 { 23 | return s 24 | } 25 | return comma(s[:n-3]) + "," + s[n-3:] 26 | 27 | } 28 | 29 | func commaBuffer(s []byte) string { 30 | var buf bytes.Buffer 31 | b := 0 32 | if len(s) <= 3 { 33 | fmt.Println(string(s)) 34 | return string(s) 35 | } 36 | for _, v := range s { 37 | buf.WriteByte(v) 38 | if b == 2 { 39 | buf.WriteByte(',') 40 | b = -1 41 | } 42 | b++ 43 | } 44 | return buf.String() 45 | 46 | } 47 | -------------------------------------------------------------------------------- /gop_homework/ch3/第三章练习题/练习3.10/test.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/gop_homework/ch3/第三章练习题/练习3.10/test.txt -------------------------------------------------------------------------------- /gop_homework/ch3/第三章练习题/练习3.11/main.go: -------------------------------------------------------------------------------- 1 | //练习 3.11: 完善comma函数,以支持浮点数处理和一个可选的正负号的处理。 2 | package main 3 | 4 | import ( 5 | "bytes" 6 | "strconv" 7 | ) 8 | 9 | func main() { 10 | t := "3232323223323232323232322332232323" 11 | var t1 float64 = 3443344343344343434343433443434343 12 | commaBuffer(t) 13 | commaBuffer(t1) 14 | 15 | } 16 | 17 | func commaBuffer(s interface{}) string { 18 | var buf bytes.Buffer 19 | b := 0 20 | if k, ok := s.(float64); ok { 21 | st := strconv.FormatFloat(k, 'f', 5, 64) 22 | if len([]byte(st)) <= 3 { 23 | return st 24 | } 25 | for _, v := range []byte(st) { 26 | buf.WriteByte(v) 27 | if b == 2 { 28 | buf.WriteByte(',') 29 | b = -1 30 | } 31 | b++ 32 | } 33 | } else if k, ok := s.(string); ok { 34 | if len([]byte(k)) <= 3 { 35 | return k 36 | } 37 | for _, v := range []byte(k) { 38 | buf.WriteByte(v) 39 | if b == 2 { 40 | buf.WriteByte(',') 41 | b = -1 42 | } 43 | b++ 44 | } 45 | } 46 | 47 | return buf.String() 48 | 49 | } 50 | -------------------------------------------------------------------------------- /gop_homework/ch3/第三章练习题/练习3.12/example_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func ExampleEathOther() { 6 | fmt.Println("ok nice") 7 | // Output:ok nice 8 | } 9 | -------------------------------------------------------------------------------- /gop_homework/ch3/第三章练习题/练习3.12/main.go: -------------------------------------------------------------------------------- 1 | //练习 3.12: 编写一个函数,判断两个字符串是否是是相互打乱的,也就是说它们有着相同的字符,但是对应不同的顺序。 2 | package main 3 | 4 | import "fmt" 5 | 6 | func main() { 7 | fmt.Println(EathOther("321", "123")) 8 | 9 | } 10 | 11 | func EathOther(s1, s2 string) (bool, string) { 12 | var ts int = 0 13 | var ty int = 0 14 | byteS1 := []byte(s1) 15 | byteS2 := []byte(s2) 16 | if len(byteS1) != len(byteS2) { 17 | return false, "len不相等" 18 | } 19 | for i := 0; i < len(byteS1); i++ { 20 | ts = 0 21 | for j := 0; j < len(byteS1); j++ { 22 | if byteS1[i] == byteS2[j] { 23 | ts++ 24 | } 25 | 26 | } 27 | if ts > 0 { 28 | ty++ 29 | } 30 | } 31 | if ty == len(byteS2) { 32 | return true, "nice" 33 | } else { 34 | return false, "有不相等的数据" 35 | } 36 | return false, "" 37 | 38 | } 39 | -------------------------------------------------------------------------------- /gop_homework/ch3/第三章练习题/练习3.12/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func BenchmarkEathOther(b *testing.B) { 8 | for i := 0; i < b.N; i++ { 9 | EathOther("12345", "54321") 10 | } 11 | } 12 | 13 | func TestEathOther(t *testing.T) { 14 | if k, v := EathOther("12345", "54321"); k { 15 | t.Log("ok", v) 16 | } else { 17 | t.Fatal("error", v) 18 | } 19 | } 20 | 21 | 22 | 23 | //go test 24 | //PASS 25 | //ok github.com/googege/gopl_homework/ch3/第三章练习题/练习3.12 0.008s 26 | 27 | //go test -bench=. -cpu=4 28 | //goos: darwin 29 | //goarch: amd64 30 | //pkg: github.com/googege/gopl_homework/ch3/第三章练习题/练习3.12 31 | //BenchmarkEathOther-4 30000000 45.2 ns/op 32 | //PASS 33 | //ok github.com/googege/gopl_homework/ch3/第三章练习题/练习3.12 1.410s 34 | -------------------------------------------------------------------------------- /gop_homework/ch3/第三章练习题/练习3.13/main.go: -------------------------------------------------------------------------------- 1 | //练习 3.13: 编写KB、MB的常量声明,然后扩展到YB 2 | package main 3 | 4 | import "fmt" 5 | 6 | const ( 7 | _ = 1 << (10 * iota) //iota = 0 8 | KiB // 1024 iota = 1 9 | MiB // 1048576 iota =2 10 | GiB // 1073741824 11 | TiB // 1099511627776 (exceeds 1 << 32) 12 | PiB // 1125899906842624 13 | EiB // 1152921504606846976 14 | ZiB // 1180591620717411303424 (exceeds 1 << 64) 15 | YiB // 1208925819614629174706176 16 | ) 17 | 18 | func main() { 19 | fmt.Printf("%b\t%d\n", KiB, KiB) 20 | } 21 | 22 | // 1 << 0 = 1 23 | // 1 << 10 == 10000000000 24 | //1 << 20 == 100000000000000000000 25 | 26 | // 所谓左移符号,就是这样的 最后一位的数字 (当然是1) 移动的位数,然后没有的地方用0补充。 27 | 28 | //也就是说 : -------------------------------------------------------------------------------- /gop_homework/ch3/第三章练习题/练习3.5/tt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/gop_homework/ch3/第三章练习题/练习3.5/tt.png -------------------------------------------------------------------------------- /gop_homework/ch3/第三章练习题/练习3.7/main.go: -------------------------------------------------------------------------------- 1 | //练习 3.7: 另一个生成分形图像的方式是使用牛顿法来求解一个复数方程,例如$z^4-1=0$。每个起点到四个根的迭代次数对应阴影的灰度。 2 | // 方程根对应的点用颜色表示。 3 | package main 4 | -------------------------------------------------------------------------------- /gop_homework/ch3/第三章练习题/练习3.8/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "testing" 4 | 5 | func Benchmarkcomp64(b *testing.B) { 6 | for i := 0; i < b.N; i++ { 7 | tt() 8 | } 9 | } 10 | 11 | func Benchmarkcom128(b *testing.B) { 12 | for i := 0; i < b.N; i++ { 13 | tt128() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /gop_homework/ch4/autoescape/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 117. 5 | 6 | // Autoescape demonstrates automatic HTML escaping in html/template. 7 | package main 8 | 9 | import ( 10 | "html/template" 11 | "log" 12 | "os" 13 | ) 14 | 15 | //!+ 16 | func main() { 17 | const templ = `

    A: {{.A}}

    B: {{.B}}

    ` 18 | t := template.Must(template.New("escape").Parse(templ)) 19 | var data struct { 20 | A string // untrusted plain text 21 | B template.HTML // trusted HTML 22 | } 23 | data.A = "Hello!" 24 | data.B = "Hello!" 25 | if err := t.Execute(os.Stdout, data); err != nil { 26 | log.Fatal(err) 27 | } 28 | } 29 | 30 | //!- 31 | -------------------------------------------------------------------------------- /gop_homework/ch4/dedup/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 96. 5 | 6 | // Dedup prints only one instance of each line; duplicates are removed. 7 | package main 8 | 9 | import ( 10 | "bufio" 11 | "fmt" 12 | "os" 13 | ) 14 | 15 | //!+ 16 | func main() { 17 | seen := make(map[string]bool) // a set of strings 18 | input := bufio.NewScanner(os.Stdin) 19 | for input.Scan() { 20 | line := input.Text() 21 | if !seen[line] { 22 | seen[line] = true 23 | fmt.Println(line) 24 | } 25 | } 26 | 27 | if err := input.Err(); err != nil { 28 | fmt.Fprintf(os.Stderr, "dedup: %v\n", err) 29 | os.Exit(1) 30 | } 31 | } 32 | 33 | //!- 34 | -------------------------------------------------------------------------------- /gop_homework/ch4/embed/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 106. 5 | 6 | // Embed demonstrates basic struct embedding. 7 | package main 8 | 9 | import "fmt" 10 | 11 | type Point struct{ X, Y int } 12 | 13 | type Circle struct { 14 | Point 15 | Radius int 16 | } 17 | 18 | type Wheel struct { 19 | Circle 20 | Spokes int 21 | } 22 | 23 | func main() { 24 | var w Wheel 25 | //!+ 26 | w = Wheel{Circle{Point{8, 8}, 5}, 20} 27 | 28 | w = Wheel{ 29 | Circle: Circle{ 30 | Point: Point{X: 8, Y: 8}, 31 | Radius: 5, 32 | }, 33 | Spokes: 20, // NOTE: trailing comma necessary here (and at Radius) 34 | } 35 | 36 | fmt.Printf("%#v\n", w) 37 | // Output: 38 | // Wheel{Circle:Circle{Point:Point{X:8, Y:8}, Radius:5}, Spokes:20} 39 | 40 | w.X = 42 41 | 42 | fmt.Printf("%#v\n", w) 43 | // Output: 44 | // Wheel{Circle:Circle{Point:Point{X:42, Y:8}, Radius:5}, Spokes:20} 45 | //!- 46 | } 47 | -------------------------------------------------------------------------------- /gop_homework/ch4/github/github.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 110. 5 | //!+ 6 | 7 | // Package github provides a Go API for the GitHub issue tracker. 8 | // See https://developer.github.com/v3/search/#search-issues. 9 | package github 10 | 11 | import "time" 12 | 13 | const IssuesURL = "https://api.github.com/search/issues" 14 | 15 | type IssuesSearchResult struct { 16 | TotalCount int `json:"total_count"` 17 | Items []*Issue 18 | } 19 | 20 | type Issue struct { 21 | Number int 22 | HTMLURL string `json:"html_url"` 23 | Title string 24 | State string 25 | User *User 26 | CreatedAt time.Time `json:"created_at"` 27 | Body string // in Markdown format 28 | } 29 | 30 | type User struct { 31 | Login string 32 | HTMLURL string `json:"html_url"` 33 | } 34 | 35 | //!- 36 | -------------------------------------------------------------------------------- /gop_homework/ch4/homework/test4.1/main.go: -------------------------------------------------------------------------------- 1 | //练习 4.1: 编写一个函数,计算两个SHA256哈希码中不同bit的数目。(参考2.6.2节的PopCount函数。) 2 | package main 3 | 4 | import ( 5 | "crypto/sha256" 6 | "fmt" 7 | ) 8 | 9 | func main() { 10 | sha1 := sha256.Sum256([]byte("11!")) 11 | sha2 := sha256.Sum256([]byte("111")) 12 | fmt.Println(sha1, sha2) 13 | n := SHA256Count(sha1, sha2) 14 | fmt.Println("不同的书目是:", n) 15 | 16 | } 17 | 18 | func SHA256Count(shaOne, shaTwo [32]byte) int { 19 | var y int 20 | for i := 0; i < len(shaOne); i++ { 21 | if shaTwo[i] != shaOne[i] { 22 | y++ 23 | } 24 | 25 | } 26 | return y 27 | } 28 | 29 | //[239 24 195 39 99 227 251 83 234 251 33 179 214 1 0 204 157 56 234 173 153 111 111 96 115 170 3 222 250 121 221 174] [246 224 161 226 172 65 148 90 154 167 255 138 138 170 12 235 193 42 59 204 152 26 146 154 213 207 129 10 9 14 17 174] 30 | //不同的书目是: 31 31 | // 一般情况下都是 全部不一样,好不容易有个31的。 32 | -------------------------------------------------------------------------------- /gop_homework/ch4/homework/test4.13/text.md: -------------------------------------------------------------------------------- 1 | text.png 2 | ![text.png](./text.png) -------------------------------------------------------------------------------- /gop_homework/ch4/homework/test4.13/text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/gop_homework/ch4/homework/test4.13/text.png -------------------------------------------------------------------------------- /gop_homework/ch4/homework/test4.14/2.html: -------------------------------------------------------------------------------- 1 | 2 | {{define "transfer_1"}} 3 | 4 |
    5 | 6 |
    7 | 8 |
    9 | {{end}} 10 | -------------------------------------------------------------------------------- /gop_homework/ch4/homework/test4.14/alipay.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/gop_homework/ch4/homework/test4.14/alipay.jpeg -------------------------------------------------------------------------------- /gop_homework/ch4/homework/test4.14/alipay1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/gop_homework/ch4/homework/test4.14/alipay1.jpeg -------------------------------------------------------------------------------- /gop_homework/ch4/homework/test4.14/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/gop_homework/ch4/homework/test4.14/favicon.ico -------------------------------------------------------------------------------- /gop_homework/ch4/homework/test4.14/transfer/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func main(){ 6 | 7 | http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) { 8 | http.Redirect(writer,request,"https://coastroad.net",http.StatusMovedPermanently) 9 | }) 10 | http.ListenAndServe(":80",nil) 11 | } 12 | -------------------------------------------------------------------------------- /gop_homework/ch4/homework/test4.14/wechat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/gop_homework/ch4/homework/test4.14/wechat.png -------------------------------------------------------------------------------- /gop_homework/ch4/homework/test4.14/wechat1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/gop_homework/ch4/homework/test4.14/wechat1.png -------------------------------------------------------------------------------- /gop_homework/ch4/homework/test4.2/main.go: -------------------------------------------------------------------------------- 1 | //练习 4.2: 编写一个程序,默认情况下打印标准输入的SHA256编码,并支持通过命令行flag定制,输出SHA384或SHA512哈希算法。 2 | package main 3 | 4 | import ( 5 | "crypto/sha512" 6 | "fmt" 7 | "os" 8 | ) 9 | 10 | func main(){ 11 | for _,v := range os.Args[1:] { 12 | t := sha512.New().Sum([]byte(v)) 13 | fmt.Println(t) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /gop_homework/ch4/homework/test4.3/main.go: -------------------------------------------------------------------------------- 1 | //练习 4.3: 重写reverse函数,使用数组指针代替slice。 2 | package main 3 | 4 | import "fmt" 5 | 6 | func reverse1(s [5]int) { // 这么写的时候 s 已经是复制值了,所以失败。 7 | st := &s 8 | for i, j := 0, len(*st)-1; i < j; i, j = i+1, j-1 { 9 | (*st)[i], (*st)[j] = (*st)[j], (*st)[i] 10 | //fmt.Println(*st) 11 | } 12 | } 13 | 14 | func reverse2(s *[5]int) { 15 | for i, j := 0, len(*s)-1; i < j; i, j = i+1, j-1 { 16 | (*s)[i], (*s)[j] = (*s)[j], (*s)[i] 17 | 18 | } 19 | } 20 | func main() { 21 | t := [5]int{1, 443, 223, 2, 0} 22 | reverse1(t) 23 | fmt.Println(t) 24 | reverse2(&t) 25 | fmt.Println(t) 26 | } 27 | -------------------------------------------------------------------------------- /gop_homework/ch4/homework/test4.4/main.go: -------------------------------------------------------------------------------- 1 | //练习 4.4: 编写一个rotate函数,通过一次循环完成旋转。 2 | package main 3 | 4 | func rotate(sli []int){ 5 | 6 | } 7 | 8 | -------------------------------------------------------------------------------- /gop_homework/ch4/homework/test4.5/main.go: -------------------------------------------------------------------------------- 1 | //练习 4.5: 写一个函数在原地完成消除[]string中相邻重复的字符串的操作。 2 | package main 3 | 4 | //pass 转换为 []byte 即可。 5 | -------------------------------------------------------------------------------- /gop_homework/ch4/homework/test4.6/main.go: -------------------------------------------------------------------------------- 1 | //练习 4.6: 编写一个函数,原地将一个UTF-8编码的[]byte类型的slice中相邻的空格(参考unicode.IsSpace)替换成一个空格返回 2 | package main 3 | 4 | import ( 5 | "fmt" 6 | "unicode" 7 | ) 8 | 9 | func main() { 10 | s := "2 49 d 2" 11 | st := []rune(s) 12 | result := make([]rune,0) 13 | for i := 0; i < len(st); i++{ 14 | 15 | if i +1 >= len(st) { 16 | result = append(result,st[i]) 17 | break 18 | } 19 | if !unicode.IsSpace(st[i]){ 20 | result = append(result,st[i]) 21 | } 22 | if unicode.IsSpace(st[i]) && !unicode.IsSpace(st[i+1]) { 23 | result = append(result,st[i]) 24 | } 25 | } 26 | fmt.Println(string(result)) 27 | 28 | } 29 | 30 | 31 | -------------------------------------------------------------------------------- /gop_homework/ch4/homework/test4.8/main.go: -------------------------------------------------------------------------------- 1 | //练习 4.8: 修改charcount程序,使用unicode.IsLetter等相关的函数,统计字母、数字等Unicode中不同的字符类别。 2 | package main 3 | 4 | -------------------------------------------------------------------------------- /gop_homework/ch4/homework/test4.9/main.go: -------------------------------------------------------------------------------- 1 | //练习 4.9: 编写一个程序wordfreq程序,报告输入文本中每个单词出现的频率。 2 | // 在第一次调用Scan前先调用input.Split(bufio.ScanWords)函数,这样可以按单词而不是按行输入。 3 | package main 4 | 5 | import ( 6 | "bufio" 7 | "fmt" 8 | "os" 9 | "sort" 10 | ) 11 | 12 | func wordfreq() { 13 | testMao := make(map[string]int) 14 | file, err := os.Open("./tt.txt") 15 | fmt.Println(err) 16 | input := bufio.NewScanner(file) 17 | input.Split(bufio.ScanWords) 18 | for input.Scan() { 19 | testMao[input.Text()]++ 20 | } 21 | paixu(testMao) 22 | //for k, v := range testMao { 23 | // fmt.Println(len(testMao)) 24 | // fmt.Printf("%s: %% %.3f", k, float32(v*100/len(testMao))) 25 | //} 26 | 27 | } 28 | 29 | func main() { 30 | wordfreq() 31 | } 32 | 33 | func paixu(sr map[string]int) { 34 | result := make([]int, 0) 35 | for _,v := range sr { 36 | result = append(result, v) 37 | } 38 | sort.Ints(result) 39 | for _, v := range result { 40 | fmt.Println(v) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /gop_homework/ch4/homework/test4.9/test4.9: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/gop_homework/ch4/homework/test4.9/test4.9 -------------------------------------------------------------------------------- /gop_homework/ch4/sha256/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 83. 5 | 6 | // The sha256 command computes the SHA256 hash (an array) of a string. 7 | package main 8 | 9 | import "fmt" 10 | 11 | //!+ 12 | import "crypto/sha256" 13 | 14 | func main() { 15 | c1 := sha256.Sum256([]byte("x")) 16 | c2 := sha256.Sum256([]byte("X")) 17 | fmt.Printf("%x\n%x\n%t\n%T\n", c1, c2, c1 == c2, c1) 18 | // Output: 19 | // 2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881 20 | // 4b68ab3847feda7d6c62c1fbcbeebfa35eab7351ed5e78f4ddadea5df64b8015 21 | // false 22 | // [32]uint8 23 | } 24 | 25 | //!- 26 | -------------------------------------------------------------------------------- /gop_homework/ch4/treesort/sort_test.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package treesort_test 5 | 6 | import ( 7 | "math/rand" 8 | "sort" 9 | "testing" 10 | 11 | "gopl.io/ch4/treesort" 12 | ) 13 | 14 | func TestSort(t *testing.T) { 15 | data := make([]int, 50) 16 | for i := range data { 17 | data[i] = rand.Int() % 50 18 | } 19 | treesort.Sort(data) 20 | if !sort.IntsAreSorted(data) { 21 | t.Errorf("not sorted: %v", data) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /gop_homework/ch5/defer1/defer.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 150. 5 | 6 | // Defer1 demonstrates a deferred call being invoked during a panic. 7 | package main 8 | 9 | import "fmt" 10 | 11 | //!+f 12 | func main() { 13 | f(3) 14 | } 15 | 16 | func f(x int) { 17 | fmt.Printf("f(%d)\n", x+0/x) // panics if x == 0 18 | defer fmt.Printf("defer %d\n", x) 19 | f(x - 1) 20 | } 21 | 22 | //!-f 23 | 24 | /* 25 | //!+stdout 26 | f(3) 27 | f(2) 28 | f(1) 29 | defer 1 30 | defer 2 31 | defer 3 32 | //!-stdout 33 | 34 | //!+stderr 35 | panic: runtime error: integer divide by zero 36 | main.f(0) 37 | src/gopl.io/ch5/defer1/defer.go:14 38 | main.f(1) 39 | src/gopl.io/ch5/defer1/defer.go:16 40 | main.f(2) 41 | src/gopl.io/ch5/defer1/defer.go:16 42 | 43 | main.f(3) 44 | src/gopl.io/ch5/defer1/defer.go:16 45 | main.main() 46 | src/gopl.io/ch5/defer1/defer.go:10 47 | //!-stderr 48 | */ 49 | -------------------------------------------------------------------------------- /gop_homework/ch5/homework/test5.1/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "testing" 4 | 5 | func BenchmarkT6(b *testing.B) { 6 | for i := 0; i < b.N; i++ { 7 | t6() 8 | } 9 | } -------------------------------------------------------------------------------- /gop_homework/ch5/homework/test5.11/main.go: -------------------------------------------------------------------------------- 1 | //练习5.11: 现在线性代数的老师把微积分设为了前置课程。完善topSort,使其能检测有向图中的环。 2 | package main 3 | 4 | // 本部分需要稍微研究久一点,暂时搁置。todo 研究拓扑排序和深度排序以及广度排序。较为复杂。 5 | 6 | -------------------------------------------------------------------------------- /gop_homework/ch5/homework/test5.13/main.go: -------------------------------------------------------------------------------- 1 | //练习5.13: 修改crawl,使其能保存发现的页面,必要时, 2 | // 可以创建目录来保存这些页面。只保存来自原始域名下的页面。 3 | // 假设初始页面在golang.org下,就不要保存vimeo.com下的页面。 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "gopl.io/ch5/links" 9 | "log" 10 | "regexp" 11 | "strings" 12 | ) 13 | 14 | var ( 15 | url string = "https://coastroad.net" 16 | ) 17 | 18 | var p map[string]string 19 | 20 | func crawl(url string) []string { 21 | fmt.Println(url) 22 | list, err := links.Extract(url) 23 | if err != nil { 24 | log.Print(err) 25 | } 26 | re := regexp.MustCompile("^http://|^https://") 27 | for k, v := range list { 28 | list[k] = strings.Replace(v, url, "", 1) 29 | if re.MatchString(list[k]) { 30 | list[k] = "" 31 | } 32 | } 33 | return list 34 | } 35 | 36 | func main() { 37 | p := make(map[string]string) 38 | for _, v := range crawl(url) { 39 | if v != "" { 40 | p[v] = url + v 41 | } 42 | } 43 | fmt.Println(p) 44 | } 45 | -------------------------------------------------------------------------------- /gop_homework/ch5/homework/test5.14/main.go: -------------------------------------------------------------------------------- 1 | //练习5.14: 使用breadthFirst遍历其他数据结构。 2 | // 比如,topoSort例子中的课程依赖关系(有向图), 3 | // 个人计算机的文件层次结构(树),你所在城市的公交或地铁线路(无向图)。 4 | package main 5 | 6 | import "fmt" 7 | 8 | func breadthFirst(f func(item string) []string, worklist *[]string) { 9 | seen := make(map[string]bool) 10 | for len(*worklist) > 0 { 11 | items := *worklist 12 | for _, item := range items { 13 | if !seen[item] { 14 | seen[item] = true 15 | fmt.Println(f(item)) 16 | fmt.Println(*worklist) 17 | *worklist = append(*worklist, f(item)...) 18 | } 19 | } 20 | } 21 | } 22 | 23 | func main() { 24 | worklist := make([]string, 0) 25 | worklist = []string{ 26 | "12345", 27 | "12343423323", 28 | "12324354trgfdwfwq", 29 | "3454rdfwetrewdf", 30 | } 31 | breadthFirst(func(item string) []string { 32 | return []string{"12"} 33 | }, &worklist) 34 | fmt.Println(worklist) 35 | } 36 | -------------------------------------------------------------------------------- /gop_homework/ch5/homework/test5.15/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "testing" 4 | 5 | func Testmax(t *testing.T) { 6 | if max(1, 2, 3, 4, 5) != 5 { 7 | t.Error("测试结果错误最大值寻找失败,max函数编写异常") 8 | } else { 9 | t.Log("测试结果成功,测试max函数结果正确") 10 | } 11 | } 12 | 13 | func TestMin(t *testing.T) { 14 | if min(1, 2, 3, 4, 5) != 1 { 15 | t.Error("测试结果失败,寻找最小值错误min函数编写异常") 16 | } else { 17 | t.Log("测试结果成功,寻找最小值min函数编程正确") 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /gop_homework/ch5/homework/test5.16/main.go: -------------------------------------------------------------------------------- 1 | //练习5.16:编写多参数版本的strings.Join。 2 | package main 3 | 4 | import ( 5 | "bytes" 6 | "fmt" 7 | ) 8 | 9 | func Join(a []string, sep ...string) string { 10 | var bu bytes.Buffer 11 | for _, v := range sep { 12 | bu.WriteString(v) // 往缓存中写入数据 13 | } 14 | return bu.String() // 提取出数据。 15 | } 16 | func main() { 17 | fmt.Println(Join(nil, "12", "33", "323", "233232")) 18 | } 19 | -------------------------------------------------------------------------------- /gop_homework/ch5/homework/test5.16/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func BenchmarkJoin(b *testing.B) { 8 | for i := 0; i < b.N; i++ { 9 | Join([]string{"1","2","3","4"},"1","2","23","234343","2334","233323") 10 | } 11 | } 12 | 13 | 14 | // 为了实现同样的效果 strings.Join 必须这么写,那么就会变得很慢。但是自定义的Join并不会这样。 15 | 16 | // 17 | //go test -bench=. -cpu=4 18 | //goos: darwin 19 | //goarch: amd64 20 | //pkg: github.com/googege/gopl_homework/ch5/homework/test5.16 21 | //BenchmarkJoin-4 10000000 196 ns/op 22 | //BenchmarkGoJoin-4 2000000 707 ns/op 23 | //PASS 24 | //ok github.com/googege/gopl_homework/ch5/homework/test5.16 4.293s -------------------------------------------------------------------------------- /gop_homework/ch5/homework/test5.19/main.go: -------------------------------------------------------------------------------- 1 | //练习5.19: 使用panic和recover编写一个不包含return语句但能返回一个非零值的函数。 2 | package main 3 | 4 | import "fmt" 5 | 6 | func tt(){ 7 | defer func() { 8 | if e := recover();e != nil { 9 | fmt.Println(e) 10 | } 11 | }() 12 | dd() 13 | } 14 | 15 | 16 | func dd(){ 17 | panic("12") 18 | } 19 | 20 | func main(){ 21 | tt() 22 | } -------------------------------------------------------------------------------- /gop_homework/ch5/homework/test5.2/main.go: -------------------------------------------------------------------------------- 1 | //练习 5.2: 编写函数,记录在HTML树中出现的同名元素的次数。 2 | package main 3 | 4 | import ( 5 | "fmt" 6 | "golang.org/x/net/html" 7 | "io/ioutil" 8 | "net/http" 9 | "strings" 10 | ) 11 | 12 | func main() { 13 | lin := make(map[string]int) 14 | res, err := http.Get("http://www.haust.edu.cn") 15 | if err != nil { 16 | fmt.Println("打印main函数中的错误err", err) 17 | } 18 | d, err := ioutil.ReadAll(res.Body) 19 | if err != nil { 20 | fmt.Println("err", err) 21 | } 22 | read := strings.NewReader(string(d)) 23 | node, err := html.Parse(read) 24 | if err != nil { 25 | fmt.Println(err) 26 | } 27 | dataMap := visit(lin, node) 28 | for k,v := range dataMap { 29 | fmt.Println(k,": ",v) 30 | } 31 | res.Body.Close() 32 | } 33 | 34 | func visit(s map[string]int, n *html.Node) map[string]int { 35 | if n.Type == html.ElementNode {// 出错 36 | s[n.Data]++ 37 | } 38 | for i := n.FirstChild; i != nil; i = i.NextSibling { 39 | s = visit(s, i) 40 | } 41 | return s 42 | } 43 | -------------------------------------------------------------------------------- /gop_homework/ch5/homework/test5.5/data.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | var urls = []string{ 4 | "https://coastroad.net", 5 | "https://facebook.com", 6 | "https://google.com", 7 | "https://github.com", 8 | "http://haust.edu.cn", 9 | "https://www.qq.com", 10 | "https://qlcoud.tencent.com", 11 | "https://app.cloudcone.com", 12 | "https://baidu.com", 13 | "https://youtube.com", 14 | "https://youku.com", 15 | "http://tudou.com", 16 | "https://pornhub.com", 17 | "https://xvideos.com", 18 | "https://www.taobao.com", 19 | "https://www.tmall.com", 20 | "https://apple.com", 21 | "https://volvocar.com", 22 | "https://bmw.com", 23 | "https://bilibili.com", 24 | "https://lynkco.com.cn", 25 | "https://zhihu.com", 26 | "https://www.porsche.com", 27 | "https://instagram.com", 28 | "https://www.usa.gov/", 29 | "https://www.whitehouse.gov/", 30 | "https://www.nike.com", 31 | "https://adidas.com", 32 | "https://kapa.com", 33 | "https://www.converse.com/us/en_us/c/converse", 34 | } 35 | -------------------------------------------------------------------------------- /gop_homework/ch5/homework/test5.5/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "testing" 4 | 5 | func BenchmarkSync(b *testing.B) { 6 | for i := 0; i < b.N; i++ { 7 | Recover() 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /gop_homework/ch5/homework/test5.7/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "testing" 4 | 5 | func TestOutLine(t *testing.T) { 6 | 7 | err := outline("https:coastroad.net") 8 | if err != nil { 9 | t.Error(err) 10 | } 11 | } 12 | 13 | //--- FAIL: TestOutLine (0.00s) 14 | // main_test.go:9: Get https:coastroad.net: http: no Host in request URL 15 | //FAIL 16 | //exit status 1 17 | //FAIL github.com/googege/gopl_homework/ch5/homework/test5.7 0.019s 18 | -------------------------------------------------------------------------------- /gop_homework/ch5/homework/test5.9/main.go: -------------------------------------------------------------------------------- 1 | //练习 5.9: 编写函数expand,将s中的"foo"替换为f("foo")的返回值。 2 | package main 3 | 4 | import "fmt" 5 | 6 | func expand(s string, f func(string) string) string { 7 | return f(s) 8 | } 9 | 10 | func main() { 11 | s := expand("12", func(s string) string { 12 | s += "." 13 | return s 14 | }) 15 | fmt.Println(s) 16 | } 17 | -------------------------------------------------------------------------------- /gop_homework/ch5/outline/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 123. 5 | 6 | // Outline prints the outline of an HTML document tree. 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | "os" 12 | 13 | "golang.org/x/net/html" 14 | ) 15 | 16 | //!+ 17 | func main() { 18 | doc, err := html.Parse(os.Stdin) 19 | if err != nil { 20 | fmt.Fprintf(os.Stderr, "outline: %v\n", err) 21 | os.Exit(1) 22 | } 23 | outline(nil, doc) 24 | } 25 | 26 | func outline(stack []string, n *html.Node) { 27 | if n.Type == html.ElementNode { 28 | stack = append(stack, n.Data) // push tag 29 | fmt.Println(stack) 30 | } 31 | for c := n.FirstChild; c != nil; c = c.NextSibling { 32 | outline(stack, c) 33 | } 34 | } 35 | 36 | //!- 37 | -------------------------------------------------------------------------------- /gop_homework/ch5/squares/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 135. 5 | 6 | // The squares program demonstrates a function value with state. 7 | package main 8 | 9 | import "fmt" 10 | 11 | //!+ 12 | // squares returns a function that returns 13 | // the next square number each time it is called. 14 | func squares() func() int { 15 | var x int 16 | return func() int { 17 | x++ 18 | return x * x 19 | } 20 | } 21 | 22 | func main() { 23 | f := squares() 24 | fmt.Println(f()) // "1" 25 | fmt.Println(f()) // "4" 26 | fmt.Println(f()) // "9" 27 | fmt.Println(f()) // "16" 28 | } 29 | 30 | //!- 31 | -------------------------------------------------------------------------------- /gop_homework/ch5/sum/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 142. 5 | 6 | // The sum program demonstrates a variadic function. 7 | package main 8 | 9 | import "fmt" 10 | 11 | //!+ 12 | func sum(vals ...int) int { 13 | total := 0 14 | for _, val := range vals { 15 | total += val 16 | } 17 | return total 18 | } 19 | 20 | //!- 21 | 22 | func main() { 23 | //!+main 24 | fmt.Println(sum()) // "0" 25 | fmt.Println(sum(3)) // "3" 26 | fmt.Println(sum(1, 2, 3, 4)) // "10" 27 | //!-main 28 | 29 | //!+slice 30 | values := []int{1, 2, 3, 4} 31 | fmt.Println(sum(values...)) // "10" 32 | //!-slice 33 | } 34 | -------------------------------------------------------------------------------- /gop_homework/ch5/trace/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 146. 5 | 6 | // The trace program uses defer to add entry/exit diagnostics to a function. 7 | package main 8 | 9 | import ( 10 | "log" 11 | "time" 12 | ) 13 | 14 | //!+main 15 | func bigSlowOperation() { 16 | defer trace("bigSlowOperation")() // don't forget the extra parentheses 17 | // ...lots of work... 18 | time.Sleep(10 * time.Second) // simulate slow operation by sleeping 19 | } 20 | 21 | func trace(msg string) func() { 22 | start := time.Now() 23 | log.Printf("enter %s", msg) 24 | return func() { log.Printf("exit %s (%s)", msg, time.Since(start)) } 25 | } 26 | 27 | //!-main 28 | 29 | func main() { 30 | bigSlowOperation() 31 | } 32 | 33 | /* 34 | !+output 35 | $ go build gopl.io/ch5/trace 36 | $ ./trace 37 | 2015/11/18 09:53:26 enter bigSlowOperation 38 | 2015/11/18 09:53:36 exit bigSlowOperation (10.000589217s) 39 | !-output 40 | */ 41 | -------------------------------------------------------------------------------- /gop_homework/ch6/homework/test6.1/main.go: -------------------------------------------------------------------------------- 1 | //练习6.1: 为bit数组实现下面这些方法 2 | // 3 | //func (*IntSet) Len() int // return the number of elements 4 | //func (*IntSet) Remove(x int) // remove x from the set 5 | //func (*IntSet) Clear() // remove all elements from the set 6 | //func (*IntSet) Copy() *IntSet // return a copy of the set 7 | package main 8 | 9 | type IntSet struct { 10 | words []uint64 // bit 数组。 11 | } 12 | 13 | func (i *IntSet) Len() int { 14 | return len(i.words) 15 | } 16 | 17 | func (i *IntSet) Remove(x int) { 18 | if i.Len() <= x { 19 | return 20 | } 21 | i.words = append(i.words[:x], i.words[x+1:]...) 22 | } 23 | func (i *IntSet) Clear() { 24 | i.words = make([]uint64, 0) 25 | } 26 | func (i *IntSet) Copy() *IntSet { 27 | t := *i // 取得实际值的复制值 28 | return &t //然后把这个复制的值的地址给返回。 29 | } 30 | -------------------------------------------------------------------------------- /gop_homework/ch6/homework/test6.1/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestAll(t *testing.T) { 9 | i := &IntSet{ 10 | []uint64{ 11 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12 | }, 13 | } 14 | fmt.Println("开始测试len函数,正确答案应该是10") 15 | fmt.Println(i.Len()) 16 | fmt.Println("Copy函数,正确答案应该是&{[]uint64{1,2,3,4,5,6,7,8,9,10,}}") 17 | fmt.Println(i.Copy()) 18 | fmt.Println("开始测试Remove函数,正确答案应该是{1,3,4,5,6,7,8,9,10}") 19 | i.Remove(1) 20 | fmt.Println(i.words) 21 | fmt.Println("开始测试clear函数,正确答案是:[]") 22 | i.Clear() 23 | fmt.Println(i.words) 24 | } 25 | 26 | func BenchmarkAll(b *testing.B) { 27 | for i := 0; i < b.N; i++ { 28 | i := &IntSet{ 29 | []uint64{ 30 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 31 | }, 32 | } 33 | i.Len() 34 | i.Remove(1) 35 | i.Copy() 36 | i.Clear() 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /gop_homework/ch6/homework/test6.2/main.go: -------------------------------------------------------------------------------- 1 | //练习 6.2: 定义一个变参方法(*IntSet).AddAll(...int),这个方法可以添加一组IntSet,比如s.AddAll(1,2,3)。 2 | package main 3 | 4 | type IntSet struct { 5 | words []uint64 6 | } 7 | 8 | func (i *IntSet) AddAll(sep ...int) { 9 | for _, v := range sep { 10 | i.Add(v) 11 | } 12 | } 13 | func (s *IntSet) Add(x int) { 14 | word, bit := x/64, uint(x%64) 15 | for word >= len(s.words) { 16 | s.words = append(s.words, 0) 17 | } 18 | s.words[word] |= 1 << bit 19 | } 20 | -------------------------------------------------------------------------------- /gop_homework/ch6/homework/test6.4/main.go: -------------------------------------------------------------------------------- 1 | //*练习6.4: 实现一个Elems方法,返回集合中的所有元素,用于做一些range之类的遍历操作。 2 | package main 3 | 4 | type IntSet struct { 5 | Words []uint64 6 | } 7 | 8 | //Elems method. 9 | func (s *IntSet) Elems() []uint64 { 10 | result := make([]uint64, 0) 11 | for _, v := range s.Words { 12 | result = append(result, v) 13 | } 14 | return result 15 | } 16 | -------------------------------------------------------------------------------- /gop_homework/ch6/homework/test6.5/main.go: -------------------------------------------------------------------------------- 1 | //练习 6.5: 我们这章定义的IntSet里的每个字都是用的uint64类型,但是64位的数值可能在32位的平台上不高效。 2 | // 修改程序,使其使用uint类型,这种类型对于32位平台来说更合适。当然了,这里我们可以不用简单粗暴地除64, 3 | // 可以定义一个常量来决定是用32还是64,这里你可能会用到平台的自动判断的一个智能表达式:32 << (^uint(0) >> 63) 4 | package main 5 | 6 | const IS64 = 32 << (^uint(0) >> 63) // 判断是否是64位平台。// 这样就可以照顾是32和64位系统了。 7 | 8 | type IntSet struct { 9 | words []uint// 这样就可以照顾是32和64位系统了。 10 | } 11 | 12 | func (s *IntSet) Add(x int) { 13 | word, bit := x/IS64, uint(x%IS64)// 这样就可以照顾是32和64位系统了。 14 | for word >= len(s.words) { 15 | s.words = append(s.words, 0) 16 | } 17 | s.words[word] |= 1 << bit 18 | } 19 | 20 | // 没有后缀的 uint 就是指最少是32 它会根据系统选择 32或者是64 那么该除以几呢?使用32 << (^uint(0) >> 63) 即可判断。 -------------------------------------------------------------------------------- /gop_homework/ch7/bytecounter/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 173. 5 | 6 | // Bytecounter demonstrates an implementation of io.Writer that counts bytes. 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | ) 12 | 13 | //!+bytecounter 14 | 15 | type ByteCounter int 16 | 17 | func (c *ByteCounter) Write(p []byte) (int, error) { 18 | *c += ByteCounter(len(p)) // convert int to ByteCounter 19 | return len(p), nil 20 | } 21 | 22 | //!-bytecounter 23 | 24 | func main() { 25 | //!+main 26 | var c ByteCounter 27 | c.Write([]byte("hello")) 28 | fmt.Println(c) // "5", = len("hello") 29 | 30 | c = 0 // reset the counter 31 | var name = "Dolly" 32 | fmt.Fprintf(&c, "hello, %s", name) 33 | fmt.Println(c) // "12", = len("hello, Dolly") 34 | //!-main 35 | } 36 | -------------------------------------------------------------------------------- /gop_homework/ch7/homework/test7.1/main.go: -------------------------------------------------------------------------------- 1 | //练习 7.1: 使用来自ByteCounter的思路,实现一个针对对单词和行数的计数器。你会发现bufio.ScanWords非常的有用。 2 | package main 3 | 4 | import ( 5 | "bufio" 6 | "fmt" 7 | "io" 8 | "os" 9 | ) 10 | 11 | func main() { 12 | fmt.Println(T()) 13 | } 14 | func T() int { 15 | var d int 16 | var t = func() { 17 | d++ 18 | } 19 | scan := bufio.NewScanner(os.Stdin) 20 | scan.Split(bufio.ScanWords) // bufio.ScanWords 等这些函数符合SplitFunc函数的特征,那么就是符合这个类型。 21 | 22 | for { 23 | if scan.Scan() { 24 | fmt.Println(scan.Text()) 25 | t() 26 | 27 | } 28 | if scan.Err() == io.EOF { 29 | break 30 | } 31 | if scan.Text() == "Q" { 32 | break 33 | } 34 | } 35 | // 36 | return d 37 | } 38 | -------------------------------------------------------------------------------- /gop_homework/ch7/homework/test7.10/main.go: -------------------------------------------------------------------------------- 1 | //练习 7.10: sort.Interface类型也可以适用在其它地方。编写一个IsPalindrome(s sort.Interface) bool 2 | // 函数表明序列s是否是回文序列,换句话说反向排序不会改变这个序列。 3 | // 假设如果!s.Less(i, j) && !s.Less(j, i)则索引i和j上的元素相等。 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "sort" 9 | ) 10 | 11 | // 函数应该只使用接口,然后行使基础权利。然后传入动态实际值,这样就可以实施真实值了。 12 | func IsPalindrome(s sort.Interface, i int, j int) bool { 13 | if !s.Less(i, j) && !s.Less(j, i) { 14 | fmt.Println("则索引i和j上的元素相等") 15 | return true 16 | 17 | } 18 | return false 19 | } 20 | -------------------------------------------------------------------------------- /gop_homework/ch7/homework/test7.12/main.go: -------------------------------------------------------------------------------- 1 | //练习 7.12: 修改/list的handler让它把输出打印成一个HTML的表格而不是文本。html/template包(§4.6)可能会对你有帮助。 2 | package main 3 | 4 | import ( 5 | "fmt" 6 | "go/types" 7 | "html/template" 8 | "net/http" 9 | ) 10 | 11 | type database int 12 | func (db database) ServeHTTP(w http.ResponseWriter, req *http.Request) { 13 | switch req.URL.Path { 14 | case "/list": 15 | v := ` 16 | 17 | {{$name,$dd := range .}} 18 | $name 19 | {{end}} 20 |
    $dd
    21 | 22 | ` 23 | t,_ := template.New("name").Parse(v) 24 | t.Execute(w,db) 25 | case "/price": 26 | item := req.URL.Query().Get("item") 27 | price, ok := db[item] 28 | if !ok { 29 | w.WriteHeader(http.StatusNotFound) // 404 30 | fmt.Fprintf(w, "no such item: %q\n", item) 31 | return 32 | } 33 | fmt.Fprintf(w, "%s\n", price) 34 | default: 35 | w.WriteHeader(http.StatusNotFound) // 404 36 | fmt.Fprintf(w, "no such page: %s\n", req.URL) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /gop_homework/ch7/homework/test7.13/main.go: -------------------------------------------------------------------------------- 1 | //练习 7.13: 为Expr增加一个String方法来打印美观的语法树。当再一次解析的时候,检查它的结果是否生成相同的语法树。 2 | package main 3 | 4 | import "fmt" 5 | 6 | type Expr interface { 7 | fmt.Stringer 8 | } 9 | -------------------------------------------------------------------------------- /gop_homework/ch7/homework/test7.14/main.go: -------------------------------------------------------------------------------- 1 | //练习 7.14: 定义一个新的满足Expr接口的具体类型并且提供一个新的操作例如对它运算单元中的最小值的计算。 2 | // 因为Parse函数不会创建这个新类型的实例,为了使用它你可能需要直接构造一个语法树(或者继承parser接口)。 3 | package main 4 | 5 | 6 | func main(){ 7 | 8 | } 9 | 10 | 11 | type str struct { 12 | 13 | } 14 | 15 | func(s *str)Eval(env Env) float64 { 16 | return 1.0 17 | } 18 | 19 | func(s *str)Check(vars map[Var]bool) error{ 20 | return nil 21 | } -------------------------------------------------------------------------------- /gop_homework/ch7/homework/test7.15/main.go: -------------------------------------------------------------------------------- 1 | //练习 7.15: 编写一个从标准输入中读取一个单一表达式的程序,用户及时地提供对于任意变量的值, 2 | // 然后在结果环境变量中计算表达式的值。优雅的处理所有遇到的错误。 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "io/ioutil" 8 | "os" 9 | ) 10 | 11 | func main(){ 12 | data,err := ioutil.ReadAll(os.Stdin) 13 | if err != nil { 14 | fmt.Println(err) 15 | } 16 | fmt.Println(data) 17 | //这个练习是什么鬼意思? 18 | } 19 | 20 | -------------------------------------------------------------------------------- /gop_homework/ch7/homework/test7.18/main.go: -------------------------------------------------------------------------------- 1 | //练习 7.18: 使用基于标记的解码API,编写一个可以读取任意XML文档和构造这个文档所代表的普通节点树的程序。 2 | // 节点有两种类型:CharData节点表示文本字符串,和 Element节点表示被命名的元素和它们的属性。每一个元素节点有一个字节点的切片。 3 | package main 4 | 5 | import ( 6 | "encoding/xml" 7 | ) 8 | 9 | type Node interface{} // CharData or *Element 10 | 11 | type CharData string 12 | 13 | type Element struct { 14 | Type xml.Name // 节点名称 15 | Attr []xml.Attr// 节点属性 16 | Children []Node// 子节点。 17 | } 18 | 19 | -------------------------------------------------------------------------------- /gop_homework/ch7/homework/test7.2/main.go: -------------------------------------------------------------------------------- 1 | //练习 7.2: 写一个带有如下函数签名的函数CountingWriter,传入一个io.Writer接口类型, 2 | // 返回一个新的Writer类型把原来的Writer封装在里面和一个表示写入新的Writer字节数的int64类型指针 3 | // 4 | //func CountingWriter(w io.Writer) (io.Writer, *int64) 5 | package main 6 | 7 | import ( 8 | "fmt" 9 | "io" 10 | ) 11 | 12 | func ContingWriter(w io.Writer, p []byte) (io.Writer, *int64) { 13 | n, err := w.Write(p) 14 | if err != nil { 15 | fmt.Println(err) 16 | } 17 | a := int64(n) 18 | return w, &a 19 | } -------------------------------------------------------------------------------- /gop_homework/ch7/homework/test7.3/main.go: -------------------------------------------------------------------------------- 1 | //练习 7.3: 为在gopl.io/ch4/treesort (§4.4)的*tree类型实现一个String方法去展示tree类型的值序列。 2 | package main 3 | 4 | import ( 5 | "fmt" 6 | "strconv" 7 | ) 8 | 9 | type tree struct { 10 | value int 11 | left, right *tree 12 | } 13 | 14 | func (t *tree) String() string { 15 | value := strconv.Itoa(t.value) 16 | return "这就是我的输出:" + value 17 | } 18 | 19 | func Tree() string { 20 | var t tree 21 | return fmt.Sprint(&t) 22 | } 23 | -------------------------------------------------------------------------------- /gop_homework/ch7/homework/test7.3/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "testing" 4 | 5 | func TestTree(t *testing.T) { 6 | value := Tree() 7 | if value == "" { 8 | t.Error("测试错误") 9 | } else { 10 | t.Log("ok!") 11 | } 12 | } 13 | 14 | //go test -test.v // 使用-test.v 可以获取到 log的输出值。 15 | //=== RUN TestTree 16 | //--- PASS: TestTree (0.00s) 17 | // main_test.go:10: ok! 18 | //PASS 19 | //ok github.com/googege/gopl_homework/ch7/homework/test7.3 0.006s 20 | -------------------------------------------------------------------------------- /gop_homework/ch7/homework/test7.4/main.go: -------------------------------------------------------------------------------- 1 | //练习 7.4: strings.NewReader函数通过读取一个string参数返回一个满足io.Reader接口类型的值 2 | //(和其它值) 实现一个简单版本的NewReader,并用它来构造一个接收字符串输入的HTML解析器(§5.2) 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "io" 8 | "io/ioutil" 9 | ) 10 | 11 | type File struct { 12 | s string 13 | i int64 // current reading index 14 | prevRune int 15 | } 16 | 17 | func (r *File) Read(p []byte) (n int, err error) { // 返回写入的字节数和返回错误。 18 | if r.i >= int64(len(r.s)) { // r.i >= int64(len(r.s))的意思就是读取完了。那么返回0和EOF吧赶紧。 19 | // 一定要有EOF的判断否则使用其他读取reader的函数就会卡死。 20 | return 0, io.EOF 21 | } 22 | r.prevRune = -1 23 | n = copy(p, r.s[r.i:]) 24 | r.i += int64(n) 25 | return 26 | } 27 | 28 | func main() { 29 | b, _ := ioutil.ReadAll(NewReader("12")) 30 | fmt.Println(b) 31 | } 32 | 33 | func NewReader(s string) io.Reader { 34 | return &File{ 35 | s, 36 | 0, 37 | -1, 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /gop_homework/ch7/homework/test7.7/main.go: -------------------------------------------------------------------------------- 1 | //解释为什么帮助信息在它的默认值是20.0没有包含°C的情况下输出了°C。 2 | package main 3 | 4 | 5 | //func (c Celsius) String() string { return fmt.Sprintf("%g°C", c) } 6 | -------------------------------------------------------------------------------- /gop_homework/ch7/http1/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 191. 5 | 6 | // Http1 is a rudimentary e-commerce server. 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | "log" 12 | "net/http" 13 | ) 14 | 15 | //!+main 16 | 17 | func main() { 18 | db := database{"shoes": 50, "socks": 5} 19 | log.Fatal(http.ListenAndServe("localhost:8000", db)) 20 | } 21 | 22 | type dollars float32 23 | 24 | func (d dollars) String() string { return fmt.Sprintf("$%.2f", d) } 25 | 26 | type database map[string]dollars 27 | 28 | func (db database) ServeHTTP(w http.ResponseWriter, req *http.Request) { 29 | for item, price := range db { 30 | fmt.Fprintf(w, "%s: %s\n", item, price) 31 | } 32 | } 33 | 34 | //!-main 35 | 36 | /* 37 | //!+handler 38 | package http 39 | 40 | type Handler interface { 41 | ServeHTTP(w ResponseWriter, r *Request) 42 | } 43 | 44 | func ListenAndServe(address string, h Handler) error 45 | //!-handler 46 | */ 47 | -------------------------------------------------------------------------------- /gop_homework/ch7/sleep/sleep.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 179. 5 | 6 | // The sleep program sleeps for a specified period of time. 7 | package main 8 | 9 | import ( 10 | "flag" 11 | "fmt" 12 | "time" 13 | ) 14 | 15 | //!+sleep 16 | var period = flag.Duration("period", 1*time.Second, "sleep period") 17 | 18 | func main() { 19 | flag.Parse() 20 | fmt.Printf("Sleeping for %v...", *period) 21 | time.Sleep(*period) 22 | fmt.Println() 23 | } 24 | 25 | //!-sleep 26 | -------------------------------------------------------------------------------- /gop_homework/ch7/tempflag/tempflag.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 181. 5 | 6 | // Tempflag prints the value of its -temp (temperature) flag. 7 | package main 8 | 9 | import ( 10 | "flag" 11 | "fmt" 12 | 13 | "gopl.io/ch7/tempconv" 14 | ) 15 | 16 | //!+ 17 | var temp = tempconv.CelsiusFlag("temp", 20.0, "the temperature") 18 | 19 | func main() { 20 | flag.Parse() 21 | fmt.Println(*temp) 22 | } 23 | 24 | //!- 25 | -------------------------------------------------------------------------------- /gop_homework/ch8/clock1/clock.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 219. 5 | //!+ 6 | 7 | // Clock1 is a TCP server that periodically writes the time. 8 | package main 9 | 10 | import ( 11 | "io" 12 | "log" 13 | "net" 14 | "time" 15 | ) 16 | 17 | func main() { 18 | listener, err := net.Listen("tcp", "localhost:8000") 19 | if err != nil { 20 | log.Fatal(err) 21 | } 22 | for { 23 | conn, err := listener.Accept() 24 | if err != nil { 25 | log.Print(err) // e.g., connection aborted 26 | continue 27 | } 28 | handleConn(conn) // handle one connection at a time 29 | } 30 | } 31 | 32 | func handleConn(c net.Conn) { 33 | defer c.Close() 34 | for { 35 | _, err := io.WriteString(c, time.Now().Format("15:04:05\n")) 36 | if err != nil { 37 | return // e.g., client disconnected 38 | } 39 | time.Sleep(1 * time.Second) 40 | } 41 | } 42 | 43 | //!- 44 | -------------------------------------------------------------------------------- /gop_homework/ch8/clock2/clock.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 222. 5 | 6 | // Clock is a TCP server that periodically writes the time. 7 | package main 8 | 9 | import ( 10 | "io" 11 | "log" 12 | "net" 13 | "time" 14 | ) 15 | 16 | func handleConn(c net.Conn) { 17 | defer c.Close() 18 | for { 19 | _, err := io.WriteString(c, time.Now().Format("15:04:05\n")) 20 | if err != nil { 21 | return // e.g., client disconnected 22 | } 23 | time.Sleep(1 * time.Second) 24 | } 25 | } 26 | 27 | func main() { 28 | listener, err := net.Listen("tcp", "localhost:8000") 29 | if err != nil { 30 | log.Fatal(err) 31 | } 32 | //!+ 33 | for { 34 | conn, err := listener.Accept() 35 | if err != nil { 36 | log.Print(err) // e.g., connection aborted 37 | continue 38 | } 39 | go handleConn(conn) // handle connections concurrently 40 | } 41 | //!- 42 | } 43 | -------------------------------------------------------------------------------- /gop_homework/ch8/countdown1/countdown.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 244. 5 | 6 | // Countdown implements the countdown for a rocket launch. 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | "time" 12 | ) 13 | 14 | //!+ 15 | func main() { 16 | fmt.Println("Commencing countdown.") 17 | tick := time.Tick(1 * time.Second) 18 | for countdown := 10; countdown > 0; countdown-- { 19 | fmt.Println(countdown) 20 | <-tick 21 | } 22 | launch() 23 | } 24 | 25 | //!- 26 | 27 | func launch() { 28 | fmt.Println("Lift off!") 29 | } 30 | -------------------------------------------------------------------------------- /gop_homework/ch8/countdown2/countdown.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 244. 5 | 6 | // Countdown implements the countdown for a rocket launch. 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | "os" 12 | "time" 13 | ) 14 | 15 | //!+ 16 | 17 | func main() { 18 | // ...create abort channel... 19 | 20 | //!- 21 | 22 | //!+abort 23 | abort := make(chan struct{}) 24 | go func() { 25 | os.Stdin.Read(make([]byte, 1)) // read a single byte 26 | abort <- struct{}{} 27 | }() 28 | //!-abort 29 | 30 | //!+ 31 | fmt.Println("Commencing countdown. Press return to abort.") 32 | select { 33 | case <-time.After(10 * time.Second): 34 | // Do nothing. 35 | case <-abort: 36 | fmt.Println("Launch aborted!") 37 | return 38 | } 39 | launch() 40 | } 41 | 42 | //!- 43 | 44 | func launch() { 45 | fmt.Println("Lift off!") 46 | } 47 | -------------------------------------------------------------------------------- /gop_homework/ch8/homework/test8.1/w/wall.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "io" 5 | "log" 6 | "net" 7 | "os" 8 | "sync" 9 | "time" 10 | ) 11 | var sy sync.WaitGroup 12 | func main() { 13 | data := []string{"9090", "9091", "9092"} 14 | for _, v := range data { 15 | go Wall(v) 16 | } 17 | time.Sleep(time.Hour*1000000) 18 | } 19 | func Wall(port string) { 20 | conn, err := net.Dial("tcp", "localhost:"+port) 21 | if err != nil { 22 | log.Fatal(err) 23 | } 24 | defer conn.Close() 25 | mustCopy(os.Stdout, conn) 26 | } 27 | 28 | func mustCopy(dst io.Writer, src io.Reader) { 29 | if _, err := io.Copy(dst, src); err != nil { 30 | log.Fatal(err) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /gop_homework/ch8/homework/test8.10/main.go: -------------------------------------------------------------------------------- 1 | //练习 8.10: HTTP请求可能会因http.Request结构体中Cancel channel的关闭而取消。 2 | // 修改8.6节中的web crawler来支持取消http请求。(提示:http.Get并没有提供方便地定制一个请求的方法。 3 | // 你可以用http.NewRequest来取而代之,设置它的Cancel字段,然后用http.DefaultClient.Do(req)来进行这个http请求。) 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "io/ioutil" 9 | "net/http" 10 | ) 11 | 12 | func main() { 13 | req, err := http.NewRequest("GET", "https://coastroad.net", nil) 14 | if err != nil { 15 | fmt.Println(err) 16 | } 17 | res, _ := http.DefaultClient.Do(req) 18 | data, err := ioutil.ReadAll(res.Body) 19 | fmt.Println(string(data)) 20 | res.Body.Close() 21 | 22 | } 23 | -------------------------------------------------------------------------------- /gop_homework/ch8/homework/test8.12/main.go: -------------------------------------------------------------------------------- 1 | //练习 8.12: 使broadcaster能够将arrival事件通知当前所有的客户端。 2 | // 为了达成这个目的,你需要有一个客户端的集合, 3 | // 并且在entering和leaving的channel中记录客户端的名字。 4 | package main 5 | 6 | type client chan<- string // an outgoing message channel 7 | 8 | var ( 9 | entering = make(chan client) 10 | leaving = make(chan client) 11 | messages = make(chan string) // all incoming client messages 12 | ) 13 | 14 | func broadcaster() { 15 | clients := make(map[client]bool) // all connected clients 16 | for { 17 | select { 18 | case msg := <-messages: 19 | // Broadcast incoming message to all 20 | // clients' outgoing message channels. 21 | for cli := range clients { 22 | cli <- msg 23 | } 24 | case cli := <-entering: 25 | clients[cli] = true 26 | 27 | case cli := <-leaving: 28 | delete(clients, cli) 29 | close(cli) 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /gop_homework/ch8/homework/test8.13/main.go: -------------------------------------------------------------------------------- 1 | //练习 8.13: 使聊天服务器能够断开空闲的客户端连接,比如最近五分钟之后没有发送任何消息的那些客户端 2 | // 。提示:可以在其它goroutine中调用conn.Close()来解除Read调用,就像input.Scanner()所做的那样。 3 | package main 4 | 5 | import "time" 6 | 7 | func broadcaster() { 8 | clients := make(map[client]bool) // all connected clients 9 | for { 10 | select { 11 | case <-time.After(time.Minute * 5): 12 | return // 已经延迟5分钟了,可以关闭这个连接了。 13 | case msg := <-messages: 14 | // Broadcast incoming message to all 15 | // clients' outgoing message channels. 16 | for cli := range clients { 17 | cli <- msg 18 | } 19 | case cli := <-entering: 20 | clients[cli] = true 21 | 22 | case cli := <-leaving: 23 | delete(clients, cli) 24 | close(cli) 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /gop_homework/ch8/homework/test8.14/main.go: -------------------------------------------------------------------------------- 1 | //练习 8.14: 修改聊天服务器的网络协议这样每一个客户端就可以在entering时可以提供它们的名字。 2 | // 将消息前缀由之前的网络地址改为这个名字。 3 | // 4 | package main 5 | -------------------------------------------------------------------------------- /gop_homework/ch8/homework/test8.15/main.go: -------------------------------------------------------------------------------- 1 | //练习 8.15: 如果一个客户端没有及时地读取数据可能会导致所有的客户端被阻塞。 2 | // 修改broadcaster来跳过一条消息,而不是等待这个客户端一直到其准备好写。 3 | // 或者为每一个客户端的消息发出channel建立缓冲区,这样大部分的消息便不会被丢掉; 4 | // broadcaster应该用一个非阻塞的send向这个channel中发消息。 5 | package main 6 | 7 | func broadcaster() { 8 | clients := make(map[client]bool,30) // all connected clients 9 | for { 10 | select { 11 | case msg := <-messages: 12 | // Broadcast incoming message to all 13 | // clients' outgoing message channels. 14 | for cli := range clients { 15 | cli <- msg 16 | } 17 | case cli := <-entering: 18 | clients[cli] = true 19 | 20 | case cli := <-leaving: 21 | delete(clients, cli) 22 | close(cli) 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /gop_homework/ch8/homework/test8.2/main.go: -------------------------------------------------------------------------------- 1 | //练习 8.2: 实现一个并发FTP服务器。服务器应该解析客户端来的一些命令,比如cd命令来切换目录, 2 | // ls来列出目录内文件,get和send来传输文件,close来关闭连接。 3 | // 你可以用标准的ftp命令来作为客户端,或者也可以自己实现一个。 4 | package main 5 | 6 | import ( 7 | "github.com/goftp/server" 8 | ) 9 | 10 | type MyDriverFactory struct { 11 | 12 | } 13 | func(m MyDriverFactory) NewDriver() (server.Driver, error){ 14 | return nil,nil 15 | } 16 | func main() { 17 | factory := &MyDriverFactory{} 18 | opts := &server.ServerOpts{ 19 | Factory: factory, 20 | Port: 2000, 21 | Hostname: "127.0.0.1", 22 | } 23 | server := server.NewServer(opts) 24 | server.ListenAndServe() 25 | } 26 | -------------------------------------------------------------------------------- /gop_homework/ch8/homework/test8.3/main.go: -------------------------------------------------------------------------------- 1 | //练习 8.3: 在netcat3例子中,conn虽然是一个interface类型的值, 2 | // 但是其底层真实类型是*net.TCPConn,代表一个TCP连接。 3 | // 一个TCP连接有读和写两个部分,可以使用CloseRead和CloseWrite方法分别关闭它们。 4 | // 修改netcat3的主goroutine代码,只关闭网络连接中写的部分, 5 | // 这样的话后台goroutine可以在标准输入被关闭后继续打印从reverb1服务器传回的数据。 6 | // (要在reverb2服务器也完成同样的功能是比较困难的;参考练习 8.4。) 7 | package main 8 | 9 | import ( 10 | "io" 11 | "log" 12 | "net" 13 | "os" 14 | "sync" 15 | ) 16 | 17 | //!+ 18 | func main() { 19 | var sy sync.WaitGroup 20 | sy.Add(1) 21 | conn, err := net.Dial("tcp", "localhost:8000") 22 | if err != nil { 23 | log.Fatal(err) 24 | } 25 | go func() { 26 | defer sy.Done() 27 | io.Copy(os.Stdout, conn) // NOTE: ignoring errors 28 | log.Println("done") 29 | }() 30 | mustCopy(conn, os.Stdin) 31 | conn.Close() 32 | sy.Wait() 33 | } 34 | 35 | //!- 36 | 37 | func mustCopy(dst io.Writer, src io.Reader) { 38 | if _, err := io.Copy(dst, src); err != nil { 39 | log.Fatal(err) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /gop_homework/ch8/homework/test8.9/main.go: -------------------------------------------------------------------------------- 1 | //练习 8.9: 编写一个du工具,每隔一段时间将root目录下的目录大小计算并显示出来。 2 | package main 3 | 4 | import ( 5 | "fmt" 6 | "os/exec" 7 | "time" 8 | ) 9 | 10 | func main() { 11 | du() 12 | } 13 | 14 | func du() { 15 | for { 16 | cmd := exec.Command("ls", "-i", "/") 17 | data, err := cmd.Output() 18 | if err != nil { 19 | fmt.Println(err) 20 | } 21 | fmt.Println(string(data)) 22 | time.Sleep(time.Second * 3) 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /gop_homework/ch8/netcat1/netcat.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 221. 5 | //!+ 6 | 7 | // Netcat1 is a read-only TCP client. 8 | package main 9 | 10 | import ( 11 | "io" 12 | "log" 13 | "net" 14 | "os" 15 | ) 16 | 17 | 18 | func main() { 19 | conn, err := net.Dial("tcp", "localhost:8000") 20 | if err != nil { 21 | log.Fatal(err) 22 | } 23 | defer conn.Close() 24 | mustCopy(os.Stdout, conn) 25 | } 26 | 27 | func mustCopy(dst io.Writer, src io.Reader) { 28 | if _, err := io.Copy(dst, src); err != nil { 29 | log.Fatal(err) 30 | } 31 | } 32 | 33 | //!- 34 | -------------------------------------------------------------------------------- /gop_homework/ch8/netcat2/netcat.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 223. 5 | 6 | // Netcat is a simple read/write client for TCP servers. 7 | package main 8 | 9 | import ( 10 | "io" 11 | "log" 12 | "net" 13 | "os" 14 | ) 15 | 16 | //!+ 17 | func main() { 18 | conn, err := net.Dial("tcp", "localhost:8000") 19 | if err != nil { 20 | log.Fatal(err) 21 | } 22 | defer conn.Close() 23 | go mustCopy(os.Stdout, conn) 24 | mustCopy(conn, os.Stdin) 25 | } 26 | 27 | //!- 28 | 29 | func mustCopy(dst io.Writer, src io.Reader) { 30 | if _, err := io.Copy(dst, src); err != nil { 31 | log.Fatal(err) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /gop_homework/ch8/netcat3/netcat.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 227. 5 | 6 | // Netcat is a simple read/write client for TCP servers. 7 | package main 8 | 9 | import ( 10 | "io" 11 | "log" 12 | "net" 13 | "os" 14 | ) 15 | 16 | //!+ 17 | func main() { 18 | conn, err := net.Dial("tcp", "localhost:8000") 19 | if err != nil { 20 | log.Fatal(err) 21 | } 22 | done := make(chan struct{}) 23 | go func() { 24 | io.Copy(os.Stdout, conn) // NOTE: ignoring errors 25 | log.Println("done") 26 | done <- struct{}{} // signal the main goroutine 27 | }() 28 | mustCopy(conn, os.Stdin) 29 | conn.Close() 30 | <-done // wait for background goroutine to finish 31 | } 32 | 33 | //!- 34 | 35 | func mustCopy(dst io.Writer, src io.Reader) { 36 | if _, err := io.Copy(dst, src); err != nil { 37 | log.Fatal(err) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /gop_homework/ch8/pipeline1/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 228. 5 | 6 | // Pipeline1 demonstrates an infinite 3-stage pipeline. 7 | package main 8 | 9 | import "fmt" 10 | 11 | //!+ 12 | func main() { 13 | naturals := make(chan int) 14 | squares := make(chan int) 15 | 16 | // Counter 17 | go func() { 18 | for x := 0; ; x++ { 19 | naturals <- x 20 | } 21 | }() 22 | 23 | // Squarer 24 | go func() { 25 | for { 26 | x := <-naturals 27 | squares <- x * x 28 | } 29 | }() 30 | 31 | // Printer (in main goroutine) 32 | for { 33 | fmt.Println(<-squares) 34 | } 35 | } 36 | 37 | //!- 38 | -------------------------------------------------------------------------------- /gop_homework/ch8/pipeline2/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 229. 5 | 6 | // Pipeline2 demonstrates a finite 3-stage pipeline. 7 | package main 8 | 9 | import "fmt" 10 | 11 | //!+ 12 | func main() { 13 | naturals := make(chan int) 14 | squares := make(chan int) 15 | 16 | // Counter 17 | go func() { 18 | for x := 0; x < 100; x++ { 19 | naturals <- x 20 | } 21 | close(naturals) 22 | }() 23 | 24 | // Squarer 25 | go func() { 26 | for x := range naturals { 27 | squares <- x * x 28 | } 29 | close(squares) 30 | }() 31 | 32 | // Printer (in main goroutine) 33 | for x := range squares { 34 | fmt.Println(x) 35 | } 36 | } 37 | 38 | //!- 39 | -------------------------------------------------------------------------------- /gop_homework/ch8/pipeline3/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 231. 5 | 6 | // Pipeline3 demonstrates a finite 3-stage pipeline 7 | // with range, close, and unidirectional channel types. 8 | package main 9 | 10 | import "fmt" 11 | 12 | //!+ 13 | func counter(out chan<- int) { 14 | for x := 0; x < 100; x++ { 15 | out <- x 16 | } 17 | close(out) 18 | } 19 | 20 | func squarer(out chan<- int, in <-chan int) { 21 | for v := range in { 22 | out <- v * v 23 | } 24 | close(out) 25 | } 26 | 27 | func printer(in <-chan int) { 28 | for v := range in { 29 | fmt.Println(v) 30 | } 31 | } 32 | 33 | func main() { 34 | naturals := make(chan int) 35 | squares := make(chan int) 36 | 37 | go counter(naturals) 38 | go squarer(squares, naturals) 39 | printer(squares) 40 | } 41 | 42 | //!- 43 | -------------------------------------------------------------------------------- /gop_homework/ch8/spinner/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 218. 5 | 6 | // Spinner displays an animation while computing the 45th Fibonacci number. 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | "time" 12 | ) 13 | 14 | //!+ 15 | func main() { 16 | go spinner(100 * time.Millisecond) 17 | const n = 45 18 | fibN := fib(n) // slow 19 | fmt.Printf("\rFibonacci(%d) = %d\n", n, fibN) 20 | } 21 | 22 | func spinner(delay time.Duration) { 23 | for { 24 | for _, r := range `-\|/` { 25 | fmt.Printf("\r%c", r) 26 | time.Sleep(delay) 27 | } 28 | } 29 | } 30 | 31 | func fib(x int) int { 32 | if x < 2 { 33 | return x 34 | } 35 | return fib(x-1) + fib(x-2) 36 | } 37 | 38 | //!- 39 | -------------------------------------------------------------------------------- /gop_homework/ch9/bank1/bank.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 261. 5 | //!+ 6 | 7 | // Package bank provides a concurrency-safe bank with one account. 8 | package bank 9 | 10 | var deposits = make(chan int) // send amount to deposit 11 | var balances = make(chan int) // receive balance 12 | 13 | func Deposit(amount int) { deposits <- amount } 14 | func Balance() int { return <-balances } 15 | 16 | func teller() { 17 | var balance int // balance is confined to teller goroutine 18 | for { 19 | select { 20 | case amount := <-deposits: 21 | balance += amount 22 | case balances <- balance: 23 | } 24 | } 25 | } 26 | 27 | func init() { 28 | go teller() // start the monitor goroutine 29 | } 30 | 31 | //!- 32 | -------------------------------------------------------------------------------- /gop_homework/ch9/bank1/bank_test.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package bank_test 5 | 6 | import ( 7 | "fmt" 8 | "testing" 9 | 10 | "gopl.io/ch9/bank1" 11 | ) 12 | 13 | func TestBank(t *testing.T) { 14 | done := make(chan struct{}) 15 | 16 | // Alice 17 | go func() { 18 | bank.Deposit(200) 19 | fmt.Println("=", bank.Balance()) 20 | done <- struct{}{} 21 | }() 22 | 23 | // Bob 24 | go func() { 25 | bank.Deposit(100) 26 | done <- struct{}{} 27 | }() 28 | 29 | // Wait for both transactions. 30 | <-done 31 | <-done 32 | 33 | if got, want := bank.Balance(), 300; got != want { 34 | t.Errorf("Balance = %d, want %d", got, want) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /gop_homework/ch9/bank2/bank.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 262. 5 | 6 | // Package bank provides a concurrency-safe bank with one account. 7 | package bank 8 | 9 | //!+ 10 | var ( 11 | sema = make(chan struct{}, 1) // a binary semaphore guarding balance 12 | balance int 13 | ) 14 | 15 | func Deposit(amount int) { 16 | sema <- struct{}{} // acquire token 17 | balance = balance + amount 18 | <-sema // release token 19 | } 20 | 21 | func Balance() int { 22 | sema <- struct{}{} // acquire token 23 | b := balance 24 | <-sema // release token 25 | return b 26 | } 27 | 28 | //!- 29 | -------------------------------------------------------------------------------- /gop_homework/ch9/bank2/bank_test.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package bank_test 5 | 6 | import ( 7 | "sync" 8 | "testing" 9 | 10 | "gopl.io/ch9/bank2" 11 | ) 12 | 13 | func TestBank(t *testing.T) { 14 | // Deposit [1..1000] concurrently. 15 | var n sync.WaitGroup 16 | for i := 1; i <= 1000; i++ { 17 | n.Add(1) 18 | go func(amount int) { 19 | bank.Deposit(amount) 20 | n.Done() 21 | }(i) 22 | } 23 | n.Wait() 24 | 25 | if got, want := bank.Balance(), (1000+1)*1000/2; got != want { 26 | t.Errorf("Balance = %d, want %d", got, want) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /gop_homework/ch9/bank3/bank.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 263. 5 | 6 | // Package bank provides a concurrency-safe single-account bank. 7 | package bank 8 | 9 | //!+ 10 | import "sync" 11 | 12 | var ( 13 | mu sync.Mutex // guards balance 14 | balance int 15 | ) 16 | 17 | func Deposit(amount int) { 18 | mu.Lock() 19 | balance = balance + amount 20 | mu.Unlock() 21 | } 22 | 23 | func Balance() int { 24 | mu.Lock() 25 | b := balance 26 | mu.Unlock() 27 | return b 28 | } 29 | 30 | //!- 31 | -------------------------------------------------------------------------------- /gop_homework/ch9/bank3/bank_test.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package bank_test 5 | 6 | import ( 7 | "sync" 8 | "testing" 9 | 10 | "gopl.io/ch9/bank3" 11 | ) 12 | 13 | func TestBank(t *testing.T) { 14 | // Deposit [1..1000] concurrently. 15 | var n sync.WaitGroup 16 | for i := 1; i <= 1000; i++ { 17 | n.Add(1) 18 | go func(amount int) { 19 | bank.Deposit(amount) 20 | n.Done() 21 | }(i) 22 | } 23 | n.Wait() 24 | 25 | if got, want := bank.Balance(), (1000+1)*1000/2; got != want { 26 | t.Errorf("Balance = %d, want %d", got, want) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /gop_homework/ch9/homework/test9.1/main.go: -------------------------------------------------------------------------------- 1 | //练习 9.1: 给gopl.io/ch9/bank1程序添加一个Withdraw(amount int)取款函数。 2 | // 其返回结果应该要表明事务是成功了还是因为没有足够资金失败了。 3 | // 这条消息会被发送给monitor的goroutine,且消息需要包含取款的额度和一个新的channel, 4 | // 这个新channel会被monitor goroutine来把boolean结果发回给Withdraw。 5 | package main 6 | 7 | var deposits = make(chan int) // send amount to deposit 8 | var balances = make(chan int) // receive balance 9 | 10 | func Deposit(amount int) { 11 | deposits <- amount 12 | } 13 | 14 | func Balance() int { 15 | return <-balances 16 | } 17 | 18 | func Withdraw(amount int) { 19 | 20 | } 21 | 22 | func teller() { 23 | var balance int // balance is confined to teller goroutine 24 | for { 25 | select { 26 | case amount := <-deposits: 27 | balance += amount 28 | case balances <- balance: 29 | } 30 | } 31 | } 32 | 33 | func init() { 34 | go teller() // start the monitor goroutine 35 | } 36 | -------------------------------------------------------------------------------- /gop_homework/ch9/homework/test9.2/main.go: -------------------------------------------------------------------------------- 1 | //练习 9.2: 重写2.6.2节中的PopCount的例子,使用sync.Once,只在第一次需要用到的时候进行初始化。 2 | // (虽然实际上,对PopCount这样很小且高度优化的函数进行同步可能代价没法接受) 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "sync" 8 | ) 9 | 10 | // pc[i] is the population count of i. 11 | var pc [256]byte 12 | var sy sync.Once 13 | 14 | func init() { 15 | sy.Do(func() {// 只需要初始化一次 16 | for i := range pc { 17 | pc[i] = pc[i/2] + byte(i&1) 18 | } 19 | 20 | }) 21 | 22 | } 23 | 24 | // PopCount returns the population count (number of set bits) of x. 25 | func PopCount(x uint64) int { 26 | return int(pc[byte(x>>(0*8))] + 27 | pc[byte(x>>(1*8))] + 28 | pc[byte(x>>(2*8))] + 29 | pc[byte(x>>(3*8))] + 30 | pc[byte(x>>(4*8))] + 31 | pc[byte(x>>(5*8))] + 32 | pc[byte(x>>(6*8))] + 33 | pc[byte(x>>(7*8))]) 34 | } 35 | 36 | func main(){ 37 | fmt.Println(PopCount(12)) 38 | } -------------------------------------------------------------------------------- /gop_homework/ch9/homework/test9.3/main.go: -------------------------------------------------------------------------------- 1 | //练习 9.3: 扩展Func类型和(*Memo).Get方法,支持调用方提供一个可选的done channel, 2 | // 使其具备通过该channel来取消整个操作的能力(§8.9)。一个被取消了的Func的调用结果不应该被缓存。 3 | package main 4 | 5 | 6 | -------------------------------------------------------------------------------- /gop_homework/ch9/homework/test9.4/main.go: -------------------------------------------------------------------------------- 1 | //练习 9.4: 创建一个流水线程序,支持用channel连接任意数量的goroutine, 2 | // 在跑爆内存之前,可以创建多少流水线阶段?一个变量通过整个流水线需要用多久 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "time" 8 | ) 9 | 10 | func main() { 11 | ch := make(chan int) 12 | for i :=0;i < 3;i++{ 13 | go func(i int) { 14 | fmt.Println() 15 | ch <- i 16 | }(i) 17 | } 18 | fmt.Println("d:",<-ch) 19 | time.Sleep(1e10) 20 | } 21 | -------------------------------------------------------------------------------- /gop_homework/ch9/homework/test9.6/data.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | var data = []int64{ 4 | 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,1,2,3,4,5,6,7,8,9, 5 | } 6 | -------------------------------------------------------------------------------- /gop_homework/ch9/homework/test9.6/main.go: -------------------------------------------------------------------------------- 1 | //练习9.6: 测试一下计算密集型的并发程序(练习8.5那样的)会被GOMAXPROCS怎样影响到。 2 | // 在你的电脑上最佳的值是多少?你的电脑CPU有多少个核心? 3 | package main 4 | 5 | import ( 6 | "runtime" 7 | "sync" 8 | "sync/atomic" 9 | ) 10 | 11 | var ( 12 | sy sync.WaitGroup 13 | resulttt int64 14 | ) 15 | 16 | func main() { 17 | TT() 18 | } 19 | func TT() { 20 | le := runtime.NumCPU() // 分割的cpus数量 21 | dataLength := len(data) // data的数量 22 | t := dataLength / le 23 | sy.Add(le) 24 | for i := 0; i < le; i++ { // 假如是 32核的。每一个内核计算 dataLength / le 25 | var j []int64 26 | if i == le-1 { 27 | j = data[t*i:] 28 | } else { 29 | j = data[t*i : t*(i+1)] 30 | } 31 | go deal(j) 32 | } 33 | sy.Wait() 34 | } 35 | 36 | func deal(str []int64) { 37 | defer sy.Done() 38 | var result int64 = 0 39 | for _, v := range str { 40 | result += v 41 | } 42 | atomic.AddInt64(&resulttt, result) 43 | } 44 | -------------------------------------------------------------------------------- /gop_homework/ch9/homework/test9.6/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "testing" 4 | 5 | func BenchmarkTT(b *testing.B) { 6 | for i := 0; i < b.N; i++ { 7 | TT() 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /gop_homework/ch9/memo/memo.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // See page 272. 5 | 6 | //!+ 7 | 8 | // Package memo provides a concurrency-unsafe 9 | // memoization of a function of type Func. 10 | package memo 11 | 12 | // A Memo caches the results of calling a Func. 13 | type Memo struct { 14 | f Func 15 | cache map[string]result 16 | } 17 | 18 | // Func is the type of the function to memoize. 19 | type Func func(key string) (interface{}, error) 20 | 21 | type result struct { 22 | value interface{} 23 | err error 24 | } 25 | 26 | func New(f Func) *Memo { 27 | return &Memo{f: f, cache: make(map[string]result)} 28 | } 29 | 30 | // NOTE: not concurrency-safe! 31 | func (memo *Memo) Get(key string) (interface{}, error) { 32 | res, ok := memo.cache[key] 33 | if !ok { 34 | res.value, res.err = memo.f(key) 35 | memo.cache[key] = res 36 | } 37 | return res.value, res.err 38 | } 39 | 40 | //!- 41 | -------------------------------------------------------------------------------- /gop_homework/ch9/memo2/memo_test.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package memo_test 5 | 6 | import ( 7 | "testing" 8 | 9 | "gopl.io/ch9/memo2" 10 | "gopl.io/ch9/memotest" 11 | ) 12 | 13 | var httpGetBody = memotest.HTTPGetBody 14 | 15 | func Test(t *testing.T) { 16 | m := memo.New(httpGetBody) 17 | memotest.Sequential(t, m) 18 | } 19 | 20 | func TestConcurrent(t *testing.T) { 21 | m := memo.New(httpGetBody) 22 | memotest.Concurrent(t, m) 23 | } 24 | -------------------------------------------------------------------------------- /gop_homework/ch9/memo3/memo_test.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package memo_test 5 | 6 | import ( 7 | "testing" 8 | 9 | "gopl.io/ch9/memo3" 10 | "gopl.io/ch9/memotest" 11 | ) 12 | 13 | var httpGetBody = memotest.HTTPGetBody 14 | 15 | func Test(t *testing.T) { 16 | m := memo.New(httpGetBody) 17 | memotest.Sequential(t, m) 18 | } 19 | 20 | func TestConcurrent(t *testing.T) { 21 | m := memo.New(httpGetBody) 22 | memotest.Concurrent(t, m) 23 | } 24 | -------------------------------------------------------------------------------- /gop_homework/ch9/memo4/memo_test.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package memo_test 5 | 6 | import ( 7 | "testing" 8 | 9 | "gopl.io/ch9/memo4" 10 | "gopl.io/ch9/memotest" 11 | ) 12 | 13 | var httpGetBody = memotest.HTTPGetBody 14 | 15 | func Test(t *testing.T) { 16 | m := memo.New(httpGetBody) 17 | memotest.Sequential(t, m) 18 | } 19 | 20 | func TestConcurrent(t *testing.T) { 21 | m := memo.New(httpGetBody) 22 | memotest.Concurrent(t, m) 23 | } 24 | -------------------------------------------------------------------------------- /gop_homework/ch9/memo5/memo_test.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package memo_test 5 | 6 | import ( 7 | "testing" 8 | 9 | "gopl.io/ch9/memo5" 10 | "gopl.io/ch9/memotest" 11 | ) 12 | 13 | var httpGetBody = memotest.HTTPGetBody 14 | 15 | func Test(t *testing.T) { 16 | m := memo.New(httpGetBody) 17 | defer m.Close() 18 | memotest.Sequential(t, m) 19 | } 20 | 21 | func TestConcurrent(t *testing.T) { 22 | m := memo.New(httpGetBody) 23 | defer m.Close() 24 | memotest.Concurrent(t, m) 25 | } 26 | -------------------------------------------------------------------------------- /helloC/README.md: -------------------------------------------------------------------------------- 1 | ## hello c 2 | c语言入门计划 3 | -------------------------------------------------------------------------------- /helloDart/README.md: -------------------------------------------------------------------------------- 1 | ## 对关于dart的客户端系列进行研究 2 | 包括 3 | 1. flutter 4 | 2. angularDart 5 | 3. fuchsia操作系统 6 | -------------------------------------------------------------------------------- /helloDart/hello.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ffi'; 2 | interface Dd6 { 3 | T fff4(); 4 | }; 5 | void main() async { 6 | int a; 7 | a = 12; 8 | String b = "Flutter is the father of dart"; 9 | print("hello dart hello flutter"); 10 | print("hello"); 11 | final String name = "bob"; 12 | var a1 = 3.134.toString(); 13 | var a333 =[1,2,3,4]; 14 | [1,2,3,4,5].forEach((ele)=> print(ele)); 15 | void aaad(args ) async{ 16 | 17 | } 18 | a333.forEach((k) => print('$k')); 19 | var a1111 = { 20 | "12":"1221", 21 | } ; 22 | var c = new Map.from(a1111); 23 | print(c); 24 | dd(); 25 | print(DD is! Object); 26 | DD()(); 27 | } 28 | 29 | String hello(String from,String b,[int ddd]) => "$from::::$b:::[$ddd]"; 30 | Void dd() { 31 | print(hello("12","121")); 32 | } 33 | 34 | var aaff3a = [1,3,3,4,4]; 35 | 36 | Function DD() { 37 | 38 | return () => print("${~122}"); 39 | } 40 | Map oo6 = { 41 | 1:"3", 42 | 34:"1221", 43 | }; 44 | 45 | -------------------------------------------------------------------------------- /helloDart/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | ) 7 | 8 | func main() { 9 | if 12 > 1 { 10 | fmt.Print("1") 11 | } 12 | } 13 | 14 | func uit() { 15 | fmt.Print("heiehieh") 16 | } 17 | -------------------------------------------------------------------------------- /helloPython/README.md: -------------------------------------------------------------------------------- 1 | ## hello python 2 | 3 | 不管以后用多少Python,该学还是学学嘛,毕竟简单。不学亏了。 4 | -------------------------------------------------------------------------------- /helloShellScript/README.md: -------------------------------------------------------------------------------- 1 | ## 也算是回顾也算是重新学习shell 2 | - 获取进程的id 利用名字 pgrep -f name, 如果是可执行文件的话 pidof name 这样 也可以额 ps -ef |grep go|grep -v grep|awk '{print$2}' 3 | 其中 awk是一种在Linux中运用的编程语言 这样就输出了第二个选项 就是进程id grep -v grep 是将grep自己的干扰项去除。 4 | -------------------------------------------------------------------------------- /helloShellScript/restart/README.md: -------------------------------------------------------------------------------- 1 | ## 遇到某个进程 崩溃就重启的脚本 2 | -------------------------------------------------------------------------------- /helloShellScript/restart/restart.sh: -------------------------------------------------------------------------------- 1 | # ! /bin/sh 2 | 3 | SERVICE_PATH="/data/www/ec" 4 | 5 | SERVICE_NAME="go-mysql-sync" 6 | 7 | START_CMD="./$SERVICE_NAME -config=river.toml" 8 | 9 | LOG_FILE="restart.log" 10 | 11 | 12 | cd $SERVICE_PATH 13 | 14 | pwd 15 | 16 | while true 17 | 18 | do 19 | 20 | procnum=`ps -ef|grep $SERVICE_NAME|grep -v grep|wc -l` 21 | 22 | if [ $procnum -eq 0 ] 23 | 24 | then 25 | 26 | echo "start service...................." 27 | 28 | echo `date +%Y-%m-%d` `date +%H:%M:%S` $SERVICE_NAME >>$LOG_FILE 29 | 30 | ${START_CMD} 31 | 32 | fi 33 | 34 | sleep 1 //每秒检查一轮 35 | 36 | done 37 | -------------------------------------------------------------------------------- /huihuilovemetoo.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/huihuilovemetoo.md -------------------------------------------------------------------------------- /ilovehuihui.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/ilovehuihui.md -------------------------------------------------------------------------------- /joinMyGroup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/joinMyGroup.png -------------------------------------------------------------------------------- /joinPublic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/joinPublic.png -------------------------------------------------------------------------------- /mymy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/mymy.png -------------------------------------------------------------------------------- /pluspro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/pluspro.png -------------------------------------------------------------------------------- /reviewJavaScript/README.md: -------------------------------------------------------------------------------- 1 | ## 复习 JS 2 | -------------------------------------------------------------------------------- /wechat1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basicExploration/Demos/61f7057c8fdce88349fb38cd6da8084ffaa7303a/wechat1.png --------------------------------------------------------------------------------