├── .gitignore ├── Fixnum_bit_range └── main.go ├── HttpResetResponseBody └── reset_http_resbody.go ├── IO.reader └── main.go ├── IO.writer └── main.go ├── Mutex ├── lock_unlock_with_diff_goroutine.go ├── main.go ├── password_demo.go └── ticker_demo.go ├── Os.signal └── use-signal-channel.go ├── Os.user └── main.go ├── README.md ├── SECURITY.md ├── ahocorasick_demo.go ├── backend_demo.go ├── bigfile.go ├── bit-operation ├── main.go └── optCode.go ├── break_demo.go ├── breakpoint-download └── breakpoint.go ├── captcha.html ├── captche.go ├── cgo ├── func │ └── main.go └── select_os │ └── main.go ├── channel ├── channel.go ├── channel_panic_and_deadlock.go ├── range_for_channel_demo.go ├── select_wait.go ├── select_with_channel.go ├── synchronize_and_commu.go └── use-goroutine-generate-iter.go ├── concurrent ├── atomic_addint.go ├── channle_demo.go ├── ctrl-concurrent-count.go ├── go-worker-channel-pool │ └── worker-pool-demo.go ├── goroutinePool │ ├── pool.go │ └── work.go ├── multi-concurrent-ctrl │ └── mulity-concurrent-ctr.go ├── mutex.go ├── mutexAndChanCtrl │ ├── use-chan-contro-goroutine.go │ └── useMutextConcurrencyThread.go ├── producer-and-consumer │ ├── produt-consumer-context.go │ └── 简单的demo.go ├── pubsub │ ├── pub-sub.go │ └── pubsub.go └── screen-primes.go ├── config.yaml ├── context ├── context-use.go ├── context1.go ├── context2.go ├── context_demo.go ├── context_theory.md └── demo.go ├── cpu.pprof ├── create-orc-file └── orc_file.go ├── cron.go ├── decodede.go ├── defer └── main.go ├── demo └── getway │ ├── api │ └── api.go │ ├── go.mod │ ├── go.sum │ ├── main.go │ └── router │ └── router.go ├── diandongche.go ├── docconve └── main.go ├── docker └── docker.md ├── dorequest.go ├── emum └── emun.go ├── etcdwrap ├── README.md ├── client.go ├── discovery.go ├── operate.go ├── register.go └── watcher.go ├── excel.demo ├── .DS_Store ├── excel.go └── read_excel.go ├── excel_gen.go ├── fastjson.go ├── file-upload-download ├── download.go ├── upload.go └── view │ ├── index.html │ └── success.html ├── file-watcher └── watcher.go ├── file_chunk_upload_service ├── chunk_upload │ └── chunk_upload.go ├── demo.go ├── file_chunk │ └── lookup.go └── main.go ├── fmtstring.go ├── func-Params └── func-as-params.go ├── func_option_design └── func_option_design.go ├── generate-stack.go ├── gin_middleware_modify_response.go ├── go-close-func ├── closure_func.go └── closure_func_test.go ├── go-cmd ├── cmd.go └── subslice.go ├── go-etcd ├── client │ ├── main.go │ ├── transport │ │ └── transport.go │ └── utils │ │ ├── balance.go │ │ ├── client.go │ │ └── endpoint.go └── server │ ├── main.go │ └── utils │ └── server.go ├── go-for-select ├── goroutine-exit.go └── multi-thread.go ├── go-local-cache └── main.go ├── go-socket.io-example └── gin-socket.io.go ├── go-web ├── net-http-web │ ├── http-handlefunc.go │ ├── http-handler.go │ ├── request-params.go │ └── web-demo.go └── static-app │ ├── delivery-func.go │ ├── main.go │ ├── static │ └── javascript │ │ ├── index.js │ │ └── jquery.min.js │ ├── user-list.go │ └── view │ ├── content.html │ ├── cookie.html │ ├── footer.html │ ├── header.html │ ├── index.html │ ├── table.html │ └── test.html ├── go.mod ├── go.sum ├── go_logrus └── go_logrus.go ├── golang-gc └── gc-not-release.go ├── golang-learn ├── add-string-method-for-enum.go ├── base64-encode.go ├── defer-add-item-to-slice.go ├── funcLearn.go ├── image-process.go ├── init-map.go ├── linked_list.go ├── new和make的区别.md ├── rand-goroutine.go ├── rm-item-from-slice.go ├── select-overtime │ └── select-overtime.go ├── set.go ├── string_join.go ├── switch-and-select │ ├── select-timeout.go │ └── switch.go ├── switch-type.go ├── time_func.md ├── with-context-pack-func.go └── 引用类型and值类型.go ├── golang-lib-use ├── filetype │ └── checkFileType.go ├── flag │ └── flag.go ├── gin.jwt.middleware.go ├── go-option-design │ ├── default-option.go │ └── type-func │ │ └── type-func.go ├── kardianos.server │ └── example.go ├── net-http-attention-issue │ └── http_client_useing.go ├── sync.Atomic.go ├── sync.Map源码.go ├── sync.Once.go ├── sync.Pool.go └── uber.zap │ └── zap.go ├── golang-oop-idea └── go-oop-summary.go ├── golang-sort └── sort-slice.go ├── grpc-example ├── grpc-theory.go ├── grpc-theory_test.go ├── hello │ ├── hello.pb.go │ └── hello.proto └── server │ └── server.go ├── han.go ├── http表单 └── postForm.go ├── image-process └── image-process-method.go ├── img └── GPM.png ├── inherit └── struct_inherit.go ├── inputReader-read-data-from-control └── readInputfromos.go ├── interface-and-struct-method ├── go-oop.go ├── interface-learn.go ├── interface-method-set.go ├── interface和反射的理解.go └── point-value-struct-distinct.go ├── interface_inherit └── interface_inherit.go ├── io-cache └── io-cache.go ├── ioutilpackage └── main.go ├── ip-ping └── ipPing.go ├── json ├── convert-struct-to-map.go ├── json-marshal-process-null.go ├── json-stream-rw.md └── unMarshal-interface-data.go ├── json2string.go ├── jsonbenchmark ├── jsbench.go └── jsbench_test.go ├── list └── list_struct.go ├── logger.log ├── logger ├── logger.log └── main.go ├── map-concurrent-process ├── define-set.go └── use-chan-process-current-map.go ├── map-value-is-struct └── map-value-is-struct.go ├── mux_router └── main.go ├── mysql ├── delete │ └── mysql-delete.go ├── insert │ └── mysql-insert.go ├── search │ └── mysql-search.go ├── sql.go └── update │ └── mysql-update.go ├── nginx-weighted-round-robin └── round_robin.go ├── panic-and-recover ├── main.go └── recover-protect.go ├── pdf2word └── pdf2word.go ├── polymorphic └── polymorphic_example.go ├── posts.csv ├── pprof ├── pprof.analysis └── use_pprof_in_gin.md ├── practice ├── design.go └── https_web.go ├── producer-and-consumer.go ├── program_demo ├── .DS_Store ├── read_word.go ├── test-person.docx ├── test.pptx └── test.xlsx ├── proxy ├── http-simple-proxy │ ├── simple-proxy.go │ └── simple-proxy_test.go ├── proxy.md └── tcp-trans │ ├── lookupip.go │ ├── port-trans.go │ ├── tcp-trans.go │ └── tls │ ├── client │ └── client.go │ └── server │ └── server.go ├── reflect-and-interface ├── main.go ├── reflect-func.go ├── reflect-interface.go ├── reflect-process-struct.go ├── reflect_learn.go ├── reflect库的理解.md ├── test.go └── useReflectCallFunc.go ├── regexp └── use-regexp-get-substring.go ├── rewrite-res-body-under-gin-middleware └── hijacker.go ├── ring └── ring.go ├── select-sum └── select-sum.go ├── share-memory-and-chan ├── channel-used.go └── memory.go ├── slice ├── slice-use-key.go └── two-demension-slice.go ├── some_work_demo.go ├── sonic.demo.go ├── static-app ├── .DS_Store └── static │ └── .DS_Store ├── string-byte-rune ├── define-enum-string-method.go ├── optimize-string-byte-convert.go └── string_rune_byte.go ├── struct ├── anonymous_struct.go ├── main.go ├── null_struct.go ├── struct-inherit.go ├── struct-with-method.go ├── struct_details.go └── unsafe_pointer.go ├── sync_wait.go ├── syncmap.go ├── template_demo.go ├── tequila ├── ac.go ├── check_bank_number.go └── payload_parser.go ├── test.info ├── test.txt ├── test_omitempty_of_json.go ├── ticker.go ├── tika-demo ├── tika-server-standard-2.9.1.jar └── tika.go ├── toml-file ├── config.toml └── dddd.go ├── ua.go ├── udp-server └── main.go ├── unsafe_pointer_demo.go ├── use_sort_reverse_slice.go ├── utf82gbk └── utf8Tgbk.go ├── viper.go ├── wait_group └── main.go ├── websocket ├── client │ └── websocket-client.go ├── server │ └── websocket-server.go └── websocket_serve.go ├── work-test ├── main.go └── manu.json ├── xmlDemo └── main.go ├── 字符串零拷贝 └── string_byte.go ├── 技术文档 ├── GC │ ├── gc处理命令.md │ ├── gc管理及优化.md │ ├── go-GPM模型.md │ └── golang-GC.md ├── HTTP-TCP │ ├── http.md │ ├── tcp.md │ └── tls握手过程.md ├── HttpCode │ └── HTTP状态码.png ├── Linux │ ├── 1-Linux基础.md │ ├── 2-Linux用户磁盘管理.md │ ├── 3-Linux的vi、vim使用.md │ ├── 4-Linux的yum命令.md │ ├── 5-yum源配置.md │ ├── 6-常用操作快捷键.md │ ├── 7- Linux环境下的各种常用开发软件安装教程.md │ ├── img │ │ ├── 1-Linux基础介绍.png │ │ ├── 1-Linux基础介绍(目录结构).png │ │ ├── 1576057399279.png │ │ ├── 1576057511502.png │ │ ├── 1576057711660.png │ │ ├── 1576057716311.png │ │ ├── 1576057723337.png │ │ ├── 1576057726913.png │ │ ├── 1576057730548.png │ │ ├── 1576057740616.png │ │ ├── 1576057781943.png │ │ ├── 1576057981486.png │ │ ├── 1576058065143.png │ │ ├── 1576058227429.png │ │ ├── 1576061730124.png │ │ ├── 1576061785195.png │ │ ├── 1576114390863.png │ │ ├── 1576115489482.png │ │ ├── 1576117675409.png │ │ ├── 1577760184493.png │ │ ├── 1577760217608.png │ │ ├── Linux-Directory-Structure.jpeg │ │ ├── ls-l.png │ │ ├── more.png │ │ ├── rwx.png │ │ ├── setnu.png │ │ ├── vi模式切换.png │ │ └── yumupdate.png │ ├── linux.md │ ├── linux_dir.md │ ├── linux下各设备文件名.md │ ├── linux文件查找.md │ ├── linux泛域名解析.md │ ├── linux用户权限.md │ ├── linux磁盘分区.md │ ├── linux网卡.md │ └── shell │ │ ├── 1-shell基础教程.md │ │ ├── 2-shell基本语法.md │ │ ├── 3-shell运算符汇总.md │ │ ├── 4-shell的echo、printf、test详细介绍.md │ │ └── passport := passportRe.FindString(bodyStr) ├── Lua │ ├── 1-Lua语言入门指南.md │ ├── 2-Lua语言编程指南.md │ └── 3-Lua编程高级.md ├── Nginx │ ├── 007-Nginx实现虚拟主机、反向代理、负载均衡、高可用.md │ ├── 1-Windows环境Ngin.md │ ├── 10-如何给nginx添加外部模块.md │ ├── 2-Nginx基础入门.md │ ├── 3-nginx服务端404以及502等页面配置.md │ ├── 7-负载均衡实现实践.md │ ├── 9-Nginx配置文件nginx.conf详细介绍.md │ ├── 999-资料分享.md │ ├── img │ │ ├── 04-Keepalived.png │ │ ├── 1576745376238.png │ │ ├── 1576748336954.png │ │ ├── 1576752632200.png │ │ ├── 1576752878597.png │ │ ├── 1576752917726.png │ │ ├── 1576754226844.png │ │ ├── 1576754600807.png │ │ ├── 1576757003894.png │ │ ├── 1576757899719.png │ │ ├── 1576757921014.png │ │ ├── 1576757952498.png │ │ ├── 1576822681380.png │ │ ├── 1576822924112.png │ │ ├── 1576836138597.png │ │ ├── 1576837944705.png │ │ ├── 1576839162422.png │ │ ├── 1576843354486.png │ │ ├── 1576843508915.png │ │ ├── 1576843707409.png │ │ ├── 1576843745271.png │ │ ├── 1577327856588.png │ │ ├── 1577340754696.png │ │ ├── 1577341058999.png │ │ └── 1577343575469.png │ ├── keepalived.conf │ ├── nginx.conf │ ├── nginx安全配置.md │ ├── ngnix配置详介.md │ └── pictures │ │ ├── 7-负载均衡实现 │ │ ├── 1-HTTP重定向负载均衡.jpg │ │ ├── 2-DNS域名解析负载均衡.jpg │ │ ├── 3-反向代理负载均衡.jpg │ │ ├── 4-IP负载均衡.jpg │ │ └── 5-数据链路层负载均衡.jpg │ │ └── LVS.jpg ├── README.md ├── Redis │ ├── 1-Redis内存淘汰策略.md │ ├── 10-Redis面试热点问题.md │ ├── 2-Redis数据类型以及数据结构实现.md │ ├── 3-Redis缓存.md │ ├── 4-Redis哨兵-复制.md │ ├── 5-Redis-Cluster集群.md │ ├── 7-Redis持久化.md │ ├── 8-Redis应用场景分析.md │ ├── 9-1Redis-conf官方原始.md │ ├── 9-Redis-conf配置文件解析.md │ ├── 999-Redis运维系统命令.md │ ├── pictures │ │ ├── 1.jpg │ │ └── 2.jpg │ └── redis分布式锁.md ├── Zookeeper │ ├── img │ │ ├── 1-一般性主从架构.jpg │ │ ├── 2-CMW.jpg │ │ ├── 2-zkservice.jpg │ │ ├── 3-单机集群配置一.png │ │ ├── 3-单机集群配置三.png │ │ ├── 3-单机集群配置二.png │ │ ├── 3-单机集群配置五.png │ │ ├── 3-单机集群配置四.png │ │ ├── 4-会话在服务器之间转移.png │ │ ├── chapter9-1.jpg │ │ ├── chapter9-2Zk选举过程.jpg │ │ ├── chapter9-2ZooKeeper内部原理三--ZooKeeper选举过程(延迟选举时长).jpg │ │ ├── chapter9-2ZooKeeper内部原理三--ZooKeeper选举过程(异常情况).jpg │ │ ├── chapter9-2ZooKeeper内部原理三--ZooKeeper选举过程(正常).jpg │ │ └── chapter9-2服务器选举状态.jpg │ ├── 第1章-Zk概览.md │ ├── 第2章-了解Zk与Zk集群配置、主从模式案例演示.md │ ├── 第3章-使用Zk的API进行开发.md │ ├── 第4章-处理状态变化-主节点、从节点.md │ └── 第九章-ZooKeeper内部原理.md ├── clickhouse │ └── clickhouse.md ├── docker-build-bytefile.md ├── docker-build-image-with-step.md ├── docker-compose.md ├── docker.md ├── go │ └── update_package_by_mod.md ├── golang-compile.md ├── haproxy │ ├── docker-compose.yml │ └── haproxy.cfg ├── kafka │ ├── 1-Kafka基础.md │ └── kafka.md ├── mysql │ ├── 1-MySQL数据库读写锁示例详解、事务隔离级别示例详解.md │ ├── centos安装MariaDB的流程步骤.md │ └── mysql主从复制.md ├── regrex │ └── P.md ├── tcpdump │ └── tcpdump.md ├── xorm快速理解.md ├── 微服务and etcd │ ├── 01-微服务概述.md │ ├── 02-protobuf-1-概述与安装.md │ ├── 02-protobuf-2-语法与原理.md │ ├── 02-protobuf-3-go与protobuf.md │ ├── 03-rpc-1-rpc简介.md │ ├── 03-rpc-2-go原生rpc实现.md │ ├── 03-rpc-3-grpc与go实现.md │ ├── 04-服务发现.md │ ├── 05-etcd-1-etcd概述.md │ ├── 05-etcd-2-etcd与服务发现.md │ ├── 05-etcd-3-go操作etcd基础.md │ ├── 05-etcd-4-go与etcd租约.md │ ├── 05-etcd-5-go与etcd监听.md │ ├── 05-etcd-6-go与etcd-事务.md │ ├── 06-gomicro-1-概述.md │ ├── 06-gomicro-2-集成grpc与etcd.md │ └── 06-gomicro-3-集群.md ├── 数据结构.md ├── 缓存 │ ├── 01_mysql和redis缓存一致性解决方案.png │ └── 02-CPU缓存结构-01.png ├── 网络丢包排查 │ ├── chain.png │ ├── net-miss.md │ └── three-hand.png ├── 规则引擎 │ ├── 1-规则引擎基础.md │ └── img │ │ ├── 1576132902440.png │ │ └── 1576133475159.png └── 高可用 │ ├── 01-高可用、负载均衡不得不说的事.md │ └── img │ ├── 1578043763376.png │ ├── 1578043782006.png │ ├── 1578043798504.png │ ├── 1578043813760.png │ ├── 1578043833525.png │ ├── 1578043850043.png │ ├── 1578043873233.png │ ├── 1578043886303.png │ ├── 1578043901270.png │ └── 1578043923325.png ├── 文件处理 ├── copyfile.go ├── file.md ├── file_read.go ├── file_write.go ├── golang-store │ ├── file-store.go │ └── ram-store.go ├── gzipped.go ├── line-read │ └── read_by_line.go ├── os-openfile │ └── use-os-openfile-createfile.go ├── os2openfile │ └── main.go ├── partial-read │ └── part_read.go ├── printFilesUnderDir.go ├── read-file-ways.go ├── whole-read │ └── read_all.go └── wirte_info_type_file.go ├── 算法 ├── hashmap │ ├── hashmap.go │ └── hashmap_test.go ├── leetcode │ ├── 01-two-sum │ │ └── main.go │ ├── 02-add-number-in-list │ │ └── main.go │ ├── 03-substring-without-duplicate-char │ │ └── main.go │ ├── 04-longest-substring-palindrome │ │ ├── main.go │ │ └── main_test.go │ ├── 05-median-of-two-sorted-arrays │ │ ├── median-of-two-sorted-arrays.go │ │ └── median-of-two-sorted-arrays_test.go │ ├── 06-zigzag-conversion │ │ ├── zigzag-conversion.go │ │ └── zigzag-conversion_test.go │ ├── 07-reverse-int │ │ ├── reverse-int.go │ │ └── reverse-int_test.go │ ├── 08-string-into-int │ │ ├── string-to-int.go │ │ └── string-to-int_test.go │ ├── 09-number-palinfrome │ │ ├── palindrome-number.go │ │ └── palindrome-number_test.go │ ├── 10-regular-expression-match │ │ ├── regular-expression-match.go │ │ └── regular-expression-match_test.go │ ├── 11-container-with-most-area │ │ ├── most-area.go │ │ └── most-area_test.go │ ├── 12-integer-to-roman │ │ ├── integer-to-roman.go │ │ └── integer-to-roman_test.go │ ├── 13-longestOnes │ │ ├── longestOnes.go │ │ └── longestOnes_test.go │ ├── 14-subset │ │ └── subset.go │ ├── 15-mirror-tree │ │ ├── mirror_tree.go │ │ └── trans_mirror.go │ ├── alternate-print.go │ ├── concurrency_merge_sort │ │ ├── mergeSortMulti.go │ │ └── mergeSortMulti_test.go │ ├── concurrent_sum.go │ ├── cstdio │ │ └── cstdio.go │ ├── fetchNumber │ │ └── fetchNum.go │ ├── fisherYetes_shuffle │ │ ├── shuffle.go │ │ └── shuffle_test.go │ ├── heapsort │ │ └── heapsort.go │ ├── levelTraveTree │ │ └── level_traves_tree.go │ ├── list-move-right-and-reverse-list.go │ ├── mergeSort │ │ └── mergeSort.go │ ├── min-stack │ │ └── min-stack.go │ ├── queue-level-tree │ │ ├── queue.go │ │ └── tree-level-order-with-queue.go │ ├── red-packet │ │ ├── red_packet.go │ │ └── red_packet_test.go │ ├── slide-win │ │ └── slide_window.go │ ├── sort-algorithm │ │ ├── bubbleSort.go │ │ ├── insertSorted.go │ │ ├── quicksort │ │ │ └── quicksort.go │ │ └── selectsort │ │ │ └── selectSort.go │ ├── string-diff.go │ ├── string_multi.go │ └── traversal-of-dir │ │ └── map_filepath.go └── lru │ ├── lru.go │ └── lru_test.go ├── 网络编程 ├── socket_demo │ ├── accept-and-send-with-concurrency │ │ ├── client.go │ │ └── server.go │ └── src │ │ ├── client │ │ └── client.go │ │ └── server │ │ └── server.go ├── tcpdemo │ ├── agent │ │ └── agent.go │ └── server │ │ └── server.go └── tcp粘包 │ ├── README.md │ ├── client │ └── cli.go │ ├── proto │ └── proto.go │ └── serve │ └── serve.go └── 面试 ├── 01-defer-panic └── defer-panic.go ├── 02-for-range ├── for-range.go └── some-practice-for-range.go ├── 03-make-new └── make-new.go ├── 04-append-multi-params └── append-multi-params.go ├── 05-struct-Equal-Issue └── struct-Equal-Issue.go ├── 06-type-alias └── type-alias.go ├── 07-append-and-slice └── append-and-slice.go ├── 08-interface-choose-and-nil-point └── interface-choose-and-nil-point.go ├── 09-map-and-slice-as-param-unfold └── map-and-slice-as-param-unfold.go ├── 10-slice-operate-and-cap-and-array-equal └── slice-operate-and-cap-and-array-equal.go ├── 11-anonymous-combination └── anonymous-combination.go ├── 12-nil-blank-slice-and-interface-polymorphic └── nil-blank-slice-and-interface-polymorphic.go ├── 13-declare-point-variable └── declare-point-variable.go ├── 14-defer-closure-point └── defer-closure-point.go ├── 15-slice-delete-elem └── slice-delete-elem.go ├── 16-Ttype-and-pointT └── Ttype-and-pointT.go ├── 17-iota-and-String-method └── iota-and-String-method.go ├── 18-gorouttine-under-for-range └── gorouttine-under-for-range.go ├── 19-defer-recover-anonymous-func └── defer-recover-anonymous-func.go ├── 20-append-slice-issue └── main.go ├── 21-struct-slice └── main.go ├── 22-learn-map-with-test ├── dictionary.go └── dictionary_test.go ├── 23-alias-name └── type-struct-aliase.go ├── 24-point └── point.go ├── 25-interface-nil-issue └── interface-concrete-issue.go ├── 26-goroutine-channel-demo └── goroutine-channel.go ├── 27-string-method-issue └── sturct-achieve-string-method.go ├── 28-about-for-range-note └── main.go ├── 29-delete-elem-in-slice └── main.go ├── 30-select-single-channel └── main.go ├── 31-interface-and-nil └── main.go ├── 32-nil-and-map-issue └── main.go ├── 33-const-issue └── main.go ├── 34-variable-issue └── main.go ├── 35-struct-assign-issue └── main.go ├── 36-bit-operate-issue └── main.go ├── 37-const-and-string-issue └── main.go ├── 38-variable-hidden-issue └── main.go ├── 39-channel-and-json-issue └── main.go ├── 40-three-colon-syntax └── main.go ├── 41-func-parameter-issue └── main.go ├── 42-func-compare-with-nil └── main.go ├── 43-about-nil-struct-call-func └── main.go ├── 44-point-address-issue └── main.go ├── 45-point-receiver └── main.go ├── 46-struct-method-issue └── main.go ├── 47-multi-equal-issue └── main.go ├── 48-overflow-issue └── main.go ├── 49-valueOfmap-is-struct ├── map-init-and-use.go └── map-value-struct-issue.go ├── append-slice-issue.go └── main.go /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | *.xml 3 | -------------------------------------------------------------------------------- /HttpResetResponseBody/reset_http_resbody.go: -------------------------------------------------------------------------------- 1 | package HttpResetResponseBody 2 | 3 | /* 4 | //perform http request 5 | resp, err := http.Post(url, "application/json; charset=utf-8", bytes.NewBuffer(requestData)) 6 | defer resp.Body.Close() 7 | utils.CheckErr(err) 8 | 9 | // read the response body to a variable 10 | bodyBytes, _ := ioutil.ReadAll(resp.Body) 11 | bodyString := string(bodyBytes) 12 | //print raw response body for debugging purposes 13 | fmt.Println("\n\n", bodyString, "\n\n") 14 | 15 | //reset the response body to the original unread state 16 | resp.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes)) 17 | 18 | 19 | // Step 3 20 | oR := new(jsonResponse) 21 | json.NewDecoder(resp.Body).Decode(oR) 22 | 23 | */ 24 | -------------------------------------------------------------------------------- /IO.writer/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "os" 4 | 5 | //Go语言标准库中输出流是Writer接口, 将程序中的数据写到外部 6 | /* 7 | type Writer interface { 8 | Write(p []byte) (n int, err error) 9 | } 10 | */ 11 | //输出的时候打开文件不能使用os.Open(), 因为是只读的 12 | /* 13 | OpenFile第三个参数是文件权限, 编译时转换成二进制 14 | 第一位总是0 15 | 第二位为读权限,0表示不可读,1为可读 16 | 第三位为写权限 17 | 第四位为执行权限 18 | 整理如下: 19 | 0(0000): 不可读写,不能被执行 20 | 1(0001): 不可读写,能被执行 21 | 2(0010): 可写不可读,不能被执行 22 | 3(0011): 可写不可读,能被执行 23 | 4(0100): 可读不可写,不能被执行 24 | 5(0101): 可读不可写,能被执行 25 | 6(0110): 可读写,不能执行 26 | 7(0111): 可读写,可执行 27 | 28 | 0666: 29 | 第一个 0 表示这个数是 八进制 30 | 第一个 6 表示文件拥有者有读写权限,但没有执行权限 0110 31 | 第二个 6 表示文件拥有者同组用户有读写权限,但没有执行权限 0110 32 | 第三个 6 表示其它用户有读写权限,但没有执行权限 0110 33 | */ 34 | func main() { 35 | f, err := os.OpenFile("path.txt", os.O_APPEND, 0660) 36 | if err != nil { 37 | // 创建文件 38 | f, _ = os.Create("path") 39 | } 40 | f.Write([]byte("writer流写入数据")) 41 | f.WriteString("\r\n再次写入数据\t哈哈哈") 42 | } 43 | -------------------------------------------------------------------------------- /Mutex/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | ) 7 | 8 | /* 9 | 互斥锁sync.Mutex使用场景 10 | 多个goroutine访问同一个函数, 此函数操作一个全局变量 11 | 使用go run -race查看竞争关系 12 | 13 | *读写锁提高了更高的并行性,也就是说允许多个线程几乎同一时间读取一个共享变量,而互斥锁不行 14 | */ 15 | 16 | var ( 17 | //票数 18 | num = 100 19 | wg sync.WaitGroup 20 | mu sync.Mutex //互斥锁 21 | ) 22 | func main() { 23 | wg.Add(10) 24 | for i := 0; i < 10; i++ { 25 | go demo() 26 | } 27 | wg.Wait() 28 | fmt.Println(num, "程序执行结束") 29 | } 30 | 31 | func demo() { 32 | mu.Lock() 33 | for i := 0; i < 10; i++ { 34 | num = num - 1 35 | } 36 | mu.Unlock() 37 | wg.Done() 38 | } -------------------------------------------------------------------------------- /Mutex/ticker_demo.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "os" 7 | "sync" 8 | "time" 9 | ) 10 | 11 | //模拟售票系统 12 | var ( 13 | //票数 14 | numt = 100 15 | w sync.WaitGroup 16 | m sync.Mutex //互斥锁 17 | ) 18 | 19 | func runTick() { 20 | //设置随机种子,避免每次随机数是一养的 21 | rand.Seed(time.Now().UnixNano()) 22 | w.Add(4) 23 | go sellTickert(1) 24 | go sellTickert(2) 25 | go sellTickert(3) 26 | go sellTickert(4) 27 | w.Wait() 28 | fmt.Println("所有票数卖完") 29 | os.Exit(0) 30 | } 31 | 32 | func sellTickert(i int) { 33 | defer func() { 34 | w.Done() 35 | }() 36 | for { 37 | m.Lock() 38 | if numt > 0 { 39 | fmt.Println("第", i, "个窗口卖了", numt) 40 | numt = numt - 1 41 | } 42 | m.Unlock() 43 | if numt <= 0 { 44 | break 45 | } 46 | //防止一个goroutine卖了所有票 47 | time.Sleep(time.Duration(rand.Int63n(1000) * 1e6)) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Os.signal/use-signal-channel.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "os/signal" 7 | "time" 8 | ) 9 | 10 | var msignal chan os.Signal 11 | 12 | func dealSignal() { 13 | for { 14 | <-msignal 15 | fmt.Println("Get Signal ...") 16 | } 17 | } 18 | 19 | func main() { 20 | i := 0 21 | msignal = make(chan os.Signal, 1) 22 | signal.Notify(msignal, os.Interrupt) 23 | go dealSignal() 24 | for { 25 | i++ 26 | time.Sleep(1 * time.Second) 27 | if i > 5 { 28 | break 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Os.user/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os/user" 6 | ) 7 | 8 | /* 9 | os/user包提供User的结构体 10 | type User struct { 11 | //用户id 12 | Uid string 13 | //组id 14 | Gid string 15 | //用户名 16 | Username string 17 | //组名 18 | Name string 19 | // 用户名路径 20 | HomeDir string 21 | } 22 | 23 | type Group struct { 24 | Gid string // group ID 25 | Name string 26 | } 27 | 28 | func Current() (*User, error) 29 | func Lookup(username string) (*User, error) 30 | func LookupId(uid string) (*User, error) 31 | */ 32 | func main() { 33 | u, _ := user.Current() 34 | fmt.Println(u.Uid) 35 | fmt.Println(u.Username) 36 | fmt.Println(u.HomeDir) 37 | fmt.Println(u.GroupIds()) 38 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | *golang fmt.Printf 显示类型和值的小技巧* 2 | ```$xslt 3 | //如果值是一个结构体,%+v 的格式化输出内容将包括结构体的字段名。 4 | fmt.Printf("%+v\n", p) // {x:1 y:2} 5 | 6 | //%#v 形式则输出这个值的 Go 语法表示。例如,值的运行源代码片段。 7 | fmt.Printf("%#v\n", p) // main.point{x:1, y:2} 8 | ``` 9 | *golang工程中的文件目录与package* 10 | ``` 11 | 1. 习惯上文件目录的名字与package名字保持一致, 12 | 2. 一个文件目录下只能有一个package 13 | 3. 如若不一致,import的时候要写目录名,引用的时候要写包名 14 | ``` 15 | *golang方法指针接收和值接收的区别* 16 | ```$xslt 17 | 1. 值接收者声明的方法,调用时使用改值的一个副本去执行 18 | 2. 指针接收者声明的方法,引用地址->指向接收者的值,可以修改该值 19 | 3. 在使用时,值类型的接收者也可以使用指针类型的调用 20 | 原因:对指针进行了转换(*t).method() 21 | ``` 22 | *声明指针不会开辟内存地址,只是准备要指向内存某个空间,而声明变量会开辟内存地址,准备存放内容.所以指针类型变量都是把一个变量的地址赋值给指针变量* 23 | 24 | 25 | *golang面向对象思想* 26 | 27 | ```gotemplate 28 | 1.golang中的继承是通过struct匿名组合来实现的; 29 | 2.多态是通过接口来实现的 30 | 3.struct与interface之间是隐形继承的 31 | 4.接口是对继承的一种补充 32 | 5.继承主要解决代码的复用性和可维护性 33 | 6.接口的价值设计各种规范,让其他struct实现这些方法,多态上多些 34 | ``` 35 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Use this section to tell people about which versions of your project are 6 | currently being supported with security updates. 7 | 8 | | Version | Supported | 9 | | ------- | ------------------ | 10 | | 5.1.x | :white_check_mark: | 11 | | 5.0.x | :x: | 12 | | 4.0.x | :white_check_mark: | 13 | | < 4.0 | :x: | 14 | 15 | ## Reporting a Vulnerability 16 | 17 | Use this section to tell people how to report a vulnerability. 18 | 19 | Tell them where to go, how often they can expect to get an update on a 20 | reported vulnerability, what to expect if the vulnerability is accepted or 21 | declined, etc. 22 | -------------------------------------------------------------------------------- /bit-operation/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | /* 8 | 原码:正数是其二进制本身;负数是符号位为1,数值部分取X绝对值的二进制。 9 | 反码:正数的反码和原码相同;负数是符号位为1,其它位是原码取反。 10 | 补码:正数的补码和原码,反码相同;负数是符号位为1,其它位是原码取反,未位加1。 11 | 12 | */ 13 | func main() { 14 | //原码 0000 0011 15 | //反码 0000 0011 16 | //补码 0000 0011 17 | var a int8 = 3 18 | //原码 1000 0010 19 | //反码 1111 1101 20 | //补码 1111 1110 21 | var b int8 = -2 22 | 23 | //// 左移和右移 操作的是原码, 结果为乘以2的n次方 24 | //fmt.Println(a << 2) // 0000 1100 25 | //fmt.Println(b << 2) // 1000 1000 26 | //// 右移, 正数的最小值是0, 负数的最小值是-1 27 | //fmt.Println(a >> 2) // 0000 0000 28 | //fmt.Println(b >> 2) // 0000 0000 29 | 30 | //位运算符使用的是补码 补码 -> 反码 -> 原码 31 | fmt.Println(a | b) // 1111 1111 -> 1111 1110 -> 1000 0001 32 | fmt.Println(a & b) // 0000 0010 -> 0000 0010 -> 0000 0010 33 | fmt.Println(-1 ^ (-1 << 5)) 34 | } 35 | 36 | -------------------------------------------------------------------------------- /bit-operation/optCode.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "golang.org/x/exp/slices" // Go 1.18 及以上版本的 slices 包 6 | ) 7 | 8 | //位运算符用于websocket协议的判断 9 | var WebsocketOpCodes []byte = []byte{ 10 | 0, // continuation frame 11 | 1, // text 12 | 2, // binary 13 | 8, // close 14 | 9, // ping 15 | 10, // pong 16 | } 17 | 18 | func processWebSocketFrame(data []byte) error { 19 | if len(data) == 0 { 20 | return fmt.Errorf("data is empty") 21 | } 22 | 23 | opCode := data[0] & 0x0F 24 | if !slices.Contains(WebsocketOpCodes, opCode) { 25 | return fmt.Errorf("unsupported opcode: %d", opCode) 26 | } 27 | 28 | // 处理有效的操作码... 29 | return nil 30 | } 31 | 32 | func main() { 33 | data := []byte{9, 11} // 示例数据,代表一个文本帧 34 | err := processWebSocketFrame(data) 35 | if err != nil { 36 | fmt.Println("Error:", err) 37 | } else { 38 | fmt.Println("Frame processed successfully.") 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /break_demo.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func main() { 9 | 10 | ticker := time.NewTicker(time.Second * 2) 11 | timer := time.NewTimer(time.Second * 9) 12 | cycle: 13 | for { 14 | select { 15 | case <-ticker.C: 16 | fmt.Println("*********ticker break********") 17 | case <-timer.C: 18 | fmt.Println("break exit") 19 | break cycle 20 | } 21 | } 22 | 23 | ticker.Stop() 24 | timer.Stop() 25 | fmt.Println("break test over!") 26 | } 27 | -------------------------------------------------------------------------------- /captche.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | 7 | "github.com/VictoriaMetrics/fastcache" 8 | ) 9 | 10 | func main() { 11 | path := "./captcha.html" 12 | bs, err := ioutil.ReadFile(path) 13 | if err != nil { 14 | fmt.Println("----", err) 15 | } 16 | fmt.Println(len(bs)) 17 | pc := fastcache.New(1) 18 | pc.Set([]byte("page"), bs) 19 | fmt.Println(pc.Get(nil, []byte("page"))) 20 | var val string 21 | var v interface{} = 1 22 | val = v.(string) 23 | fmt.Println(val) 24 | 25 | } 26 | -------------------------------------------------------------------------------- /cgo/select_os/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | /* 4 | #cgo windows CFLAGS: -DCGO_OS_WINDOWS=1 5 | #cgo darwin CFLAGS: -DCGO_OS_DARWIN=1 6 | #cgo linux CFLAGS: -DCGO_OS_LINUX=1 7 | 8 | #if defined(CGO_OS_WINDOWS) 9 | const char* os = "windows"; 10 | #elif defined(CGO_OS_DARWIN) 11 | const char* os = "darwin"; 12 | #elif defined(CGO_OS_LINUX) 13 | const char* os = "linux"; 14 | #else 15 | error(unknown os) 16 | #endif 17 | */ 18 | import "C" 19 | 20 | func main() { 21 | print(C.GoString(C.os)) 22 | } 23 | -------------------------------------------------------------------------------- /channel/channel.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | //主线程中,channel阻塞:产生死锁fatal error : all goroutines are asleep -deadlock! 6 | func main() { 7 | ch := make(chan int, 10) 8 | go func() { 9 | for i:=0; i<10; i++ { 10 | ch <- i 11 | } 12 | close(ch) 13 | }() 14 | 15 | for i := range ch{ 16 | fmt.Println(i) 17 | } 18 | //close(ch) 19 | //fmt.Println(<-ch) 20 | //done := make(chan bool) // 无缓冲通道 21 | //defer close(done) 22 | // 23 | //go func() { 24 | // time.Sleep(9 * time.Second) 25 | // fmt.Println("one done") 26 | // done <- true 27 | //}() 28 | // 29 | //go func() { 30 | // time.Sleep(5 * time.Second) 31 | // fmt.Println("two done") 32 | // done <- true 33 | //}() 34 | // 35 | //// wait until both are done 36 | //for c := 0; c < 2; c++ { 37 | // <-done 38 | //} 39 | //fmt.Println("handle1 done") 40 | } 41 | 42 | -------------------------------------------------------------------------------- /channel/channel_panic_and_deadlock.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | //1. fatal error: all goroutines are asleep - deadlock! 4 | 5 | func cacheChannel() { 6 | //无缓存通道读 7 | ch := make(chan int) 8 | <-ch 9 | //无缓存通道写,没有写成读 10 | ch <- 1 11 | 12 | //通道的缓存无数据,但执行读通道。 13 | //通道的缓存已经占满,向通道写数据,但无协程读。 14 | chm := make(chan int, 5) 15 | <-chm 16 | } 17 | 18 | //2. panic 19 | // 20 | //向已经关闭的channel写。 21 | //c关闭已经关闭的channel 22 | -------------------------------------------------------------------------------- /channel/range_for_channel_demo.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | //for range的特别之处:会一直阻塞当前协程,如果在其他协程中调用了close(ch),那么就会跳出for range循环 6 | //demo 7 | func forRange() { 8 | ch := make(chan string) 9 | ch2 := make(chan int) 10 | 11 | go func() { 12 | for i := 97; i < 123; i++ { 13 | ch <- fmt.Sprintf("%c", i) 14 | } 15 | //用来跳出range循环 16 | close(ch) 17 | ch2 <- 1 18 | }() 19 | 20 | go func() { 21 | for c := range ch { 22 | fmt.Println(c) 23 | } 24 | fmt.Println("check 阻塞") 25 | }() 26 | <-ch2 27 | fmt.Println("执行结束") 28 | } 29 | -------------------------------------------------------------------------------- /channel/select_wait.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func selectWait() { 9 | start := time.Now() 10 | wait := make(chan int, 1) 11 | go func() { 12 | fmt.Println("做点东西") 13 | time.Sleep(1 * time.Second) 14 | wait <- 2 15 | }() 16 | fmt.Println("这里是主程序") 17 | select { 18 | case nums := <-wait: 19 | fmt.Println(nums) 20 | case <-time.After(3 * time.Second): 21 | fmt.Println("3秒后") 22 | } 23 | fmt.Println(time.Since(start)) 24 | } 25 | -------------------------------------------------------------------------------- /channel/select_with_channel.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | //for循环中使用select: 使用break标签退出循环 6 | func forSelect() { 7 | ch := make(chan int) 8 | 9 | for i := 0; i < 10; i++ { 10 | go func(j int) { 11 | ch <- j 12 | }(i) 13 | } 14 | EXIT: 15 | for { 16 | select { 17 | case c := <-ch: 18 | fmt.Println(c) 19 | default: 20 | break EXIT 21 | } 22 | } 23 | fmt.Println("程序结束") 24 | } 25 | -------------------------------------------------------------------------------- /channel/synchronize_and_commu.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | /* 4 | 已关闭的chan只能读不能写 5 | 声明语法 6 | var 名称 chan 类型 7 | var 名称 chan <- 类型 //只写 8 | var 名称 <- chan 类型//只读 9 | 名称:=make(chan int) //无缓存channel 10 | 名称:=make(chan int,0)//无缓存channel 11 | 名称:=make(chan int,100)//有缓存channel 12 | 取值 13 | ch <- 值 //向ch中添加一个值 14 | <- ch //从ch中取出一个值 15 | a:=<-ch //从ch中取出一个值并赋值给a 16 | a,b:=<-ch//从ch中取出一个值赋值给a,如果ch已经关闭或ch中没有值,b为false 17 | */ 18 | 19 | //主线程和子线程的同步; 子线程至今通信 20 | /* 21 | func main() { 22 | //声明chan用于子线程通信 23 | ch := make(chan string) 24 | //同步 25 | chi := make(chan int) 26 | 27 | go func() { 28 | fmt.Println("开始传递信息") 29 | ch <- "来自星星的你" 30 | close(ch) 31 | chi <- 1 32 | }() 33 | 34 | go func() { 35 | fmt.Println("开始接收数据") 36 | content := <- ch 37 | fmt.Println("接收到的数据为:", content) 38 | chi <- 2 39 | }() 40 | //查看当前同步的子线程 41 | result := <- chi 42 | fmt.Println(result) 43 | result = <- chi 44 | fmt.Println(result) 45 | } 46 | */ 47 | -------------------------------------------------------------------------------- /channel/use-goroutine-generate-iter.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "sync" 5 | ) 6 | 7 | //单项channel的初识化 8 | //''' 9 | //ch := make(chan int) 10 | //ch1 := <-chan int(ch) //类型转换为单向读取channel 11 | //ch2 := chan<- int(ch) //类型转换为单向写入channel 12 | //''' 13 | type threadSafeSet struct { 14 | sync.RWMutex 15 | s []interface{} 16 | } 17 | 18 | func (set *threadSafeSet) Iter() chan interface{} { 19 | ch := make(chan interface{}, len(set.s)) 20 | go func() { 21 | set.RLock() 22 | for elem, value := range set.s { 23 | ch <- value 24 | println("Iter", elem, value) 25 | } 26 | close(ch) 27 | set.RUnlock() 28 | }() 29 | return ch 30 | } 31 | 32 | //func main() { 33 | // th := threadSafeSet{s: []interface{}{1,2,3}} 34 | // v := <-th.Iter() 35 | // fmt.Println(v) 36 | //} 37 | -------------------------------------------------------------------------------- /concurrent/atomic_addint.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "sync" 5 | "sync/atomic" 6 | ) 7 | 8 | var sum int64 9 | 10 | func worker_atomic(wg *sync.WaitGroup) { 11 | defer func() { 12 | wg.Done() 13 | }() 14 | var i int64 15 | for i = 0; i < 10000; i++ { 16 | atomic.AddInt64(&sum, i) 17 | } 18 | } 19 | 20 | /* 21 | func main() { 22 | wg := sync.WaitGroup{} 23 | wg.Add(2) 24 | go worker_atomic(&wg) 25 | go worker_atomic(&wg) 26 | wg.Wait() 27 | fmt.Println("执行结束", sum) 28 | } 29 | */ 30 | -------------------------------------------------------------------------------- /concurrent/channle_demo.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | /* 4 | var wait sync.WaitGroup 5 | var w sync.WaitGroup 6 | 7 | func main() { 8 | ch := make(chan int) 9 | sign := make(chan int, 1) 10 | wait.Add(2) 11 | go func(wait *sync.WaitGroup) { 12 | for i := 0; i < 10000; i++ { 13 | ch <- i 14 | } 15 | wait.Done() 16 | }(&wait) 17 | 18 | go func(wait *sync.WaitGroup) { 19 | for i := 0; i < 10000; i++ { 20 | ch <- i 21 | } 22 | wait.Done() 23 | }(&wait) 24 | 25 | go func() { 26 | wait.Wait() 27 | sign <- 1 28 | }() 29 | w.Add(1) 30 | go func(wait *sync.WaitGroup) { 31 | sum := 0 32 | END: 33 | for { 34 | select { 35 | case m := <-ch: 36 | sum += m 37 | fmt.Println(sum) 38 | case <-sign: 39 | w.Done() 40 | break END 41 | } 42 | } 43 | fmt.Println("循环结束") 44 | }(&w) 45 | w.Wait() 46 | fmt.Println("执行结束") 47 | } 48 | */ 49 | -------------------------------------------------------------------------------- /concurrent/ctrl-concurrent-count.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | /* 4 | var wg sync.WaitGroup 5 | 6 | func main() { 7 | jobs := 10 8 | //控制线程数量 9 | pool := 3 10 | jobChans := make(chan int, pool) 11 | for i := 0; i < pool; i++ { 12 | go func() { 13 | for ch := range jobChans { 14 | fmt.Println("hello" + strconv.Itoa(ch)) 15 | wg.Done() 16 | } 17 | }() 18 | } 19 | for i := 0; i < jobs; i++ { 20 | wg.Add(1) 21 | jobChans <- i 22 | fmt.Printf("index: %d, goroutine number: %d\n", i, runtime.NumGoroutine()) 23 | } 24 | wg.Wait() 25 | fmt.Println("done") 26 | } 27 | */ 28 | -------------------------------------------------------------------------------- /concurrent/goroutinePool/pool.go: -------------------------------------------------------------------------------- 1 | package goroutinePool 2 | 3 | type signal struct {} 4 | 5 | type f func() error 6 | 7 | type Pool struct { 8 | capacity int32 9 | running int32 10 | freeSignal chan signal 11 | } -------------------------------------------------------------------------------- /concurrent/goroutinePool/work.go: -------------------------------------------------------------------------------- 1 | package goroutinePool 2 | 3 | type Work struct { 4 | pool *Pool 5 | task chan f 6 | } 7 | -------------------------------------------------------------------------------- /concurrent/multi-concurrent-ctrl/mulity-concurrent-ctr.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | ) 7 | 8 | func main() { 9 | //multi channel ctrl 10 | done := make(chan int, 10) // 带 10 个缓存 11 | 12 | // 开N个后台打印线程 13 | for i := 0; i < cap(done); i++ { 14 | go func() { 15 | fmt.Println("你好, 世界") 16 | done <- 1 17 | }() 18 | } 19 | 20 | // 等待N个后台线程完成, 此处不能使用range来处理, fatal error: all goroutines are asleep - deadlock! 21 | for i := 0; i < cap(done); i++ { 22 | <-done 23 | } 24 | 25 | //waitgroup 控制 26 | var wg sync.WaitGroup 27 | 28 | // 开N个后台打印线程 29 | for i := 0; i < 10; i++ { 30 | wg.Add(1) 31 | 32 | go func() { 33 | fmt.Println("你好, 世界") 34 | wg.Done() 35 | }() 36 | } 37 | 38 | // 等待N个后台线程完成 39 | wg.Wait() 40 | } 41 | -------------------------------------------------------------------------------- /concurrent/mutex.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "sync" 5 | ) 6 | 7 | var total struct { 8 | sync.Mutex 9 | value int 10 | } 11 | 12 | func worker(wt *sync.WaitGroup) { 13 | defer func() { 14 | wt.Done() 15 | }() 16 | for i := 0; i <= 100; i++ { 17 | total.Lock() 18 | total.value += i 19 | total.Unlock() 20 | } 21 | } 22 | 23 | /* 24 | 25 | func main() { 26 | var wg sync.WaitGroup 27 | wg.Add(2) 28 | go worker(&wg) 29 | go worker(&wg) 30 | wg.Wait() 31 | fmt.Printf("执行结束,value为%v\n", total.value) 32 | } 33 | */ 34 | -------------------------------------------------------------------------------- /concurrent/mutexAndChanCtrl/use-chan-contro-goroutine.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | ) 7 | 8 | //func main() { 9 | 10 | //} 11 | func main() { 12 | //使用mutex lock控制并发 13 | var mutex sync.Mutex 14 | i := 6 15 | mutex.Lock() 16 | go func() { 17 | fmt.Println(i) 18 | mutex.Unlock() 19 | }() 20 | mutex.Lock() 21 | //使用chan控制并发 22 | done := make(chan bool, 1) 23 | go func() { 24 | fmt.Println("执行子线程") 25 | done <- true 26 | }() 27 | <-done 28 | fmt.Println("执行结束") 29 | } 30 | -------------------------------------------------------------------------------- /concurrent/mutexAndChanCtrl/useMutextConcurrencyThread.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | ) 7 | 8 | func mutex() { 9 | var mu sync.Mutex 10 | msg := "" 11 | mu.Lock() 12 | go func() { 13 | msg = "你好" 14 | mu.Unlock() 15 | }() 16 | mu.Lock() //阻塞等待子线程先执行赋值 17 | fmt.Println(msg) 18 | } 19 | -------------------------------------------------------------------------------- /concurrent/producer-and-consumer/produt-consumer-context.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "context" 4 | 5 | func Process(ctx context.Context) { 6 | //控制product线程 7 | n := 3 8 | for i := 0; i 0 { 26 | for _, item := range row { 27 | fmt.Println(item) 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /fastjson.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | 7 | "github.com/valyala/fastjson" 8 | ) 9 | 10 | func main() { 11 | str := []string{"openid123"} 12 | param := []string{"openid", "0"} 13 | b, err := json.Marshal(str) 14 | if err == nil { 15 | v := fastjson.GetString(b, param[1:]...) 16 | if v == "" { 17 | fmt.Println("nil") 18 | } 19 | fmt.Println(v) 20 | } 21 | 22 | str1 := `{"Mobile":"13021015699"}` 23 | param = []string{"Mobile"} 24 | var p fastjson.Parser 25 | v, _ := p.Parse(str1) 26 | fmt.Printf("mobile=%s\n", v.GetStringBytes(param...)) 27 | } 28 | -------------------------------------------------------------------------------- /file-upload-download/view/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 文件上传 6 | 7 | 8 |
 9 |         
10 | 文件名字: 11 | 文件: 12 | 13 |
14 | 15 | 下载 16 |
17 | 18 | -------------------------------------------------------------------------------- /file-upload-download/view/success.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 |
 9 |         

{{.}}write success

10 |
11 | 12 | -------------------------------------------------------------------------------- /file_chunk_upload_service/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | "os" 7 | 8 | chunk "github.com/sevenelevenlee/go-notes/file_chunk_upload_service/chunk_upload" 9 | ) 10 | 11 | func FileServer() { 12 | http.HandleFunc("/chunkUpload", chunk.ChunkFile) 13 | if err := http.ListenAndServe(":8001", nil); err != nil { 14 | log.Fatal("服务启动失败") 15 | os.Exit(-1) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /fmtstring.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func main() { 8 | var s1 interface{} = "123" 9 | var s2 []byte = []byte{'4', '5', '6'} 10 | fmt.Println(fmt.Sprintf("%s%s", s1, s2)) 11 | } 12 | -------------------------------------------------------------------------------- /func-Params/func-as-params.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | //函数是引用类型,传递的是地址 6 | //函数作为参数的demo 7 | func demo(iner func(name string)) { 8 | fmt.Println("demo started") 9 | iner("lee") 10 | } 11 | 12 | func main() { 13 | demo(func(name string){ 14 | fmt.Println("name is ", name) 15 | }) 16 | } 17 | -------------------------------------------------------------------------------- /func_option_design/func_option_design.go: -------------------------------------------------------------------------------- 1 | package func_option_design 2 | 3 | type generatorOpt struct { 4 | useAllExportedFields bool 5 | throwErrorOnCycle bool 6 | schemaCustomizer SchemaCustomizerFn 7 | } 8 | 9 | type Option func(opt *generatorOpt) 10 | 11 | //callback func 12 | type SchemaCustomizerFn func(name string) error 13 | 14 | func UseAllExportedFields() Option { 15 | return func(opt *generatorOpt) { 16 | opt.useAllExportedFields = false 17 | } 18 | } 19 | 20 | func ThrowErrorOnCycle() Option { 21 | return func(opt *generatorOpt) { 22 | opt.throwErrorOnCycle = true 23 | } 24 | } 25 | 26 | func schemaCustomizer(sc SchemaCustomizerFn) Option { 27 | return func(opt *generatorOpt) { 28 | opt.schemaCustomizer = sc 29 | } 30 | } 31 | 32 | //构造struct generatorOpt 33 | func GenerateOpt(ops ...Option) *generatorOpt { 34 | gopt := &generatorOpt{} 35 | for _, fn := range ops { 36 | fn(gopt) 37 | } 38 | return gopt 39 | } 40 | -------------------------------------------------------------------------------- /generate-stack.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | const STACK_INIT_SIZE = 100 4 | 5 | type Stack struct { 6 | list *List 7 | len int 8 | } 9 | 10 | type List struct { 11 | Data int 12 | Next *List 13 | } 14 | func InitStack() *Stack { 15 | return &Stack{ 16 | &List{}, 17 | 1, 18 | } 19 | } 20 | 21 | func (s *Stack) push(value int) { 22 | l := &List{Data: value} 23 | curl := s.list 24 | for curl.Next != nil { 25 | curl = curl.Next 26 | } 27 | curl.Next = l 28 | s.len += 1 29 | } 30 | 31 | func (s *Stack) pop() { 32 | pre := s.list 33 | curl := s.list.Next 34 | for curl.Next != nil { 35 | curl = curl.Next 36 | pre = pre.Next 37 | } 38 | pre.Next = nil 39 | s.len -= 1 40 | } 41 | //func main() { 42 | // s := InitStack() 43 | // s.push(1) 44 | // s.push(2) 45 | // fmt.Println(s.len) 46 | // s.pop() 47 | // s.pop() 48 | // fmt.Println(s.len) 49 | //} -------------------------------------------------------------------------------- /go-close-func/closure_func_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | //func TestDeferPrint(t *testing.T) { 8 | // DeferPrint() 9 | //} 10 | 11 | func TestProcessFunc(t *testing.T) { 12 | s := ProcessFunc() 13 | for _, v := range s { 14 | v() 15 | } 16 | } 17 | 18 | 19 | func TestProcessFunc1(t *testing.T) { 20 | s := ProcessFunc1() 21 | for _, v := range s { 22 | v() 23 | } 24 | } -------------------------------------------------------------------------------- /go-etcd/client/transport/transport.go: -------------------------------------------------------------------------------- 1 | package transport 2 | 3 | import ( 4 | "context" 5 | "net/http" 6 | "strconv" 7 | ) 8 | 9 | // 产品详情请求的参数 /product/id 10 | type ProductDetailRequest struct { 11 | ProductId int 12 | } 13 | 14 | func ProductDetailEncode(ctx context.Context, httpRequest *http.Request, requestParam interface{}) error { 15 | pdr := requestParam.(ProductDetailRequest) 16 | httpRequest.URL.Path += "/product/" + strconv.Itoa(pdr.ProductId) 17 | return nil 18 | } 19 | -------------------------------------------------------------------------------- /go-etcd/client/utils/endpoint.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "context" 5 | "net/http" 6 | ) 7 | 8 | // 发关Http请求的函数 requestParam请求参数 responseResult响应结果 9 | type EndPoint func(ctx context.Context, requestParam interface{}) (responseResult interface{}, err error) 10 | 11 | // 解析Http请求函数 12 | type EncodeRequest func(context.Context, *http.Request, interface{}) error 13 | -------------------------------------------------------------------------------- /go-local-cache/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/patrickmn/go-cache" 6 | "time" 7 | ) 8 | 9 | func main() { 10 | c := cache.New(1*time.Minute, 5*time.Minute) 11 | 12 | // Set the value of the key "foo" to "bar", with the default expiration time 13 | c.Set("foo", 1, cache.DefaultExpiration) 14 | 15 | // Set the value of the key "baz" to 42, with no expiration time 16 | // (the item won't be removed until it is re-set, or removed using 17 | // c.Delete("baz") 18 | //c.Set("baz", 42, cache.NoExpiration) 19 | 20 | // Get the string associated with the key "foo" from the cache 21 | foo, found := c.Get("foo") 22 | if found { 23 | fmt.Println(foo) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /go-web/net-http-web/http-handlefunc.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func test(w http.ResponseWriter, r *http.Request) { 6 | w.Write([]byte("测试handle func 函数")) 7 | } 8 | func handleFunc() { 9 | server := http.Server{Addr: "localhost:3002"} 10 | http.HandleFunc("/test", test) 11 | server.ListenAndServe() 12 | } 13 | -------------------------------------------------------------------------------- /go-web/net-http-web/http-handler.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | type FHandler struct{} 6 | type SHandler struct{} 7 | 8 | func (f *FHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 9 | w.Write([]byte("第一个handler")) 10 | } 11 | 12 | func (s *SHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 13 | w.Write([]byte("第二个handler")) 14 | } 15 | 16 | func handler() { 17 | f := FHandler{} 18 | s := SHandler{} 19 | 20 | server := http.Server{Addr: "localhost:8899"} 21 | http.Handle("/first", &f) 22 | http.Handle("/second", &s) 23 | server.ListenAndServe() 24 | } 25 | -------------------------------------------------------------------------------- /go-web/net-http-web/request-params.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "reflect" 7 | ) 8 | 9 | func FetchParamWithstandardLib() { 10 | server := http.Server{Addr: "localhost:8899"} 11 | http.HandleFunc("/param", param) 12 | server.ListenAndServe() 13 | } 14 | 15 | func param(w http.ResponseWriter, r *http.Request) { 16 | w.Write([]byte("获取header信息")) 17 | //获取header信息 map[key]sring 18 | header := r.Header 19 | fmt.Println(header) 20 | fmt.Fprintln(w, "header信息: ", header) 21 | fmt.Println(reflect.TypeOf(header["Accept-Encoding"]).String()) 22 | for _, v := range header["Accept-Encoding"] { 23 | fmt.Println(v) 24 | } 25 | fmt.Println("----", r.FormValue("test")) 26 | //获取请求参数, 需要先解析 27 | r.ParseForm() 28 | fmt.Println(r.Form) 29 | fmt.Fprintln(w, r.Form["test"][0]) 30 | 31 | //通过formvalue取值 32 | fmt.Fprintln(w, r.FormValue("test")) 33 | } 34 | -------------------------------------------------------------------------------- /go-web/static-app/delivery-func.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "html/template" 6 | "net/http" 7 | "time" 8 | ) 9 | 10 | func MyFunc(t string) string { 11 | m, _ := time.Parse("2006-01-02 15:04:05", t) 12 | fmt.Println(m) 13 | m = m.Add(60 * time.Second) 14 | fmt.Println(m) 15 | return m.Format("2006-01-02 15:04:05") 16 | } 17 | 18 | func funcParam(w http.ResponseWriter, request *http.Request) { 19 | //把自定义函数绑定到FuncMap上 20 | funcmap := template.FuncMap{"mfunc": MyFunc} 21 | t := template.New("test.html").Funcs(funcmap) 22 | //解析模版 23 | t, _ = t.ParseFiles("view/test.html") 24 | time := "2020-05-10 10:50:00" 25 | t.Execute(w, time) 26 | } 27 | -------------------------------------------------------------------------------- /go-web/static-app/static/javascript/index.js: -------------------------------------------------------------------------------- 1 | function alertbutton() { 2 | alert("{{.}}") 3 | } 4 | -------------------------------------------------------------------------------- /go-web/static-app/view/content.html: -------------------------------------------------------------------------------- 1 | {{define "content"}} 2 | 3 | 4 | 5 | 6 | Title 7 | 8 | 9 |
10 |     {{template "header" "这是header"}}
11 | content的信息
12 | {{template "footer" "这是footer"}} 13 |
14 | 15 | 16 | {{end}} 17 | -------------------------------------------------------------------------------- /go-web/static-app/view/cookie.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 生产Cookie
9 | 获取cookie
10 | {{.}} 11 | 12 | 13 | -------------------------------------------------------------------------------- /go-web/static-app/view/footer.html: -------------------------------------------------------------------------------- 1 | {{define "footer"}} 2 | 3 | 4 | 5 | 6 | Title 7 | 8 | 9 | footer的信息:{{.}} 10 | 11 | 12 | {{end}} -------------------------------------------------------------------------------- /go-web/static-app/view/header.html: -------------------------------------------------------------------------------- 1 | {{define "header"}} 2 | 3 | 4 | 5 | 6 | Title 7 | 8 | 9 | header的信息:{{.}} 10 | 11 | 12 | {{end}} 13 | -------------------------------------------------------------------------------- /go-web/static-app/view/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 9 |

静态文件template demo

10 |
尊敬的{{.}}男士/女士
11 |         {{.user.Name}}
12 |         {{.user.Age}}
13 |         {{.money}}
14 |     
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /go-web/static-app/view/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 |
 9 | 
10 | 
11 |         
12 |         自定义函数的时间: {{mfunc .}}
13 |     
14 | 15 | -------------------------------------------------------------------------------- /golang-gc/gc-not-release.go: -------------------------------------------------------------------------------- 1 | package gcunreleased 2 | 3 | //1. 字符串与截取的字串共享,暂时性泄露 4 | var s0 string //包级变量 5 | 6 | func f(s string) { 7 | s0 = s[:50] 8 | //s0和s共享一个内存块, 到这里只有50个字节需要使用,s其他部分无法释放,需要s0在其他地方被重新修改为止 9 | } 10 | 11 | func demo() { 12 | s := "abcedfghijkcclskjsuhdksls" 13 | f(s) 14 | } 15 | 16 | /* 17 | 解决办法,转化成字节切片处理,然后再转化回来 18 | s0 = string([]byte(s[:50])) 19 | */ 20 | 21 | //2. 子切片造成的暂时性内存泄露 22 | var ss []int 23 | 24 | func g(s1 []int) { 25 | // 假设s1的长度远大于30。ss与s1共享切片,所以在ss被重新赋值之前,s1不会被释放 26 | ss = s1[len(s1)-30:] 27 | } 28 | /* 29 | 通过append方法处理 30 | ss = append(s1[:0:0], s1[len(s1)-30:]...) 31 | */ 32 | 33 | //3. goroutine被永久阻塞会造成永久性内存泄露 -------------------------------------------------------------------------------- /golang-learn/base64-encode.go: -------------------------------------------------------------------------------- 1 | //使用内置库encoding/base64编码 2 | package main 3 | 4 | import ( 5 | "encoding/base64" 6 | "fmt" 7 | "log" 8 | ) 9 | 10 | func base64Demo() { 11 | input := []byte("hello go") 12 | 13 | // base64编码 14 | encodeString := base64.StdEncoding.EncodeToString(input) 15 | fmt.Println(encodeString) 16 | 17 | // base64解码 18 | decodeBytes, err := base64.StdEncoding.DecodeString(encodeString) 19 | if err != nil { 20 | log.Fatalln(err) 21 | return 22 | } 23 | fmt.Println(string(decodeBytes)) 24 | 25 | // url中,需要使用URLEncoding 26 | } 27 | -------------------------------------------------------------------------------- /golang-learn/defer-add-item-to-slice.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type MSlice []int 6 | 7 | func NewSlice() MSlice { 8 | return make(MSlice, 0) 9 | } 10 | 11 | func (s *MSlice) Add(elem int) *MSlice { 12 | *s = append(*s, elem) 13 | fmt.Print(elem) 14 | return s 15 | } 16 | 17 | /* 18 | func main() { 19 | s := NewSlice() 20 | defer s.Add(1).Add(2).Add(3) 21 | s.Add(4) 22 | } 23 | # 1 2 4 3 24 | */ 25 | 26 | type A struct { 27 | X int `json:"x"` 28 | } 29 | -------------------------------------------------------------------------------- /golang-learn/image-process.go: -------------------------------------------------------------------------------- 1 | //golang图片处理剪切,base64数据转换,文件存储 2 | package main 3 | 4 | import ( 5 | "encoding/base64" 6 | ) 7 | 8 | const base64Table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" 9 | 10 | var coder = base64.NewEncoding(base64Table) 11 | 12 | func Base64Encode(encode_byte []byte) []byte { 13 | return []byte(coder.EncodeToString(encode_byte)) 14 | } 15 | 16 | /* 17 | func main() { 18 | file, err := os.Open("/Users/richctrl/Downloads/test.jpg") 19 | if err != nil { 20 | log.Fatal(err) 21 | } 22 | data, err := ioutil.ReadAll(file) 23 | if err != nil { 24 | log.Fatal(err) 25 | } 26 | fmt.Printf("Data as string: %s\n", Base64Encode(data)) 27 | } 28 | */ 29 | -------------------------------------------------------------------------------- /golang-learn/init-map.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | /*map的声明和初始化 4 | map的key 可以是bool 数字 string 指针 channel struct array等可以比较类型 5 | 不能是slice map func 6 | */ 7 | 8 | type People struct { 9 | Name string 10 | } 11 | 12 | func mapDemo() { 13 | //1声明, 需要分配空间 14 | var peopleDB map[string]People 15 | peopleDB = make(map[string]People) 16 | peopleDB["1234"] = People{"lee"} 17 | //map的创建 18 | //使用make 19 | test := make(map[string]People) 20 | test["222"] = People{"test"} 21 | //创建并初始化 22 | peopleDB = map[string]People{ 23 | "123": People{"anne"}, 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /golang-learn/linked_list.go: -------------------------------------------------------------------------------- 1 | //使用结构体实现链表 2 | package main 3 | 4 | import ( 5 | "fmt" 6 | ) 7 | 8 | type Node struct { 9 | data int 10 | next *Node 11 | } 12 | 13 | //遍历 14 | func showNode(node *Node) { 15 | for node != nil { 16 | fmt.Println(*node) 17 | node = node.next 18 | } 19 | } 20 | 21 | /* 22 | func main() { 23 | head := new(Node) 24 | head.data = 1 25 | node1 := new(Node) 26 | node1.data = 2 27 | node2 := new(Node) 28 | node2.data = 3 29 | 30 | head.next = node1 31 | node1.next = node2 32 | 33 | showNode(head) 34 | 35 | // 链表的头节点插入 36 | head1 := &Node{data: 0} 37 | tail := head1 38 | for i := 1; i <= 10; i++ { 39 | var node = &Node{data: i} 40 | node.next = tail 41 | tail = node 42 | } 43 | showNode(tail) 44 | } 45 | */ 46 | -------------------------------------------------------------------------------- /golang-learn/new和make的区别.md: -------------------------------------------------------------------------------- 1 | /* 2 | new和make都在堆上分配内存 3 | 4 | new 函数分配内存,make 函数初始化 5 | 6 | new(T): 适用于值类型和结构体struct, 返回一个指针 &T{} 7 | 8 | make(T): 只用于内建的引用类型slice、map、channal 9 | 10 | 声明指针不会开辟内存地址,只是准备要指向内存某个空间, 11 | 而声明变量会开辟内存地址,准备存放内容.所以指针类型变量都是把一个变量的地址赋值给指针变量 12 | */ 13 | 14 | ```go 15 | 16 | // 代码示例 17 | package main 18 | 19 | import "fmt" 20 | 21 | func main() { 22 | // p == nil; with len and cap 0 23 | p := new([]int) 24 | fmt.Println(p) 25 | 26 | // v is initialed with len 10, cap 50 27 | v := make([]int, 10, 20) 28 | fmt.Println(v) 29 | 30 | /*********Output**************** 31 | &[] 32 | [0 0 0 0 0 0 0 0 0 0] 33 | *********************************/ 34 | //(*p)[0] = 1 //会报错panic: runtime error: index out of range, because p is a nil pointer, with len and cap 0 35 | v[1] = 18 36 | 37 | i := new(string) 38 | *i = "123" 39 | fmt.Println(*i) 40 | 41 | var m *int 42 | n := 1 43 | m = &n 44 | fmt.Println(*m) 45 | } 46 | -------------------------------------------------------------------------------- /golang-learn/rand-goroutine.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "runtime" 6 | "sync" 7 | ) 8 | 9 | //gorountine 的随机性和闭包 10 | func closePackage() { 11 | runtime.GOMAXPROCS(1) 12 | wg := sync.WaitGroup{} 13 | wg.Add(20) 14 | //外部for循环的变量i, 地址不变化, 最后i=10, go引用的是外部变量i 15 | for i := 0; i < 10; i++ { 16 | go func() { 17 | fmt.Println("A:", i) 18 | wg.Done() 19 | }() 20 | } 21 | //i为函数参数,函数值拷贝后,go func内部指向值拷贝地址 22 | for i := 0; i < 10; i++ { 23 | go func(i int) { 24 | fmt.Println("B:", i) 25 | wg.Done() 26 | }(i) 27 | } 28 | wg.Wait() 29 | } 30 | -------------------------------------------------------------------------------- /golang-learn/rm-item-from-slice.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | type Slice []interface{} 8 | 9 | func (s *Slice) Remove(value interface{}) error { 10 | for i, v := range *s { 11 | if isEqual(value, v) { 12 | *s = append((*s)[:i], (*s)[i+1:]...) 13 | return nil 14 | } 15 | } 16 | return errors.New("not exist") 17 | } 18 | 19 | func isEqual(a, b interface{}) bool { 20 | return a == b 21 | } 22 | -------------------------------------------------------------------------------- /golang-learn/select-overtime/select-overtime.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func main(){ 9 | timeout := make(chan bool, 1) 10 | 11 | go func() { 12 | time.Sleep(time.Second) 13 | timeout <- true 14 | }() 15 | 16 | select { 17 | case <- timeout: 18 | fmt.Println("exceed time") 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /golang-learn/set.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "sync" 4 | 5 | type inter interface{} 6 | 7 | type Set struct { 8 | m map[inter]bool 9 | sync.RWMutex 10 | } 11 | 12 | func New() *Set { 13 | return &Set{ 14 | m: map[inter]bool{}, 15 | } 16 | } 17 | 18 | func (s *Set) Add(item inter) { 19 | s.Lock() 20 | defer s.Unlock() 21 | s.m[item] = true 22 | } 23 | -------------------------------------------------------------------------------- /golang-learn/string_join.go: -------------------------------------------------------------------------------- 1 | //字符串的链接方式 2 | package main 3 | 4 | import ( 5 | "bytes" 6 | "fmt" 7 | "strings" 8 | ) 9 | 10 | //使用+号拼接 11 | func AddStringWithOperator() string { 12 | hello := "hello" 13 | world := "world" 14 | result := hello + world 15 | return result 16 | } 17 | 18 | //使用fmt.Sprintf拼接,包含数字之类的时候使用此方法 19 | func ConnectStringWithNum(first string, last int) string { 20 | first = first 21 | last = last 22 | result := fmt.Sprintf("%s d%", first, last) 23 | return result 24 | } 25 | 26 | //string.Join 27 | func JoinString(first, last string) string { 28 | first = first 29 | last = last 30 | return strings.Join([]string{first, last}, "") 31 | } 32 | 33 | //buffer.WriteString() 34 | func ConnectStringWithBuffer(first, last string) string { 35 | var buffer bytes.Buffer 36 | buffer.WriteString(first) 37 | buffer.WriteString(last) 38 | return buffer.String() 39 | } 40 | -------------------------------------------------------------------------------- /golang-learn/switch-and-select/select-timeout.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func main() { 9 | timeout := make(chan bool, 1) 10 | 11 | go func() { 12 | time.Sleep(2 * time.Second) 13 | timeout <- true 14 | }() 15 | 16 | ch := make(chan int) 17 | select { 18 | case <-ch: 19 | case <-timeout: 20 | println("time out issue 1") 21 | //或使用time.After机制,回传chan time.Time 22 | case <-time.After(time.Second * 1): 23 | println("time out after") 24 | } 25 | 26 | //多个channel读取, 使用for + select机制实现 27 | i := 0 28 | ch0 := make(chan string) 29 | defer func() { 30 | close(ch0) 31 | }() 32 | 33 | go func() { 34 | LOOP: 35 | for { 36 | time.Sleep(1 * time.Second) 37 | fmt.Println(time.Now().Unix()) 38 | i++ 39 | select { 40 | case m := <-ch: 41 | println(m) 42 | break LOOP 43 | default: 44 | println(i) 45 | } 46 | } 47 | }() 48 | 49 | time.Sleep(time.Second * 4) 50 | ch0 <- "stop" 51 | } 52 | -------------------------------------------------------------------------------- /golang-learn/switch-and-select/switch.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | //switch用法:用于类型判断 4 | 5 | func convert(i interface{}) { 6 | switch t := i.(type) { 7 | case int: 8 | println("i is int", t) 9 | case string: 10 | println("i is string", t) 11 | default: 12 | println("type not found") 13 | } 14 | } 15 | 16 | /* 17 | func main() { 18 | var i interface{} 19 | i = 100 20 | convert(i) 21 | i = "abc" 22 | convert(i) 23 | i = []int{1,2,3,4} 24 | convert(i) 25 | } 26 | */ 27 | -------------------------------------------------------------------------------- /golang-learn/with-context-pack-func.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "sync" 4 | 5 | //函数重复的部分,封装到一个函数withContext中,函数作为参数,在调用者的上下文来调用withContext 6 | 7 | func withContext(fn func()) { 8 | mu := new(sync.Mutex) 9 | mu.Lock() 10 | defer mu.Unlock() 11 | fn() 12 | } 13 | 14 | func bar() { 15 | withContext(func() { 16 | // do some action for bar 17 | }) 18 | } 19 | 20 | type DB struct { 21 | 22 | } 23 | //数据库链接 24 | func withDBContext(fn func(db *DB) error) error{ 25 | // 从连接池获取一个数据库连接 26 | dbConn := NewDB() 27 | return fn(dbConn) 28 | } 29 | 30 | func NewDB() *DB{ 31 | return &DB{} 32 | } -------------------------------------------------------------------------------- /golang-learn/引用类型and值类型.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | Golang中只有三种引用类型:slice、map、channel 7 | 在函数调用时,像切片(slice)、字典(map)、接口(interface)、通道(channel)这样的引用类型都是默认使用引用传递(即使没有显式的指出指针)。 8 | 引用类型理解为指针:堆存储, 引用的是地址 9 | 10 | 值类型:值的拷贝, 值存储在内存的栈中 11 | */ 12 | 13 | 14 | //值类型和引用类型的区别,用数组和slice例子 15 | func main() { 16 | //值类型 17 | a := [5]int{1,2,3,4,5} 18 | b := a 19 | c := new([3]int) 20 | b[2] = 6 21 | fmt.Println(a, b, cap(c)) 22 | 23 | //引用类型 24 | d := make([]int, 5) 25 | d = []int{1,2,3,4} 26 | fmt.Println(d, len(d), cap(d)) 27 | 28 | e := new([]int) // 返回指针&T{} 29 | fmt.Println(len(*e)) 30 | } -------------------------------------------------------------------------------- /golang-lib-use/filetype/checkFileType.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io/ioutil" 7 | "strings" 8 | 9 | "github.com/h2non/filetype" 10 | ) 11 | 12 | func main() { 13 | buf, _ := ioutil.ReadFile("/Users/lee/workspace/pcapfiles/files/test.docx") 14 | 15 | kind, _ := filetype.Match(buf) 16 | if kind == filetype.Unknown { 17 | fmt.Println("Unknown file type") 18 | return 19 | } 20 | 21 | fmt.Printf("File type: %s. MIME: %s\n", kind.Extension, kind.MIME.Value) 22 | 23 | test := "xlsx,pdf,txt,docx,pptx,zip,rar,7z,odt,rtf" 24 | if strings.Contains(test, "") { 25 | fmt.Println("1") 26 | } 27 | type UserRequest struct { 28 | BodyMap string `json:"Body"` 29 | } 30 | 31 | p := UserRequest{ 32 | BodyMap: "我是body map", 33 | } 34 | obj, err := json.Marshal(p) 35 | if err != nil { 36 | fmt.Println(err) 37 | } 38 | fmt.Println(string(obj)) 39 | 40 | } 41 | -------------------------------------------------------------------------------- /golang-lib-use/flag/flag.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | ) 8 | 9 | var ( 10 | name = flag.String("name", "Tom", "Input your name") 11 | age = flag.Int("age", 18, "Input your age") 12 | f = flag.Bool("isVIP", false, "Is VIP") 13 | postCode int 14 | ) 15 | 16 | func init() { 17 | flag.IntVar(&postCode, "postcode", 1234, "Input your post code") 18 | } 19 | 20 | func main() { 21 | flag.Parse() 22 | 23 | fmt.Println("name:", *name) 24 | fmt.Println("age:", *age) 25 | fmt.Println("VIP:", *f) 26 | fmt.Println("postCode:", postCode) 27 | 28 | fmt.Println("tail:", flag.Args()) 29 | fmt.Println(flag.NArg()) 30 | fmt.Println(flag.NFlag()) 31 | 32 | args := os.Args 33 | fmt.Println("Args:", args) 34 | 35 | //paramCnt := flag.NArg() 36 | //for cnt := 0; cnt < paramCnt; cnt++ { 37 | // fmt.Println(flag.Arg(cnt)) 38 | //} 39 | } -------------------------------------------------------------------------------- /golang-lib-use/go-option-design/type-func/type-func.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | //funcOption 将func(int) int 的函数转换成 funcOption 类型 8 | 9 | type funcOption func(int) int 10 | 11 | func sum(i int) int { 12 | return i * 2 13 | } 14 | 15 | func main() { 16 | option := funcOption(sum) 17 | m := option(2) 18 | fmt.Println(m) 19 | fd := SetInsecure() 20 | di := new(dialOption) 21 | fd.apply(di) 22 | fmt.Println(di) 23 | } 24 | 25 | //定一个func 26 | type funcDial func(*dialOption) 27 | 28 | func (fd funcDial) apply(do *dialOption) { 29 | fd(do) 30 | } 31 | 32 | //对外的接口 33 | func SetInsecure() DialOption { 34 | return funcDial(func(d *dialOption){ 35 | d.insecure = true 36 | }) 37 | } 38 | 39 | type dialOption struct { 40 | insecure bool 41 | timeout time.Duration 42 | } 43 | 44 | type DialOption interface { 45 | apply(*dialOption) 46 | } -------------------------------------------------------------------------------- /golang-lib-use/net-http-attention-issue/http_client_useing.go: -------------------------------------------------------------------------------- 1 | package net_http_attention_issue 2 | 3 | import ( 4 | "net" 5 | "net/http" 6 | "time" 7 | ) 8 | 9 | //1. 默认的HttpClient不包含请求超时时间,如果你使用http.Get(url)或者&Client{}, 这将会使用http.DefaultClient,这个结构体内no timeout 10 | func NewClient() *http.Client { 11 | return &http.Client{ 12 | Timeout: 10 * time.Second, 13 | } 14 | } 15 | 16 | //2. go的Transport 可理解为连接池中的连接, 不要使用默认Transport,增加MaxIdleConnsPerHost 17 | var DefaultTransport http.RoundTripper = &http.Transport{ 18 | Proxy: nil, 19 | DialContext: (&net.Dialer{ 20 | Timeout: 30 * time.Second, 21 | KeepAlive: 30 * time.Second, //KeepAlive是tcp探活的时间间隔,并不是我们HTTP连接复用的 Keep-Alive 22 | }).DialContext, 23 | ForceAttemptHTTP2: true, 24 | MaxIdleConns: 100, //Http Client连接池有100个连接 25 | IdleConnTimeout: 90 * time.Second, //每个连接默认的空闲时间90s(90s内有请求过来,可以复用该连接) 26 | TLSHandshakeTimeout: 10 * time.Second, 27 | ExpectContinueTimeout: 1 * time.Second, 28 | } 29 | -------------------------------------------------------------------------------- /golang-lib-use/sync.Map源码.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "sync" 5 | "sync/atomic" 6 | "unsafe" 7 | ) 8 | 9 | //Map底层的数据结构 10 | type Map struct { 11 | mu sync.Mutex 12 | read atomic.Value // readOnly 13 | dirty map[interface{}]*entry 14 | misses int 15 | } 16 | 17 | // Map.read 属性实际存储的是 readOnly 18 | type readOnly struct { 19 | m map[interface{}]*entry 20 | amended bool // 则会判断 read.readOnly 中的 amended 属性,他会告诉程序 dirty 是否包含 read.readOnly.m 中没有的数据;因此若存在,也就是 amended 为 true,将会进一步到 dirty 中查找数据 21 | } 22 | 23 | type entry struct { 24 | p unsafe.Pointer // *interface{} 25 | } 26 | 27 | /* 28 | read 和 dirty 各自维护一套 key,key 指向的都是同一个 value。也就是说,只要修改了这个 entry,对 read 和 dirty 都是可见的 29 | mu: 保护read 和dirty 30 | read: 只读数据,指出并发读取 (atomic.Value 类型) 。如果需要更新 read,需要加锁保护数据安全。 31 | read 实际存储的是 readOnly 结构体,内部是一个原生 map,amended 属性用于标记 read 和 dirty 的数据是否一致 32 | dirty: 读写数据,非线性安全的原生 map。包含新sy写入的 key,并且包含 read 中所有未被删除的 key 33 | misses: 统计有多少次读取 read 没有被命中。每次 read 读取失败后,misses 的计数加 1 34 | */ 35 | -------------------------------------------------------------------------------- /golang-lib-use/sync.Once.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | /* 4 | sync.Once是sync包的一个结构体 5 | type Once struct { 6 | m Mutex 7 | done uint32 8 | } 9 | 10 | func (o *Once) Do(f func()) { 11 | if atomic.LoadUint32(&o.done) == 1 { 12 | return 13 | } 14 | // Slow-path. 15 | o.m.Lock() 16 | defer o.m.Unlock() 17 | if o.done == 0 { 18 | defer atomic.StoreUint32(&o.done, 1) 19 | f() 20 | } 21 | } 22 | 23 | 使用场景: 24 | 在程序多次调用的地方只想执行一次某代码块,可以全局声明一个once,使用once.Do()来执行次代码块 25 | */ 26 | import ( 27 | "fmt" 28 | "sync" 29 | "time" 30 | ) 31 | 32 | func demo() { 33 | var once sync.Once 34 | 35 | for i := 0; i <= 10; i++ { 36 | go once.Do(func() { 37 | fmt.Println("hello go") 38 | }) 39 | } 40 | 41 | time.Sleep(time.Second * 2) 42 | } 43 | -------------------------------------------------------------------------------- /golang-oop-idea/go-oop-summary.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | 1.golang中的继承是通过struct匿名组合来实现的; 7 | 2.多态是通过接口来实现的 8 | 3.struct与interface之间是隐形继承的 9 | 4.接口是对继承的一种补充 10 | 5.继承主要解决代码的复用性和可维护性 11 | 6.接口的价值设计各种规范,让其他struct实现这些方法,多态上多些 12 | */ 13 | //demo 猴子天生会爬树, 通过学习学会飞行和游泳 14 | type Monkey struct { 15 | Name string 16 | } 17 | 18 | func (m *Monkey) Climbing() { 19 | fmt.Println(m.Name, "天生会爬树") 20 | } 21 | 22 | type LittleMOnkey struct { 23 | Monkey //匿名字段实现继承 24 | } 25 | 26 | func (lm LittleMOnkey) Flying(){ 27 | fmt.Println(lm.Name, " 通过学习会飞翔...") 28 | } 29 | 30 | func (lm LittleMOnkey) Swimming(){ 31 | fmt.Println(lm.Name, " 通过学习会游泳...") 32 | } 33 | 34 | func main() { 35 | lm := LittleMOnkey{Monkey{"悟空"}} 36 | lm.Climbing() 37 | lm.Flying() 38 | lm.Swimming() 39 | } 40 | -------------------------------------------------------------------------------- /golang-sort/sort-slice.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | ) 7 | 8 | //sort满足以下接口 9 | /* 10 | type Interface interface { 11 | Len() int 12 | 13 | Less(i, j int) int 14 | 15 | Swap(i, j int) 16 | } 17 | */ 18 | type Man struct { 19 | Age int 20 | } 21 | 22 | type manSlice []Man 23 | 24 | func (ms manSlice) Len() int { 25 | return len(ms) 26 | } 27 | 28 | func (ms manSlice) Less(i, j int) bool { 29 | return ms[i].Age < ms[j].Age 30 | } 31 | 32 | func (ms manSlice) Swap(i, j int) { 33 | ms[i], ms[j] = ms[j], ms[i] 34 | } 35 | 36 | func main() { 37 | manslice := []Man{{5}, {4}, {3}} 38 | sort.Sort(manSlice(manslice)) 39 | fmt.Println(manslice) 40 | } 41 | -------------------------------------------------------------------------------- /grpc-example/grpc-theory_test.go: -------------------------------------------------------------------------------- 1 | package grpc_example 2 | 3 | import "testing" 4 | 5 | func TestDemo(t *testing.T) { 6 | Demo() 7 | } 8 | -------------------------------------------------------------------------------- /grpc-example/hello/hello.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package hello; 4 | 5 | service Hello { 6 | rpc SayHello (HelloRequest) returns (HelloReply) {} 7 | } 8 | 9 | message HelloRequest { 10 | string Name = 1; 11 | } 12 | 13 | message UploadParams { 14 | string setname = 1; 15 | string name = 2; 16 | int64 range_start = 3; 17 | int64 range_end = 4; 18 | bytes content = 5; 19 | } 20 | 21 | message UploadResult { 22 | string data_file_path = 1; 23 | string data_info_file_path =2; 24 | } 25 | 26 | message HelloReply { 27 | string Message = 1; 28 | } 29 | 30 | option go_package = "./hello;hello"; 31 | -------------------------------------------------------------------------------- /grpc-example/server/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "github.com/sevenelevenlee/go-notes/grpc-example/hello" 7 | "google.golang.org/grpc" 8 | "log" 9 | "net" 10 | ) 11 | 12 | const ( 13 | address = ":8848" 14 | ) 15 | 16 | type Server struct { 17 | } 18 | 19 | func (s *Server) SayHello(ctx context.Context, in *hello.HelloRequest) (*hello.HelloReply, error) { 20 | return &hello.HelloReply{ 21 | Message: "hello," + in.Name, 22 | }, nil 23 | } 24 | func main() { 25 | conn, err := net.Listen("tcp", address) 26 | if err != nil { 27 | log.Fatal(err) 28 | } 29 | fmt.Println("grpc server listening at: 8848 port") 30 | server := grpc.NewServer() 31 | hello.RegisterHelloServer(server, &Server{}) 32 | server.Serve(conn) 33 | } 34 | -------------------------------------------------------------------------------- /http表单/postForm.go: -------------------------------------------------------------------------------- 1 | package form 2 | 3 | import ( 4 | "net/http" 5 | "net/url" 6 | "strings" 7 | ) 8 | 9 | func PostWithForm() { 10 | payload := make(url.Values) 11 | payload.Add("name", "lee") 12 | payload.Add("password", "") 13 | req, _ := http.NewRequest( 14 | http.MethodPost, 15 | "", 16 | strings.NewReader(payload.Encode()), 17 | ) 18 | req.Header.Add("Content-Type", "application/x-www-form-urlencoded") 19 | 20 | _, _ = http.DefaultClient.Do(req) 21 | } 22 | 23 | //use http postform 24 | func postForm() { 25 | payload := make(url.Values) 26 | payload.Add("name", "poloxue") 27 | payload.Add("password", "123456") 28 | _, _ = http.PostForm("http://httpbin.org/post", payload) 29 | } 30 | -------------------------------------------------------------------------------- /img/GPM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/img/GPM.png -------------------------------------------------------------------------------- /inherit/struct_inherit.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | //标准组合关系 6 | /* 7 | type People struct { 8 | name string 9 | age int 10 | } 11 | 12 | type Teacher struct { 13 | people People 14 | classroom string 15 | } 16 | 17 | func main() { 18 | teacher := Teacher{People{"lee", 17}, "三年二班"} 19 | fmt.Println(teacher) 20 | } 21 | */ 22 | 23 | //使用匿名属性完成Go语言中的继承 24 | type People struct { 25 | name string 26 | age int 27 | } 28 | 29 | type Teacher struct { 30 | People //匿名组合 31 | classroom string //班级 32 | } 33 | 34 | func main() { 35 | teacher := Teacher{People{"smallming", 17}, "302教室"} 36 | fmt.Println(teacher.classroom, teacher.age, teacher.name) 37 | } 38 | -------------------------------------------------------------------------------- /inputReader-read-data-from-control/readInputfromos.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "os" 7 | ) 8 | 9 | var ( 10 | inputReader *bufio.Reader 11 | input string 12 | err error 13 | ) 14 | 15 | func main() { 16 | inputReader = bufio.NewReader(os.Stdin) 17 | fmt.Println("Please enter some input: ") 18 | for { 19 | input, err = inputReader.ReadString('\n') 20 | if err == nil { 21 | fmt.Printf("回音: %s\n", input) 22 | } 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /interface-and-struct-method/interface-learn.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | ) 7 | 8 | //interface与nil判等的问题 9 | //interface的内部包含type和value 10 | //interface==nil, 仅当type和value均为nil(nil, nil) 11 | 12 | //检查以下题目,type有值,value==nil 13 | type Animals interface { 14 | Meow() 15 | } 16 | 17 | type Catty struct { 18 | } 19 | 20 | func (*Catty) Meow() { 21 | fmt.Println("meow") 22 | } 23 | 24 | func GetAnimal() Animals { 25 | var catty *Catty 26 | catty = &Catty{} 27 | return catty 28 | } 29 | 30 | func demointerface() { 31 | var cat = GetAnimal() 32 | m := reflect.TypeOf(cat) 33 | fmt.Println(m) 34 | kind := m.Kind() 35 | fmt.Println(kind) 36 | } 37 | -------------------------------------------------------------------------------- /interface-and-struct-method/interface-method-set.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | //interface的methods set规则:*T和T都可是实现接口method的 6 | //值接收者(T)的方法, 结构体指针(*T)和值(T)都可以调用 7 | //指针接收者(*T)的方法, 只有结构体指针(*T)能调用 8 | 9 | //接口Valueer 10 | type Valueer interface { 11 | printf() 12 | } 13 | 14 | //value1和value2实现接口Valueer的方法 15 | type Value1 struct { 16 | num int 17 | } 18 | type Value2 struct { 19 | num int 20 | } 21 | 22 | //接收者为指针 23 | func (self *Value1) printf() { 24 | fmt.Println(self.num) 25 | } 26 | 27 | //接收者为结构体值 28 | func (self Value2) printf() { 29 | fmt.Println(self.num) 30 | } 31 | 32 | func intefaceMethodSet() { 33 | //声明接口变量 34 | var val Valueer 35 | //Value1赋值给val只能是指针型(*T) 36 | val = &Value1{num: 1} 37 | //调用方法 38 | val.printf() 39 | //Value2赋值给val可以是值(T), 也可以是指针(*T) 40 | val = Value2{num: 2} 41 | val = &Value2{num: 3} 42 | //调用方法 43 | val.printf() 44 | } 45 | -------------------------------------------------------------------------------- /interface-and-struct-method/interface和反射的理解.go: -------------------------------------------------------------------------------- 1 | package main 2 | /*Golang关于类型设计的一些原则 3 | 1·变量包括 (type, value) 两部分 4 | 。所以为什么nil != nil了 5 | 6 | 2·type包括static type 和 concrete type, 前者是编码过程中的类型(如int、string), 后者是runtime系统的类型 7 | 8 | 3·类型断言是否成功,取决于concrete type, 因此一个reader变量如果它的concrete type 也实现了write方法, 就可以断言为writer 9 | 10 | @反射主要与Golang的 interface 类型相关(它的 type 是concrete type),只有interface类型才有反射一说。 11 | 12 | @每个 interface 变量都有一个对应pair, interface{}类型的变量包含两个指针,一个指向值的的类型 concrete type, 另一个指向实际的值 value 13 | (value, type) 14 | 15 | 16 | // 创建类型为*os.File的变量,将其赋值给接口变量 17 | testfile, err := os.OpenFile("dev/test", os.O_RDWR, 0) 18 | // 将其赋值给接口变量 19 | var r io.Reader 20 | r = testfile 21 | 此时接口变量r的pair为(testfile, *os.File), 这个pair在接口变量连续赋值的过程中是不变的 22 | // 将r赋值给另一接口变量w 23 | var w io.Writer 24 | // 通过接口类型断言来赋值 25 | w = r.(io.Writer) //接口变量w的pair与r的pair相同,都是:(tty, *os.File 26 | 27 | //总结: 反射就是用来检测存储在接口变量内部(值value;类型concrete type) pair对的一种机制。 28 | */ 29 | -------------------------------------------------------------------------------- /interface-and-struct-method/point-value-struct-distinct.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | //方法的结构指针接收者和结构值接收者 6 | //结构指针接收者(*T)和值接收者(T)的方法集是互相继承的 7 | //区别在于:结构体指针(*T)可以改变对象的值 8 | 9 | type Cat struct { 10 | Name string 11 | Color string 12 | } 13 | //结构体指针类型接收者方法 14 | func (cat *Cat) Meow() { 15 | fmt.Println("Name:", cat.Name) 16 | } 17 | //结构体值接收者方法 18 | func (cat Cat) Eat() { 19 | fmt.Println("Color:", cat.Color) 20 | } 21 | func main() { 22 | //*T和T的方法集是互通的 23 | //值类型 24 | cat := Cat{Name: "a"} 25 | cat.Meow() 26 | cat.Eat() 27 | 28 | //指针类型 29 | cater := &Cat{"b", "black"} 30 | cater.Eat() 31 | cater.Meow() 32 | } -------------------------------------------------------------------------------- /interface_inherit/interface_inherit.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type Man struct { 6 | name string 7 | mile float64 8 | } 9 | 10 | type Live interface { 11 | run(run float64) 12 | //eat() 13 | Eat 14 | } 15 | 16 | //实现struct man继承接口Live 17 | //重写run和eat方法 18 | func (man *Man) run(mile float64) { 19 | fmt.Println("跑动了", mile, "公里") 20 | } 21 | 22 | func (man *Man) eat() { 23 | fmt.Println("一天吃两顿烦") 24 | } 25 | 26 | func main() { 27 | man := new(Man) 28 | man.name = "lee" 29 | man.mile = 200 30 | man.run(man.mile) 31 | } 32 | 33 | //实现接口的继承 34 | type Eat interface { 35 | eat() 36 | } 37 | 38 | type Child struct { 39 | 40 | } 41 | 42 | func (child Child) eat() { 43 | 44 | } 45 | -------------------------------------------------------------------------------- /ioutilpackage/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "os" 7 | ) 8 | 9 | /* 10 | func ReadAll(r io.Reader) ([]byte, error) 11 | func ReadFile(filename string) ([]byte, error) 12 | func WriteFile(filename string, data []byte, perm os.Filemode) error 13 | func ReadDir(dirname string) ([]os.FileInfo, error) 14 | */ 15 | //demo 16 | func main() { 17 | //ioutil.ReadAll 18 | file, err := os.Open("file") 19 | defer func() { 20 | file.Close() 21 | }() 22 | if err != nil { 23 | fmt.Println(err) 24 | return 25 | } 26 | b, err := ioutil.ReadAll(file) 27 | if err != nil { 28 | fmt.Println(err) 29 | return 30 | } 31 | fmt.Println(string(b)) 32 | 33 | //ioutil.ReadFile 34 | n, err := ioutil.ReadFile("file") 35 | fmt.Println(n) 36 | //ioutil.WriteFile 37 | ioutil.WriteFile("filename", []byte("111111"), 0666) 38 | //读取文件夹信息 ioutil.ReadDir() 39 | fileinfo, err := ioutil.ReadDir("/User") 40 | for _, file := range fileinfo { 41 | file.Name() 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /json/json-marshal-process-null.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | ) 7 | 8 | type User struct { 9 | Name string `json:"name"` 10 | Roles []Role `json:"roles"` 11 | } 12 | 13 | type Role struct { 14 | Name string 15 | } 16 | 17 | func avoidNull() { 18 | //初始化Role切片 避免返回null 19 | str := "" 20 | fmt.Println(str) 21 | user := User{Name: "lee", Roles: []Role{{Name: "test"}, {Name: "test2"}}} 22 | data, _ := json.Marshal(&user) 23 | fmt.Println(string(data)) 24 | b := `{"name":"lee","roles":[{"Name":"test"},{"Name":"test2"}]}` 25 | var u User 26 | err := json.Unmarshal([]byte(b), &u) 27 | if err != nil { 28 | fmt.Println(err) 29 | } 30 | fmt.Println(u) 31 | 32 | l := []int{1, 2, 3, 4, 5} 33 | for _, v := range l { 34 | if v > 3 { 35 | continue 36 | } 37 | fmt.Println(v) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /json/json-stream-rw.md: -------------------------------------------------------------------------------- 1 | #### JSON数据的流式读写 2 | ```go 3 | //go内建的encode/json包的Encoder和Decoder类型 4 | //func NewDecoder(r io.Reader) *Decoder 5 | //func NewEncoder(w io.Writer) *Encoder 6 | package main 7 | 8 | import ( 9 | "encoding/json" 10 | "log" 11 | "os" 12 | ) 13 | 14 | func main() { 15 | //从标准输入流中读取json 16 | dec := json.NewDecoder(os.Stdin) 17 | enc := json.NewEncoder(os.Stdout) 18 | for { 19 | var v map[string] interface{} 20 | if err := dec.Decode(&v); err != nil { 21 | log.Println(err) 22 | return 23 | } 24 | for k := range v { 25 | //字符串可以进行相等判断 26 | if k != "Title" { 27 | //删除map中的键 28 | delete(v, k) 29 | } 30 | } 31 | if err := enc.Encode(&v); err != nil { 32 | log.Println(err) 33 | return 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /jsonbenchmark/jsbench.go: -------------------------------------------------------------------------------- 1 | package jsonbenchmark 2 | -------------------------------------------------------------------------------- /list/list_struct.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | /* 4 | type List struct { 5 | root Element 6 | len int 7 | } 8 | 9 | type Element struct { 10 | next, prev *Element 11 | list *List 12 | Value interface{} 13 | } 14 | */ 15 | 16 | -------------------------------------------------------------------------------- /logger.log: -------------------------------------------------------------------------------- 1 | [info] 2 | 18:33:48 输出日志信息 3 | [info] 4 | 18:34:34 输出日志信息 5 | [info] 6 | 18:34:39 输出日志信息 7 | [info] 8 | 18:34:40 输出日志信息 9 | [info] 10 | 18:36:38 输出日志信息 11 | [info] 12 | 18:36:50 输出日志信息 13 | -------------------------------------------------------------------------------- /logger/logger.log: -------------------------------------------------------------------------------- 1 | [info] 2 | 12:09:16 输出日志信息 3 | [info] 4 | 12:09:34 输出日志信息 5 | [info] 6 | 18:42:19 输出日志信息 7 | [info] 8 | 18:42:36 输出日志信息 9 | [info] 10 | 18:42:49 输出日志信息 11 | [info] 12 | 18:44:24 输出日志信息 13 | [info] 14 | 18:49:40 输出日志信息 15 | [info] 16 | 18:50:19 输出日志信息 17 | [info] 18 | 17:44:09 输出日志信息 19 | [info] 20 | 17:45:46 输出日志信息 21 | [info] 22 | 08:09:32 输出日志信息 23 | [info] 24 | 08:11:05 输出日志信息 25 | [info] 26 | 08:11:59 输出日志信息 27 | -------------------------------------------------------------------------------- /map-concurrent-process/use-chan-process-current-map.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | /** * 并发编程,map的线程安全性问题,使用channel的方式 */ 4 | import ( 5 | "fmt" 6 | "time" 7 | ) 8 | 9 | var dataCh map[int]int = make(map[int]int) 10 | var chMap chan int = make(chan int) 11 | func main() { 12 | // 并发启动的协程数量 13 | max := 10000 14 | time1 := time.Now().UnixNano() 15 | 16 | for i := 0; i < max; i++ { 17 | go modifyByChan(i) 18 | } 19 | // 处理channel的服务 20 | chanServ(max) 21 | time2 := time.Now().UnixNano() 22 | fmt.Printf("data len=%d, time=%d", len(dataCh), (time2-time1)/1000000) 23 | } 24 | 25 | func modifyByChan(i int) { 26 | chMap <- i 27 | } 28 | // 专门处理chMap的服务程序 29 | func chanServ(max int) { 30 | for { 31 | i := <- chMap 32 | dataCh[i] = i 33 | if len(dataCh) == max { 34 | return 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /map-value-is-struct/map-value-is-struct.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | map初始化需要分配空间,、 7 | 结构体作为map的值时,不能直接赋值结构体某个字段,拒绝直接寻址 8 | */ 9 | 10 | type P struct { 11 | name string 12 | sex string 13 | } 14 | 15 | func main() { 16 | m := make(map[string]P) 17 | //结构体不能直接赋值字段 18 | //m["a"].name = "lee" 19 | m["a"] = P{name: "lee", sex: "man"} 20 | //直接初始化 21 | t := map[string]P{"key": P{name: "lee", sex: "nan"}} 22 | //赋值value 为temp, temp可寻址,此时可以更改temp的属性name和sex 23 | temp := t["key"] 24 | temp.name = "anne" 25 | //更改后的t中value不变, (struct为值类型) 26 | fmt.Println(t, temp) 27 | //当使用指针的时候可以直接赋值 28 | n := make(map[string]*P) 29 | p := &P{"lee", "man"} 30 | n["a"] = p 31 | n["a"].name = "test" 32 | fmt.Println(n["a"]) 33 | } 34 | -------------------------------------------------------------------------------- /mysql/delete/mysql-delete.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | "fmt" 6 | "log" 7 | ) 8 | 9 | func main() { 10 | //contact mysql 11 | db, err := sql.Open("mysql", "root:password@tcp(locahost:3306)/test") 12 | if err != nil { 13 | log.Println("数据库连接失败: ", err) 14 | return 15 | } 16 | db.Ping() 17 | defer func() { 18 | db.Close() 19 | }() 20 | 21 | stmt, err := db.Prepare("delete from test where id = ?") 22 | if err != nil { 23 | log.Println("预处理失败: ", err) 24 | return 25 | } 26 | defer func() { 27 | stmt.Close() 28 | }() 29 | 30 | res,err:=stmt.Exec(1) 31 | if err!=nil{ 32 | fmt.Println("执行SQL出现错误") 33 | } 34 | //受影响行数 35 | count,err:=res.RowsAffected() 36 | if err!=nil{ 37 | fmt.Println("获取结果失败",err) 38 | } 39 | if count > 0{ 40 | fmt.Println("删除成功") 41 | } else { 42 | fmt.Println("删除失败") 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /mysql/insert/mysql-insert.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | "fmt" 6 | _ "github.com/go-sql-driver/mysql" 7 | ) 8 | 9 | func main() { 10 | //打开连接 11 | db, err := sql.Open("mysql", "root:password@tcp(localhost:3306)/test") 12 | db.Ping() 13 | if err != nil { 14 | fmt.Println("数据库连接失败") 15 | return 16 | } 17 | 18 | defer func() { 19 | db.Close() 20 | }() 21 | 22 | //预处理sql 23 | stmt, err := db.Prepare("insert into test values(default, ?, ?)") 24 | if err != nil { 25 | fmt.Println("预处理失败") 26 | return 27 | } 28 | 29 | defer func() { 30 | stmt.Close() 31 | }() 32 | 33 | r, err := stmt.Exec("lee", "北京") 34 | if err != nil { 35 | fmt.Println("sql执行失败") 36 | return 37 | } 38 | count, err := r.RowsAffected() 39 | if err != nil { 40 | fmt.Println("数据插入失败") 41 | return 42 | } 43 | 44 | if count > 0 { 45 | fmt.Println("数据插入成功") 46 | } else { 47 | fmt.Println("失败") 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /mysql/search/mysql-search.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | "fmt" 6 | "log" 7 | _ "github.com/go-sql-driver/mysql" 8 | ) 9 | 10 | func main() { 11 | db, err := sql.Open("mysql", "root:password@tcp(localhost:3306)/test") 12 | if err != nil { 13 | log.Println("数据库连接失败: ", err) 14 | return 15 | } 16 | db.Ping() 17 | defer func() { 18 | db.Close() 19 | }() 20 | 21 | stmt, err := db.Prepare("select name from test where id = ?") 22 | if err != nil { 23 | log.Println("预处理失败: ", err) 24 | return 25 | } 26 | defer func() { 27 | stmt.Close() 28 | }() 29 | 30 | rows, err := stmt.Query(1) 31 | for rows.Next() { 32 | var name string 33 | fmt.Println(rows.Scan(&name)) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /mysql/update/mysql-update.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | "fmt" 6 | "log" 7 | _ "github.com/go-sql-driver/mysql" 8 | ) 9 | 10 | func main() { 11 | db, err := sql.Open("mysql", "root:password@tcp(localhost:3306)/test") 12 | if err != nil { 13 | log.Println("mysql连接失败: ", err) 14 | return 15 | } 16 | db.Ping() 17 | //关闭连接 18 | defer func() { 19 | db.Close() 20 | }() 21 | 22 | //sql预处理,使用占位符 23 | stmt, err := db.Prepare("update test set name = ?, address = ? where id = ?") 24 | if err != nil { 25 | log.Println("sql预处理失败: ", err) 26 | return 27 | } 28 | 29 | defer func() { 30 | stmt.Close() 31 | }() 32 | 33 | //exec执行函数,对应占位符 34 | result, err := stmt.Exec("anne", "东城", 1) 35 | if err != nil { 36 | log.Println("sql执行失败: ", err) 37 | return 38 | } 39 | 40 | count, _ := result.RowsAffected() 41 | if count > 0{ 42 | fmt.Println("数据修改成功") 43 | } else { 44 | fmt.Println("数据更新失败") 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /panic-and-recover/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | //recover通常是用在defer内部,因为panic的时候,defer是执行的 6 | //函数调用过程中, recover只恢复当前函数中的panic,恢复后当前函数结束,当前函数panic后部分不执行 7 | //panic会一直向上传递的,碰到recover的时候,panic停止向上传递 8 | func demo() { 9 | fmt.Println("demo上半部分") 10 | demo1() 11 | fmt.Println("demo下半部分") 12 | } 13 | 14 | //在demo1中添加recover, demo2的panic上传到demo1中,所以demo1下半部分不执行 15 | func demo1() { 16 | defer func() { 17 | recover() 18 | }() 19 | fmt.Println("demo1上半部分") 20 | demo2() 21 | fmt.Println("demo1下半部分") 22 | } 23 | 24 | func demo2() { 25 | fmt.Println("demo2上半部分") 26 | panic("执行panic") 27 | fmt.Println("demo2下半部分") 28 | } 29 | 30 | func main() { 31 | demo() 32 | } -------------------------------------------------------------------------------- /panic-and-recover/recover-protect.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "runtime" 6 | ) 7 | 8 | type panicContext struct { 9 | context string 10 | } 11 | 12 | func ProtectPanic() { 13 | fmt.Println("开始测试") 14 | ProtectRun(func() { 15 | fmt.Println("手动panic前") 16 | panic(panicContext{"手动触发"}) 17 | fmt.Println("手动panic后") 18 | }) 19 | 20 | //空指针 21 | ProtectRun(func() { 22 | fmt.Println("空指针赋值前") 23 | var a *int 24 | *a = 1 25 | fmt.Println("空指针赋值完成") 26 | }) 27 | } 28 | 29 | func ProtectRun(entry func()) { 30 | defer func() { 31 | err := recover() 32 | switch err.(type) { 33 | case runtime.Error: 34 | fmt.Printf("runtime error %s\n", err) 35 | default: 36 | fmt.Println("other err:", err) 37 | } 38 | }() 39 | entry() 40 | } 41 | -------------------------------------------------------------------------------- /polymorphic/polymorphic_example.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | 1.多态在代码层面最常见的一种方式是: 接口当作方法参数 7 | 2.结构体变量赋值给接口变量 8 | 3.重写接口时接收者为`Type`和`*Type`的区别 9 | * `*Type`可以调用`*Type`和`Type`作为接收者的方法.所以只要接口中多个方法中至少出现一个使用`*Type`作为接收者进行重写的方法,就必须把结构体指针赋值给接口变量,否则编译报错 10 | * `Type`只能调用`Type`作为接收者的方法 11 | */ 12 | type Live interface { 13 | run() 14 | } 15 | 16 | type People struct { 17 | name string 18 | } 19 | 20 | type Animal struct { 21 | 22 | } 23 | 24 | func (p *People) run() { 25 | fmt.Println("人在跑") 26 | } 27 | func (a *Animal) run() { 28 | fmt.Println("动物在跑") 29 | } 30 | //接口作为参数 31 | func checkSource(live Live) { 32 | live.run() 33 | } 34 | 35 | func main() { 36 | people := &People{} 37 | animal := &Animal{} 38 | //调用方法 39 | checkSource(people) 40 | checkSource(animal) 41 | //将结构体赋值给接口(向上引用) 42 | var run Live = &People{} 43 | run.run() 44 | } 45 | -------------------------------------------------------------------------------- /posts.csv: -------------------------------------------------------------------------------- 1 | 1,Hello World!,Sau Sheong 2 | 2,Bonjour Monde!,Pierre 3 | 3,Hola Mundo!,Pedro 4 | 4,Greetings Earthlings!,Sau Sheong 5 | -------------------------------------------------------------------------------- /pprof: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/pprof -------------------------------------------------------------------------------- /program_demo/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/program_demo/.DS_Store -------------------------------------------------------------------------------- /program_demo/test-person.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/program_demo/test-person.docx -------------------------------------------------------------------------------- /program_demo/test.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/program_demo/test.pptx -------------------------------------------------------------------------------- /program_demo/test.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/program_demo/test.xlsx -------------------------------------------------------------------------------- /proxy/http-simple-proxy/simple-proxy.go: -------------------------------------------------------------------------------- 1 | package http_simple_proxy 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "net/http" 7 | "net/http/httputil" 8 | "net/url" 9 | ) 10 | 11 | func NewMultiHostsRevsrseProxy(targets []*url.URL) *httputil.ReverseProxy { 12 | director := func(req *http.Request) { 13 | target := targets[rand.Int()%2] 14 | req.URL.Scheme = target.Scheme 15 | req.URL.Host = target.Host 16 | req.URL.Path = target.Path 17 | } 18 | return &httputil.ReverseProxy{Director: director} 19 | } 20 | 21 | func Print() { 22 | num := rand.Int() % 2 23 | fmt.Println(num) 24 | } 25 | -------------------------------------------------------------------------------- /proxy/http-simple-proxy/simple-proxy_test.go: -------------------------------------------------------------------------------- 1 | package http_simple_proxy 2 | 3 | import ( 4 | "net/http" 5 | "net/url" 6 | "testing" 7 | ) 8 | 9 | func TestPrint(t *testing.T) { 10 | for i := 0; i < 20; i++ { 11 | Print() 12 | } 13 | } 14 | 15 | func TestNewMultiHostsRevsrseProxy(t *testing.T) { 16 | proxy := NewMultiHostsRevsrseProxy([]*url.URL{ 17 | { 18 | Scheme: "http", 19 | Host: "localhost:9091", 20 | }, 21 | { 22 | Scheme: "http", 23 | Host: "localhost:9092", 24 | }, 25 | }) 26 | http.ListenAndServe(":9090", proxy) 27 | } 28 | -------------------------------------------------------------------------------- /proxy/tcp-trans/tls/client/client.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/tls" 5 | "fmt" 6 | "log" 7 | ) 8 | 9 | func main() { 10 | conf := &tls.Config{ 11 | InsecureSkipVerify: true, 12 | } 13 | conn, err := tls.Dial("tcp", "127.0.0.1:443", conf) 14 | if err != nil { 15 | log.Println(err) 16 | return 17 | } 18 | token := fmt.Sprintf("zs-token: %v", "ndop3gsbjQlxityQLhk57A4CudfY7zbFcSRczc5zJ0c\n\r") 19 | defer conn.Close() 20 | n, err := conn.Write([]byte(token)) 21 | if err != nil { 22 | log.Println(n, err) 23 | return 24 | } 25 | buf := make([]byte, 100) 26 | n, err = conn.Read(buf) 27 | if err != nil { 28 | log.Println(n, err) 29 | return 30 | } 31 | println(string(buf[:n])) 32 | } 33 | -------------------------------------------------------------------------------- /reflect-and-interface/reflect-func.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | socket "github.com/googollee/go-socket.io" 6 | "reflect" 7 | ) 8 | 9 | func main() { 10 | c := event 11 | fv := reflect.ValueOf(c) 12 | ft := fv.Type() 13 | fmt.Println(ft.NumIn()) 14 | for i := 0; i < ft.NumIn(); i++ { 15 | fmt.Println(ft.In(i)) 16 | } 17 | 18 | var num float64 = 2.3435 19 | 20 | // 指针 *float64 21 | pointer := reflect.ValueOf(&num) 22 | // float64 23 | value := reflect.ValueOf(num) 24 | 25 | /* 强制转换 26 | 区分指针和值 27 | 转换类型要完全符合,否者直接panic 28 | */ 29 | convertPointer := pointer.Interface().(*float64) //#=> 一个地址 30 | convertValue := value.Interface().(float64) //#=>2。3435 31 | fmt.Println(convertPointer, convertValue, value.Interface()) 32 | } 33 | 34 | func event(conn socket.Conn, msg string) { 35 | 36 | } 37 | -------------------------------------------------------------------------------- /reflect-and-interface/reflect_learn.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | ) 7 | 8 | type T struct { 9 | A int 10 | B string 11 | } 12 | 13 | func main() { 14 | t := &T{201, "mh103"} 15 | s := reflect.ValueOf(t) 16 | s = s.Elem() 17 | typeOfT := s.Type() 18 | fmt.Println(s.Type()) 19 | for i := 0; i < s.NumField(); i++ { 20 | f := s.Field(i) 21 | fmt.Println(i, typeOfT.Field(i).Name, f.Type(), f.Interface()) 22 | } 23 | } -------------------------------------------------------------------------------- /regexp/use-regexp-get-substring.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "regexp" 6 | ) 7 | 8 | /*使用正则提取url字串*/ 9 | 10 | func main() { 11 | re := `^http://www.flysnow.org/([\d]{4})/([\d]{2})/([\d]{2})/([\w-]+).html$` 12 | reg := regexp.MustCompile(re) 13 | params := reg.FindStringSubmatch("http://www.flysnow.org/2018/01/20/golang-goquery-examples-selector.html") 14 | for _, item := range params { 15 | fmt.Println(item) 16 | } 17 | 18 | //使用\W首尾确定非字符数字,用()截取分词结果 19 | pattern := "\\W(1[45][0-9]{7})\\W|\\W([P|p|S|s]\\d{7})\\W|\\W([S|s|G|g]\\d{8})\\W|\\W([Gg|Tt|Ss|Ll|Qq|Dd|Aa|Ff]\\d{8})\\W|\\W([H|h|M|m]\\d{8,10})\\W" 20 | reg1 := regexp.MustCompile(pattern) 21 | p := reg1.FindStringSubmatch("测141234567测") 22 | for _, item := range p { 23 | fmt.Println(item) 24 | } 25 | 26 | email := "([a-zA-Z0-9_\\-\\.]+)@([a-zA-Z0-9_\\-\\.]+)\\.([a-zA-Z]{2,5})" 27 | e := regexp.MustCompile(email) 28 | emailr := e.FindStringSubmatch("23js@163.com") 29 | fmt.Println(emailr[0]) 30 | } 31 | -------------------------------------------------------------------------------- /ring/ring.go: -------------------------------------------------------------------------------- 1 | package ring 2 | 3 | import ( 4 | "container/ring" 5 | "fmt" 6 | ) 7 | 8 | //双向链表 9 | func testRing() { 10 | //初始化Ring结构 11 | r := ring.New(5) 12 | r.Value = 0 13 | r.Next().Value = 1 14 | r.Next().Value = 2 15 | r.Prev().Value = 3 16 | r.Prev().Value = 4 17 | 18 | //遍历循环链表 19 | r.Do(func(i interface{}) { 20 | fmt.Println(i) 21 | }) 22 | //移动 23 | _ = r.Move(1).Value 24 | 25 | //添加 26 | r1 := ring.New(1) 27 | r1.Value = 5 28 | r.Next().Link(r1) 29 | 30 | //删除 n%r.len() 31 | r.Unlink(1) 32 | } 33 | -------------------------------------------------------------------------------- /share-memory-and-chan/channel-used.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func CCount(ch chan int) { 6 | ch <- 1 7 | fmt.Println("Counting") 8 | } 9 | 10 | func main() { 11 | 12 | chs := make([] chan int, 10) 13 | 14 | for i:=0; i<10; i++ { 15 | chs[i] = make(chan int) 16 | go CCount(chs[i]) 17 | } 18 | 19 | for _, ch := range(chs) { 20 | <-ch 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /share-memory-and-chan/memory.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "runtime" 6 | "sync" 7 | ) 8 | 9 | var counter = 0 10 | 11 | func Count(lock *sync.Mutex) { 12 | lock.Lock() 13 | counter++ 14 | fmt.Println("counter = ", counter) 15 | lock.Unlock() 16 | } 17 | 18 | func main() { 19 | lock := &sync.Mutex{} 20 | for i := 0; i < 10; i++ { 21 | go Count(lock) 22 | } 23 | for { 24 | lock.Lock() 25 | c := counter 26 | lock.Unlock() 27 | 28 | runtime.Gosched() 29 | if c >= 10 { 30 | break 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /slice/two-demension-slice.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | init 二维切片 7 | */ 8 | func main() { 9 | tslice := make([][]bool, 5) 10 | for i := range tslice { 11 | tslice[i] = make([]bool, 5) 12 | } 13 | //输出内容 14 | for i := range mslice { 15 | for j := range mslice[i] { 16 | fmt.Println(i, j, mslice[i][j]) 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /static-app/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/static-app/.DS_Store -------------------------------------------------------------------------------- /static-app/static/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/static-app/static/.DS_Store -------------------------------------------------------------------------------- /string-byte-rune/define-enum-string-method.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type BizType int 8 | 9 | const ( 10 | SearchFlight BizType = iota 11 | CalendarFlight 12 | BookingFlight 13 | ) 14 | 15 | //func (b BizType) ValueString() string { 16 | // return strconv.Itoa(int(b)) 17 | //} 18 | 19 | func (b BizType) String() string { 20 | return [...]string{"search flight", "calendar flight", "booking flight"}[b] 21 | } 22 | 23 | func main() { 24 | var search BizType = SearchFlight 25 | fmt.Println(search) 26 | } -------------------------------------------------------------------------------- /struct/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | "strings" 7 | ) 8 | 9 | /* 10 | 声明为变量时,并分配内存空间, 在进行struct中的变量赋值时,可直接使用。 11 | 声明为指针时,并未进行赋值,也没有分配内存空间 12 | */ 13 | var c Man 14 | 15 | type Man struct { 16 | Name string 17 | } 18 | 19 | func main() { 20 | var a *Man 21 | //指针必须指定内存地址,否则//invalid memory address or nil pointer dereference 22 | a = &Man{} 23 | var b Man 24 | if a == nil { 25 | fmt.Printf("777: \n", 1) 26 | } 27 | if &b == nil { 28 | fmt.Printf("888: ", &b) 29 | } 30 | a.Name = "lee" 31 | b.Name = "lee" 32 | fmt.Println(a) 33 | fmt.Println(b) 34 | 35 | c.Name = "lee" 36 | fmt.Println() 37 | 38 | s, _ := M() 39 | fmt.Println(s) 40 | } 41 | 42 | func M() (string, error) { 43 | b := []byte{'"', '{', '}', '"'} 44 | str := string(b) 45 | return strconv.Unquote(strings.Replace(strconv.Quote(str), `\\u`, `\u`, -1)) 46 | } 47 | -------------------------------------------------------------------------------- /struct/null_struct.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | ) 7 | 8 | //struct{}是一个无元素的结构类型, 大小为0, 通常作为占位符 9 | //struct {} {}是一个复合字面量,它构造了一个struct {}类型结构值,该结构值也是空的: 10 | 11 | type m chan struct{} 12 | 13 | var wg sync.WaitGroup 14 | func main() { 15 | n := make(m, 1) 16 | n <- struct {}{} 17 | select { 18 | case <- n: 19 | fmt.Println("空值") 20 | } 21 | 22 | test := make(chan int) 23 | go func() { 24 | test <- 1 25 | }() 26 | 27 | <- test 28 | fmt.Println("关闭") 29 | } 30 | -------------------------------------------------------------------------------- /struct/struct-inherit.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type People struct { 6 | 7 | } 8 | 9 | func (p *People) ShowA() { 10 | fmt.Println("ShowA") 11 | p.ShowB() 12 | } 13 | 14 | func (p *People) ShowB() { 15 | fmt.Println("ShowB") 16 | } 17 | 18 | type Teachers struct { 19 | People 20 | } 21 | 22 | func (t *Teachers) ShowB() { 23 | fmt.Println("teacher show B") 24 | } 25 | 26 | func main() { 27 | t := &Teachers{} 28 | t.ShowA() 29 | } 30 | -------------------------------------------------------------------------------- /tequila/ac.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ahocorasick "github.com/petar-dambovaliev/aho-corasick" 6 | ) 7 | 8 | var builder = ahocorasick.NewAhoCorasickBuilder(ahocorasick.Opts{ 9 | AsciiCaseInsensitive: true, 10 | MatchOnlyWholeWords: false, 11 | MatchKind: ahocorasick.LeftMostFirstMatch, 12 | DFA: true, 13 | }) 14 | 15 | var dict = []string{"air", "flight", "login", "signin", "signup", "register", "password", "sms", "captcha", "upload", "download", "query", "list", "search", "pay", "checkout", "book", "order", "reserve", "calendar", "coupon"} 16 | 17 | func main() { 18 | var res []interface{} 19 | res = append(res, builder.Build(dict)) 20 | acid := 0 21 | prefix := "szffp-webloginloginMcodeSF" 22 | matches := res[acid].(ahocorasick.AhoCorasick).FindAll(prefix) 23 | var ret []int 24 | for _, match := range matches { 25 | ret = append(ret, match.Pattern()) 26 | } 27 | fmt.Println(ret) 28 | } 29 | -------------------------------------------------------------------------------- /test.info: -------------------------------------------------------------------------------- 1 | {"name":"lee","age":22,"sex":"boy"} -------------------------------------------------------------------------------- /test.txt: -------------------------------------------------------------------------------- 1 | But what is the performance impact 2 | of using S3 across a network instead of using HDFS? 3 | This work done by Tatsuya Kawano (@tatsuya6502) 4 | aims to answer that question by examining the 5 | performance of different combinations of query type and storage type -------------------------------------------------------------------------------- /test_omitempty_of_json.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | ) 7 | 8 | type Message struct { 9 | FinalTestingRes FinalTestingRes `json:"final_testing_res,omitempty"` 10 | } 11 | 12 | type FinalTestingRes struct { 13 | Results []TestingRes `json:",omitempty"` 14 | FinalAction string `json:",omitempty"` 15 | FinalRiskName string `json:",omitempty"` 16 | } 17 | 18 | type TestingRes struct { 19 | Action string 20 | RiskName string 21 | Reason string 22 | IsOK bool `json:"-"` 23 | } 24 | 25 | func main() { 26 | mess := Message{ 27 | FinalTestingRes: FinalTestingRes{ 28 | []TestingRes{}, 29 | "block", 30 | "", 31 | }, 32 | } 33 | b, _ := json.Marshal(mess) 34 | fmt.Println(string(b)) 35 | } 36 | -------------------------------------------------------------------------------- /tika-demo/tika-server-standard-2.9.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/tika-demo/tika-server-standard-2.9.1.jar -------------------------------------------------------------------------------- /tika-demo/tika.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "github.com/google/go-tika/tika" 7 | "log" 8 | "os" 9 | ) 10 | 11 | func main() { 12 | pwd, _ := os.Getwd() 13 | jar := pwd + "/tika-demo/tika-server-standard-2.9.1.jar" 14 | fmt.Println(jar) 15 | s, err := tika.NewServer(jar, "") 16 | if err != nil { 17 | log.Fatal(err) 18 | } 19 | err = s.Start(context.Background()) 20 | if err != nil { 21 | log.Fatal(err) 22 | } 23 | defer s.Stop() 24 | 25 | f, err := os.Open("/Users/lee/workspace/pcapfiles/test.png") 26 | if err != nil { 27 | log.Fatal(err) 28 | } 29 | defer f.Close() 30 | 31 | client := tika.NewClient(nil, s.URL()) 32 | body, err := client.Parse(context.Background(), f) 33 | fmt.Println(body) 34 | } 35 | -------------------------------------------------------------------------------- /toml-file/dddd.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io/ioutil" 7 | 8 | "github.com/spf13/viper" 9 | ) 10 | 11 | func main() { 12 | content, err := ioutil.ReadFile("./config.toml") 13 | fmt.Println(err) 14 | v := viper.New() 15 | v.SetConfigType("toml") 16 | v.ReadConfig(bytes.NewBuffer(content)) 17 | var res map[string]interface{} 18 | v.Unmarshal(&res) 19 | fmt.Println(res["go-validator"].([]interface{})[0].(map[string]interface{})["source_name"]) 20 | fmt.Println(res["version"]) 21 | } 22 | -------------------------------------------------------------------------------- /udp-server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | ) 7 | 8 | func main() { 9 | // 要监听的地址和端口 10 | address := "192.168.1.100:80" 11 | 12 | // 监听UDP数据包 13 | conn, err := net.ListenPacket("udp", address) 14 | if err != nil { 15 | panic(err) 16 | } 17 | defer conn.Close() 18 | 19 | fmt.Printf("Listening on %s...\n", address) 20 | 21 | // 创建一个用于读取数据的缓冲区 22 | buffer := make([]byte, 2048) 23 | 24 | for { 25 | // 读取数据 26 | n, addr, err := conn.ReadFrom(buffer) 27 | if err != nil { 28 | fmt.Println("Failed to read data:", err) 29 | continue 30 | } 31 | 32 | // 输出收到的消息和发送者地址 33 | fmt.Printf("Received '%s' from %s\n", string(buffer[:n]), addr) 34 | 35 | // 将消息回显给发送者 36 | _, err = conn.WriteTo(buffer[:n], addr) 37 | if err != nil { 38 | fmt.Println("Failed to write data:", err) 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /unsafe_pointer_demo.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "unsafe" 7 | ) 8 | 9 | type SiteConfig struct { 10 | Host string `json:"host"` 11 | On bool `json:"on"` 12 | Configs map[string]interface{} `json:"configs"` 13 | } 14 | 15 | func main() { 16 | i := int64(1) 17 | var p *int32 18 | p = (*int32)(unsafe.Pointer(&i)) 19 | fmt.Printf("-----use unsafe pointer转化类型:----%#v\n", *p) 20 | str := "[{\"host\": \"127.0.0.1\", \"on\": false, \"configs\": {\"time_range_matcher\": {\"start\": \"2\" , \"end\": \"5\"}, \"region_matcher\": true, \"http_request_matcher\": [\"option\", \"get\"], \"static_html_matcher\": true}}]" 21 | var sites []SiteConfig 22 | err := json.Unmarshal([]byte(str), &sites) 23 | if err != nil { 24 | fmt.Println(err) 25 | } 26 | fmt.Println(sites) 27 | } 28 | -------------------------------------------------------------------------------- /wait_group/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | ) 7 | 8 | //使用waitGroup来处理程序阻塞 9 | /* 10 | type WaitGroup struct { 11 | noCopy noCopy 12 | state1 [12]byte 13 | sema uint32 14 | } 15 | *method 16 | func (wg *WaitGroup) Add(delta int) 17 | func (wg *WaitGroup) Done() 18 | func (wg *WaitGroup) Wait() 19 | */ 20 | var wg sync.WaitGroup 21 | 22 | func main() { 23 | wg.Add(5) 24 | for i := 1; i < 6; i++ { 25 | go func(i int) { 26 | fmt.Printf("第%d次执行\n", i) 27 | wg.Done() 28 | }(i) 29 | } 30 | wg.Wait() 31 | } 32 | -------------------------------------------------------------------------------- /xmlDemo/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/xml" 5 | "fmt" 6 | "io/ioutil" 7 | ) 8 | 9 | type Peoples struct { 10 | //xml根节点 11 | XMLName xml.Name `xml:"peoples"` 12 | //属性 13 | Version string `xml:"version,attr"` 14 | //子节点 15 | Peos []People `xml:"people"` 16 | } 17 | 18 | type People struct { 19 | XMLName xml.Name `xml:"people"` 20 | Id int `xml:"id,attr"` 21 | Name string `xml:"name"` 22 | Address string `xml:"address"` 23 | } 24 | 25 | func main() { 26 | people := new(Peoples) 27 | xmlfile, _ := ioutil.ReadFile("./peoples.xml") 28 | xml.Unmarshal(xmlfile, people) 29 | fmt.Println(people) 30 | 31 | //生成xml文件 32 | p := People{Id: 1, Name: "lee", Address: "北京"} 33 | //格式化 34 | b, _ := xml.MarshalIndent(p, "", " ") 35 | //追加头信息 36 | b = append([]byte(xml.Header), b...) 37 | ioutil.WriteFile("./people.xml", b, 0666) 38 | } 39 | -------------------------------------------------------------------------------- /技术文档/GC/gc处理命令.md: -------------------------------------------------------------------------------- 1 | go build --gcflags=-m 逃逸分析 2 | //pprof 3 | go tool pprof -http=:8000 http://localhost:8080/debug/pprof/heap 查看内存使用 4 | go tool pprof -http=:8000 http://localhost:8080/debug/pprof/profile 查看cpu占用 5 | 6 | go build -o main 7 | GODEBUG=gctrace=1 打印gc信息 8 | 9 | 方式2:go tool trace 10 | 在代码中添加: 11 | f, _ := os.Create("trace.out") 12 | defer f.Close() 13 | trace.Start(f) 14 | defer trace.Stop() 15 | 然后运行程序,等程序运行完成,执行以下命令 16 | go tool trace trace.out -------------------------------------------------------------------------------- /技术文档/GC/gc管理及优化.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/GC/gc管理及优化.md -------------------------------------------------------------------------------- /技术文档/HTTP-TCP/tls握手过程.md: -------------------------------------------------------------------------------- 1 | #### SSL / TLS 握手详细过程 2 | 1. "client hello"消息:客户端通过发送"client hello"消息向服务器发起握手请求,该消息包含了客户端所支持的 TLS 版本和密码组合以供服务器进行选择,还有一个"client random"随机字符串。 3 | 2. "server hello"消息:服务器发送"server hello"消息对客户端进行回应,该消息包含了数字证书,服务器选择的密码组合和"server random"随机字符串。 4 | 3. 验证:客户端对服务器发来的证书进行验证,确保对方的合法身份,验证过程可以细化为以下几个步骤: 5 | * 检查数字签名 6 | * 验证证书链 (这个概念下面会进行说明) 7 | * 检查证书的有效期 8 | * 检查证书的撤回状态 (撤回代表证书已失效) 9 | 4. "premaster secret"字符串:客户端向服务器发送另一个随机字符串"premaster secret (预主密钥)",这个字符串是经过服务器的公钥加密过的,只有对应的私钥才能解密。 10 | 5. 使用私钥:服务器使用私钥解密"premaster secret"。 11 | 6. 生成共享密钥:客户端和服务器均使用 client random,server random 和 premaster secret,并通过相同的算法生成相同的共享密钥 KEY。 12 | 7. 客户端就绪:客户端发送经过共享密钥 KEY加密过的"finished"信号。 13 | 8. 服务器就绪:服务器发送经过共享密钥 KEY加密过的"finished"信号。 14 | 9. 达成安全通信:握手完成,双方使用对称加密进行安全通信 -------------------------------------------------------------------------------- /技术文档/HttpCode/HTTP状态码.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/HttpCode/HTTP状态码.png -------------------------------------------------------------------------------- /技术文档/Linux/6-常用操作快捷键.md: -------------------------------------------------------------------------------- 1 | --- 2 | typora-copy-images-to: img 3 | --- 4 | 5 | 6 | 7 | 8 | 9 | ## 常用快捷键 10 | 11 | linux常用操作快捷键: 12 | Tab: 命令补全/路径补全/文件名补全,一次tab是补全,两次tab,列出相关信息。 13 | Ctrl+C: 强制结束当前的进程。干了一半不想干了想反悔就Ctrl+C。 14 | Ctrl+D: 发送一个exit信号,每次当我们有“退出”的意思的时候,就可以使用这个。比如SSH登录到另一个机器,想退出就Ctrl+D。 15 | Ctrl+A: 移动到命令行首。 16 | Ctrl+E: 移动到命令行尾。 17 | Ctrl+U :从当前光标所在位置向前清除命令。 18 | Ctrl+W: 从当前光标所在位置向前清除一个单词。 19 | 上下箭头: 上下翻看命令的输入记录,如果历史记录太多翻起来太慢,就用history显示出来然后再复制粘贴。 20 | 21 | 22 | 23 | 24 | 25 | ## 系统监控命令 26 | 27 | ### **查看端口占用情况** 28 | 29 | 查看80端口是否已经打开 30 | 31 | ```shell 32 | netstat -an | grep -w 80 其中的-w表示按单词匹配,以免匹配到8080端口 33 | ``` 34 | 35 | ![1577760184493](img/1577760184493.png) 36 | 37 | 查看80端口被什么进程占用 38 | 39 | ```shell 40 | netstat -anp | grep -w 80 41 | ``` 42 | 43 | ![1577760217608](img/1577760217608.png) 44 | 45 | -------------------------------------------------------------------------------- /技术文档/Linux/img/1-Linux基础介绍.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Linux/img/1-Linux基础介绍.png -------------------------------------------------------------------------------- /技术文档/Linux/img/1-Linux基础介绍(目录结构).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Linux/img/1-Linux基础介绍(目录结构).png -------------------------------------------------------------------------------- /技术文档/Linux/img/1576057399279.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Linux/img/1576057399279.png -------------------------------------------------------------------------------- /技术文档/Linux/img/1576057511502.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Linux/img/1576057511502.png -------------------------------------------------------------------------------- /技术文档/Linux/img/1576057711660.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Linux/img/1576057711660.png -------------------------------------------------------------------------------- /技术文档/Linux/img/1576057716311.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Linux/img/1576057716311.png -------------------------------------------------------------------------------- /技术文档/Linux/img/1576057723337.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Linux/img/1576057723337.png -------------------------------------------------------------------------------- /技术文档/Linux/img/1576057726913.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Linux/img/1576057726913.png -------------------------------------------------------------------------------- /技术文档/Linux/img/1576057730548.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Linux/img/1576057730548.png -------------------------------------------------------------------------------- /技术文档/Linux/img/1576057740616.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Linux/img/1576057740616.png -------------------------------------------------------------------------------- /技术文档/Linux/img/1576057781943.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Linux/img/1576057781943.png -------------------------------------------------------------------------------- /技术文档/Linux/img/1576057981486.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Linux/img/1576057981486.png -------------------------------------------------------------------------------- /技术文档/Linux/img/1576058065143.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Linux/img/1576058065143.png -------------------------------------------------------------------------------- /技术文档/Linux/img/1576058227429.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Linux/img/1576058227429.png -------------------------------------------------------------------------------- /技术文档/Linux/img/1576061730124.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Linux/img/1576061730124.png -------------------------------------------------------------------------------- /技术文档/Linux/img/1576061785195.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Linux/img/1576061785195.png -------------------------------------------------------------------------------- /技术文档/Linux/img/1576114390863.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Linux/img/1576114390863.png -------------------------------------------------------------------------------- /技术文档/Linux/img/1576115489482.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Linux/img/1576115489482.png -------------------------------------------------------------------------------- /技术文档/Linux/img/1576117675409.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Linux/img/1576117675409.png -------------------------------------------------------------------------------- /技术文档/Linux/img/1577760184493.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Linux/img/1577760184493.png -------------------------------------------------------------------------------- /技术文档/Linux/img/1577760217608.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Linux/img/1577760217608.png -------------------------------------------------------------------------------- /技术文档/Linux/img/Linux-Directory-Structure.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Linux/img/Linux-Directory-Structure.jpeg -------------------------------------------------------------------------------- /技术文档/Linux/img/ls-l.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Linux/img/ls-l.png -------------------------------------------------------------------------------- /技术文档/Linux/img/more.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Linux/img/more.png -------------------------------------------------------------------------------- /技术文档/Linux/img/rwx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Linux/img/rwx.png -------------------------------------------------------------------------------- /技术文档/Linux/img/setnu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Linux/img/setnu.png -------------------------------------------------------------------------------- /技术文档/Linux/img/vi模式切换.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Linux/img/vi模式切换.png -------------------------------------------------------------------------------- /技术文档/Linux/img/yumupdate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Linux/img/yumupdate.png -------------------------------------------------------------------------------- /技术文档/Linux/linux下各设备文件名.md: -------------------------------------------------------------------------------- 1 | ###Linux下各设备的文件名 2 | 3 | 1. 硬件设备-> 所有的硬件设备文件都在/dev这个目录内 4 | ```text 5 | 1) 硬盘 6 | /dev/sd[a-d]: 即有/dev/sda, /dev/sdb, /dev/sdc, /dev/sdd这四个文件 7 | 2) USB 接口 8 | /dev/usb/lp[0-15] 9 | 3) 鼠标 10 | /dev/input/mouse[0-15] (通用) 11 | /dev/mouse (当前鼠标) 12 | 4) 虚拟机 13 | /dev/vd[a-p] 14 | ``` 15 | 16 | 2. Linux的可执行程序及相关的文件摆放的目录 17 | ```text 18 | /usr 19 | ``` 20 | 21 | 3. linux用户和用户组所在目录 22 | * /etc/group 用户组 23 | * /etc/passwd 用户所在目录 24 | -------------------------------------------------------------------------------- /技术文档/Linux/linux文件查找.md: -------------------------------------------------------------------------------- 1 | #### 文件搜索 2 | 3 | * which 查找可执行文件 4 | ```shell 5 | > which [-a] command 6 | * a 将所有由 PATH 目录中可以找到的指令均列出, 而不止第一个被找到的指令名称 7 | * command 执行文件 8 | ``` 9 | * whereis 查找文件 10 | ```shell 11 | > whereis 文件名 12 | ``` 13 | 14 | * find 15 | ```shell 16 | #与时间有关的选项 17 | > find [path] [option] [action] 18 | 示例 find / -mtime 2 #2天之前更改的文件 19 | #某个人的文件 20 | > find / -user username 21 | #查找某个文件 22 | > find / -name 文件名 23 | #查找文件大小 24 | > find / -size +1M 25 | ``` 26 | -------------------------------------------------------------------------------- /技术文档/Linux/linux泛域名解析.md: -------------------------------------------------------------------------------- 1 | #### dnsmasq 2 | 3 | 1. 安装 `apt-get install dnsmasq` 4 | 2. 修改配置文件`vim /etc/dnsmasq.conf` 5 | ```text 6 | # 严格按照 resolv-file 文件中的顺序从上到下进行 DNS 解析, 直到第一个成功解析成功为止 7 | strict-order 8 | 9 | # 监听的 IP 地址 10 | listen-address=127.0.0.1 11 | 12 | # 设置缓存大小 13 | cache-size=10240 14 | 15 | # 泛域名解析,访问任何 baidu.com 域名都会被解析到 6.6.6.6 16 | address=/abc.com/6.6.6.6 # 后面这个6.6.6.6是你自己服务监听的地址,我改称127.0.0.1 17 | 18 | ``` 19 | 3. 系统生效`systemctl enable --now dnsmasq` 没有生效就重启机器 20 | 21 | 4. 测试状态`systemctl status dnsmasq`或者 `ping your ip` -------------------------------------------------------------------------------- /技术文档/Linux/linux网卡.md: -------------------------------------------------------------------------------- 1 | #### 网卡 2 | 3 | 1. 查看网卡状态的命令 4 | ```shell 5 | # 列出所有网卡接口 6 | ifconfig -a 7 | 8 | # 列出所有网卡的信息, 包括接口名, 状态, 接收和发送的数据包数量, 错误数等 9 | ip -s link 10 | 11 | # mac下查看网卡接口信息 12 | netstat -i 13 | ``` 14 | 15 | 2. 查看网卡实时流量 16 | ```shell 17 | ifstat -i 18 | ``` 19 | 20 | 3. 查看端口占用 21 | ```shell 22 | netstat -tuln 23 | 24 | lsof -i: 25 | ``` 26 | 27 | 4. ifconfig列出的网卡参数说明 28 | ```text 29 | * :网卡的接口名,例如 eth0、en0 等。 30 | * :表示网卡的状态和特性的标志位,常见的标志位包括: 31 | * UP:网卡已启用并连接。 32 | * RUNNING:网卡正在运行。 33 | * BROADCAST:支持广播通信。 34 | * MULTICAST:支持多播通信。 35 | * PROMISC:网卡处于混杂模式,可以接收所有经过的数据包。 36 | * :最大传输单元,表示网卡支持的最大数据包大小。 37 | * inet :网卡配置的 IPv4 或 IPv6 地址。 38 | * netmask :子网掩码,定义了 IP 地址的网络部分和主机部分。 39 | * broadcast :广播地址,用于向网络中的所有设备广播消息。 40 | * ether :网卡的物理地址,也称为 MAC 地址。 41 | * :可能会显示其他与网卡相关的信息,例如错误计数、接收和发送的数据包数量等。 42 | ``` 43 | -------------------------------------------------------------------------------- /技术文档/Linux/shell/passport := passportRe.FindString(bodyStr): -------------------------------------------------------------------------------- 1 | passport := passportRe.FindString(bodyStr) 2 | if passport != "" { 3 | key = append(key, "passport") 4 | value = append(value, passport) 5 | log.Println("PassportCard:", value) 6 | } 7 | officer := officerRe.FindString(bodyStr) 8 | if officer != "" { 9 | key = append(key, "officer") 10 | value = append(value, officer) 11 | log.Println("OfficeCard:", value) 12 | } 13 | 14 | officerRe = regexp.MustCompile("[\u4E00-\u9FA5](字第)([0-9a-zA-Z]{4,8})(号?)") 15 | passportRe = regexp.MustCompile(`1[45][0-9]{7}|([P|p|S|s]\d{7})|([S|s|G|g]\d{8})|([Gg|Tt|Ss|Ll|Qq|Dd|Aa|Ff]\d{8})|([H|h|M|m]\d{8,10})`) 16 | 17 | 38: {`军字第2001988号`, []string{"officer"}, []string{"军字第2001988号"}}, 18 | 39: {`士字第P011816X号`, []string{"officer"}, []string{"士字第P011816X号"}}, 19 | 40: {`141234567`, []string{"passport"}, []string{"141234567"}}, 20 | 41: {`G28233515`, []string{"passport"}, []string{"G28233515"}}, -------------------------------------------------------------------------------- /技术文档/Nginx/img/04-Keepalived.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Nginx/img/04-Keepalived.png -------------------------------------------------------------------------------- /技术文档/Nginx/img/1576745376238.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Nginx/img/1576745376238.png -------------------------------------------------------------------------------- /技术文档/Nginx/img/1576748336954.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Nginx/img/1576748336954.png -------------------------------------------------------------------------------- /技术文档/Nginx/img/1576752632200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Nginx/img/1576752632200.png -------------------------------------------------------------------------------- /技术文档/Nginx/img/1576752878597.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Nginx/img/1576752878597.png -------------------------------------------------------------------------------- /技术文档/Nginx/img/1576752917726.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Nginx/img/1576752917726.png -------------------------------------------------------------------------------- /技术文档/Nginx/img/1576754226844.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Nginx/img/1576754226844.png -------------------------------------------------------------------------------- /技术文档/Nginx/img/1576754600807.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Nginx/img/1576754600807.png -------------------------------------------------------------------------------- /技术文档/Nginx/img/1576757003894.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Nginx/img/1576757003894.png -------------------------------------------------------------------------------- /技术文档/Nginx/img/1576757899719.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Nginx/img/1576757899719.png -------------------------------------------------------------------------------- /技术文档/Nginx/img/1576757921014.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Nginx/img/1576757921014.png -------------------------------------------------------------------------------- /技术文档/Nginx/img/1576757952498.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Nginx/img/1576757952498.png -------------------------------------------------------------------------------- /技术文档/Nginx/img/1576822681380.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Nginx/img/1576822681380.png -------------------------------------------------------------------------------- /技术文档/Nginx/img/1576822924112.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Nginx/img/1576822924112.png -------------------------------------------------------------------------------- /技术文档/Nginx/img/1576836138597.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Nginx/img/1576836138597.png -------------------------------------------------------------------------------- /技术文档/Nginx/img/1576837944705.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Nginx/img/1576837944705.png -------------------------------------------------------------------------------- /技术文档/Nginx/img/1576839162422.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Nginx/img/1576839162422.png -------------------------------------------------------------------------------- /技术文档/Nginx/img/1576843354486.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Nginx/img/1576843354486.png -------------------------------------------------------------------------------- /技术文档/Nginx/img/1576843508915.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Nginx/img/1576843508915.png -------------------------------------------------------------------------------- /技术文档/Nginx/img/1576843707409.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Nginx/img/1576843707409.png -------------------------------------------------------------------------------- /技术文档/Nginx/img/1576843745271.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Nginx/img/1576843745271.png -------------------------------------------------------------------------------- /技术文档/Nginx/img/1577327856588.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Nginx/img/1577327856588.png -------------------------------------------------------------------------------- /技术文档/Nginx/img/1577340754696.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Nginx/img/1577340754696.png -------------------------------------------------------------------------------- /技术文档/Nginx/img/1577341058999.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Nginx/img/1577341058999.png -------------------------------------------------------------------------------- /技术文档/Nginx/img/1577343575469.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Nginx/img/1577343575469.png -------------------------------------------------------------------------------- /技术文档/Nginx/pictures/7-负载均衡实现/1-HTTP重定向负载均衡.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Nginx/pictures/7-负载均衡实现/1-HTTP重定向负载均衡.jpg -------------------------------------------------------------------------------- /技术文档/Nginx/pictures/7-负载均衡实现/2-DNS域名解析负载均衡.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Nginx/pictures/7-负载均衡实现/2-DNS域名解析负载均衡.jpg -------------------------------------------------------------------------------- /技术文档/Nginx/pictures/7-负载均衡实现/3-反向代理负载均衡.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Nginx/pictures/7-负载均衡实现/3-反向代理负载均衡.jpg -------------------------------------------------------------------------------- /技术文档/Nginx/pictures/7-负载均衡实现/4-IP负载均衡.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Nginx/pictures/7-负载均衡实现/4-IP负载均衡.jpg -------------------------------------------------------------------------------- /技术文档/Nginx/pictures/7-负载均衡实现/5-数据链路层负载均衡.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Nginx/pictures/7-负载均衡实现/5-数据链路层负载均衡.jpg -------------------------------------------------------------------------------- /技术文档/Nginx/pictures/LVS.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Nginx/pictures/LVS.jpg -------------------------------------------------------------------------------- /技术文档/README.md: -------------------------------------------------------------------------------- 1 | #### NOTES 2 | 3 | 1. http code 4 | 2. kafka 5 | 3. lua 6 | 4. redis 7 | 5. mysql 8 | 6. linux 9 | 7. shell 10 | 8. 高可用 11 | 9. 缓存 12 | -------------------------------------------------------------------------------- /技术文档/Redis/1-Redis内存淘汰策略.md: -------------------------------------------------------------------------------- 1 | # Redis内存淘汰策略 2 | 3 | 4 | ## Redis淘汰策略 5 | 6 | 当达到最大内存```maxmemory```限制时,使用```maxmemory-policy```配置指令配置Redis的确切行为。 7 | 配置方式: maxmemory-policy options,默认为 8 | 9 | - **noeviction**: 不会移除任何key,在写的时候直接返回error 10 | - **volatile-lru** : 使用LRU算法清除过期的key 11 | - **allkeys-lru** : 使用LRU算法清除key 12 | - **volatile-lfu** : 使用LFU算法清除过期的key 13 | - **allkeys-lfu** : 使用LFU算法清除key 14 | - **volatile-random** : 在过期的key中随机移除一个key 15 | - **allkeys-random** : 在所有key中随机移除一个key 16 | - **volatile-ttl** : 移除具有具有最近过期时间的key 17 | 18 | 19 | - [Redis-缓存](https://redis.io/topics/lru-cache) -------------------------------------------------------------------------------- /技术文档/Redis/10-Redis面试热点问题.md: -------------------------------------------------------------------------------- 1 | # Redis面试热点问题. 2 | 3 | - 1[Redis架构之防雪崩设计](https://mp.weixin.qq.com/s/TBCEwLVAXdsTszRVpXhVug) 4 | 5 | - 2.[Redis的内存优化](https://cachecloud.github.io/2017/02/16/Redis%E5%86%85%E5%AD%98%E4%BC%98%E5%8C%96/) 6 | 7 | - 3.[Redis的Linux系统优化](https://cachecloud.github.io/2017/02/16/Redis%E7%9A%84Linux%E7%B3%BB%E7%BB%9F%E4%BC%98%E5%8C%96/) 8 | 9 | - 4.[Redis客户端常见异常分析](https://cachecloud.github.io/2017/02/20/Redis%E7%83%AD%E7%82%B9key%E5%AF%BB%E6%89%BE%E4%B8%8E%E4%BC%98%E5%8C%96/) 10 | 11 | - 5.[Redis热点key寻找与优化](https://cachecloud.github.io/2017/02/20/Redis%E7%83%AD%E7%82%B9key%E5%AF%BB%E6%89%BE%E4%B8%8E%E4%BC%98%E5%8C%96/) 12 | 13 | - 6.[Redis无限全量复制问题分析与优化](https://cachecloud.github.io/2016/11/24/%E5%85%A8%E9%87%8F%E5%A4%8D%E5%88%B6%E9%97%AE%E9%A2%98/) 14 | -------------------------------------------------------------------------------- /技术文档/Redis/2-Redis数据类型以及数据结构实现.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | #### 参考资料 4 | 5 | - [十二张图详解Redis的数据结构和对象系统](https://mp.weixin.qq.com/s?src=11×tamp=1561194655&ver=1684&signature=tiyZj*L1R1yHP3yQUcw6eJPJ1PWTRToOcqhrPvvKC7COAvC31Pp8BgTHiAjeVW7qWwQw9n7yzzEIqaSTH2Pv2NsazHjH7vvdfG6gUAiw0i2Lu7jn2C9UP9eAbmZo3iLV&new=1) -------------------------------------------------------------------------------- /技术文档/Redis/3-Redis缓存.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Redis/3-Redis缓存.md -------------------------------------------------------------------------------- /技术文档/Redis/5-Redis-Cluster集群.md: -------------------------------------------------------------------------------- 1 | # Redis集群 2 | 3 | ## Redis集群方案有哪些 4 | 5 | 有两种: **codis架构**、**官方的redis cluster**。 6 | 7 | ## codis集群架构 8 | 9 | codis是豌豆荚基于go编写的redis。 10 | 11 | ## 官方Redis Cluster集群方案 12 | 13 | ![](pictures/2.jpg) 14 | 15 | 特点: 16 | 17 | - Redis官网推出的,先行扩展可以达到1000个节点 18 | - 没有中心架构 19 | - 一致性哈希思想 20 | - 客户端直连redis 21 | 22 | 23 | 24 | 25 | 26 | - [redis缓存-单机、集群](https://www.cnblogs.com/fengli9998/p/6755591.html) -------------------------------------------------------------------------------- /技术文档/Redis/7-Redis持久化.md: -------------------------------------------------------------------------------- 1 | # Redis持久化 2 | 3 | Redis支持两种数据持久化方式: **RDB**、**AOF**。 4 | 5 | ## RDB持久化 6 | 7 | >根据配置的规则定时将内存中的数据持久化到硬盘上 8 | 9 | 将redis在内存中的数据记录定时dump到磁盘上的RDB持久化。 10 | 11 | 在指定的时间间格里将内存中的数据集快照写入磁盘,实际上是fork一个子进程,先将数据写入临时文件,写入成功后,再替换之前的文件,二进制压缩。 12 | 13 | 14 | 15 | ## AOF持久化 16 | 17 | >每次执行写命令后将命令记录下来 18 | 19 | AOF是将redis的操作日志以追加的方式写入文件。 20 | 21 | 和mysql类似,用日志的形式记录服务器的每一个写、删除操作;以文本的方式记录;通过查看该文件可以查看到详细的操作细节。 22 | 23 | -------------------------------------------------------------------------------- /技术文档/Redis/8-Redis应用场景分析.md: -------------------------------------------------------------------------------- 1 | # Redis应用场景 2 | 3 | - 计数器 4 | - 排行榜 5 | - session 6 | - 发布订阅 7 | - 消息队列 8 | 9 | ## 实际场景 10 | 11 | ### 页面缓存 12 | 13 | 如果使用的是服务端内容渲染,可以使用redis将经常被请求的内容缓存起来,降低页面请求渲染的延迟 14 | 15 | ### 计数器/排行榜 16 | 17 | Redis是一个运行在内存中的C程序。 18 | Redis可以实现快速计数、查询缓存的功能,同时数据可以异步落地到其他数据源。 19 | 20 | - 访问计数,用户每访问一次,计数就增加1 21 | - 排行榜: 可以按时间、按数量、按集赞数进行排行 22 | 23 | ### session 24 | 用户已经登陆的信息存放在redis中,每次用户更新或查询耕录信息可以直接从redis中获取。 25 | 26 | ### 消息队列 27 | 28 | 利用list数据类型可以构建一个简单高效的队列 29 | 30 | ### 发布订阅 31 | 32 | pub/sub 是Redis内置的发布订阅功能,可以创建多人在线聊天系统、通知触发等 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | #### 参考资料 54 | 55 | - [redis缓存-单机、集群](https://www.cnblogs.com/fengli9998/p/6755591.html) -------------------------------------------------------------------------------- /技术文档/Redis/999-Redis运维系统命令.md: -------------------------------------------------------------------------------- 1 | # Redis运维系统命令 2 | 3 | ## 下载解压 4 | ``` 5 | wget http://download.redis.io/releases/redis-5.0.5.tar.gz 6 | tar xzf redis-5.0.5.tar.gz 7 | cd redis-5.0.5 8 | make 9 | ``` 10 | 11 | ```shell 12 | tar -zxvf redis-5.0.5.tar.gz 13 | ``` 14 | 15 | 进入根目录查看: 16 | 17 | ```shell 18 | 00-RELEASENOTES CONTRIBUTING deps Makefile README.md runtest runtest-moduleapi sentinel.conf tests 19 | BUGS COPYING INSTALL MANIFESTO redis.conf runtest-cluster runtest-sentinel src utils 20 | ``` 21 | 22 | -------------------------------------------------------------------------------- /技术文档/Redis/pictures/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Redis/pictures/1.jpg -------------------------------------------------------------------------------- /技术文档/Redis/pictures/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Redis/pictures/2.jpg -------------------------------------------------------------------------------- /技术文档/Zookeeper/img/1-一般性主从架构.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Zookeeper/img/1-一般性主从架构.jpg -------------------------------------------------------------------------------- /技术文档/Zookeeper/img/2-CMW.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Zookeeper/img/2-CMW.jpg -------------------------------------------------------------------------------- /技术文档/Zookeeper/img/2-zkservice.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Zookeeper/img/2-zkservice.jpg -------------------------------------------------------------------------------- /技术文档/Zookeeper/img/3-单机集群配置一.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Zookeeper/img/3-单机集群配置一.png -------------------------------------------------------------------------------- /技术文档/Zookeeper/img/3-单机集群配置三.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Zookeeper/img/3-单机集群配置三.png -------------------------------------------------------------------------------- /技术文档/Zookeeper/img/3-单机集群配置二.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Zookeeper/img/3-单机集群配置二.png -------------------------------------------------------------------------------- /技术文档/Zookeeper/img/3-单机集群配置五.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Zookeeper/img/3-单机集群配置五.png -------------------------------------------------------------------------------- /技术文档/Zookeeper/img/3-单机集群配置四.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Zookeeper/img/3-单机集群配置四.png -------------------------------------------------------------------------------- /技术文档/Zookeeper/img/4-会话在服务器之间转移.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Zookeeper/img/4-会话在服务器之间转移.png -------------------------------------------------------------------------------- /技术文档/Zookeeper/img/chapter9-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Zookeeper/img/chapter9-1.jpg -------------------------------------------------------------------------------- /技术文档/Zookeeper/img/chapter9-2Zk选举过程.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Zookeeper/img/chapter9-2Zk选举过程.jpg -------------------------------------------------------------------------------- /技术文档/Zookeeper/img/chapter9-2ZooKeeper内部原理三--ZooKeeper选举过程(延迟选举时长).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Zookeeper/img/chapter9-2ZooKeeper内部原理三--ZooKeeper选举过程(延迟选举时长).jpg -------------------------------------------------------------------------------- /技术文档/Zookeeper/img/chapter9-2ZooKeeper内部原理三--ZooKeeper选举过程(异常情况).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Zookeeper/img/chapter9-2ZooKeeper内部原理三--ZooKeeper选举过程(异常情况).jpg -------------------------------------------------------------------------------- /技术文档/Zookeeper/img/chapter9-2ZooKeeper内部原理三--ZooKeeper选举过程(正常).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Zookeeper/img/chapter9-2ZooKeeper内部原理三--ZooKeeper选举过程(正常).jpg -------------------------------------------------------------------------------- /技术文档/Zookeeper/img/chapter9-2服务器选举状态.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/Zookeeper/img/chapter9-2服务器选举状态.jpg -------------------------------------------------------------------------------- /技术文档/docker-build-image-with-step.md: -------------------------------------------------------------------------------- 1 | #####使用docker构建更小的镜像 2 | 3 | 1. 选择较小的基础镜像 4 | ```text 5 | FROM golang:alpine 6 | ``` 7 | 2. 分阶段build 8 | ```text 9 | FROM golang:alpine AS build-env 10 | WORKDIR /app 11 | ADD . /app 12 | RUN cd /app && go build -o goapp 13 | 14 | FROM alpine 15 | RUN apk update && \ 16 | apk add ca-certificates && \ 17 | update-ca-certificates && \ 18 | rm -rf /var/cache/apk/* 19 | WORKDIR /app 20 | COPY --from=build-env /app/goapp /app 21 | EXPOSE 8080 22 | ENTRYPOINT ./goapp 23 | ``` 24 | -------------------------------------------------------------------------------- /技术文档/go/update_package_by_mod.md: -------------------------------------------------------------------------------- 1 | #### go依赖包的版本升级和降级 2 | 3 | ##### 升级 4 | * 使用go list -m -versions 查看依赖包的相关版本 5 | 6 | ```shell 7 | go list -m -versions github.com/gin-gonic/gin 8 | ``` 9 | * 查看当前使用版本 10 | 11 | ```shell 12 | go list -m github.com/gin-gonic/gin 13 | ``` 14 | 15 | * 使用go get 指定版本 16 | 17 | ```shell 18 | go get github.com/gin-gonic/gin@v1.7.3 19 | ``` 20 | 21 | ##### 降级 22 | 23 | * 首先使用go mod edit来修改版本 24 | ```shell 25 | go mod edit -require=github.com/gin-gonic/gin@v1.7.3 26 | ``` 27 | 28 | *然后使用go mod tidy, 降级成功使用go mod -m查看版本信息 29 | -------------------------------------------------------------------------------- /技术文档/golang-compile.md: -------------------------------------------------------------------------------- 1 | ##### Golang 在 Mac、Linux、Windows 下如何交叉编译 2 | 3 | * Mac 下编译 Linux 和 Windows 64位可执行程序 4 | ```text 5 | CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go 6 | 7 | GOOS:目标平台的操作系统(darwin、freebsd、linux、windows) 8 | GOARCH:目标平台的体系架构(386、amd64、arm) 9 | 交叉编译不支持 CGO 所以要禁用它 10 | ``` 11 | -------------------------------------------------------------------------------- /技术文档/haproxy/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | haproxy: 4 | image: haproxy:1.7 5 | container_name: haproxy_v1 6 | restart: always 7 | volumes: 8 | - /home/zhao/go-proj/src/test-haproxy/haproxy:/etc/haproxy:ro 9 | command: ["haproxy", "-f", "/etc/haproxy/haproxy.cfg"] 10 | ports: 11 | - 80:80 12 | - 443:443 13 | - 3000:3000 14 | - 5000:5000 15 | -------------------------------------------------------------------------------- /技术文档/数据结构.md: -------------------------------------------------------------------------------- 1 | ####数据结构堆和栈的区别 2 | 3 | * 栈 4 | ```text 5 | 栈是一种先进后出的线性表,通常在栈顶进行数据的插入和删除 6 | ``` 7 | 8 | * 堆 9 | ```text 10 | 堆是一种经过排序的树形数据结构。 11 | 两个特性: 12 | 1. 堆中的某个节点的值总是不大于或不小于其父节点的值 13 | 2. 堆总是一颗完全二叉树 14 | ``` 15 | -------------------------------------------------------------------------------- /技术文档/缓存/01_mysql和redis缓存一致性解决方案.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/缓存/01_mysql和redis缓存一致性解决方案.png -------------------------------------------------------------------------------- /技术文档/缓存/02-CPU缓存结构-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/缓存/02-CPU缓存结构-01.png -------------------------------------------------------------------------------- /技术文档/网络丢包排查/chain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/网络丢包排查/chain.png -------------------------------------------------------------------------------- /技术文档/网络丢包排查/three-hand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/网络丢包排查/three-hand.png -------------------------------------------------------------------------------- /技术文档/规则引擎/img/1576132902440.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/规则引擎/img/1576132902440.png -------------------------------------------------------------------------------- /技术文档/规则引擎/img/1576133475159.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/规则引擎/img/1576133475159.png -------------------------------------------------------------------------------- /技术文档/高可用/img/1578043763376.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/高可用/img/1578043763376.png -------------------------------------------------------------------------------- /技术文档/高可用/img/1578043782006.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/高可用/img/1578043782006.png -------------------------------------------------------------------------------- /技术文档/高可用/img/1578043798504.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/高可用/img/1578043798504.png -------------------------------------------------------------------------------- /技术文档/高可用/img/1578043813760.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/高可用/img/1578043813760.png -------------------------------------------------------------------------------- /技术文档/高可用/img/1578043833525.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/高可用/img/1578043833525.png -------------------------------------------------------------------------------- /技术文档/高可用/img/1578043850043.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/高可用/img/1578043850043.png -------------------------------------------------------------------------------- /技术文档/高可用/img/1578043873233.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/高可用/img/1578043873233.png -------------------------------------------------------------------------------- /技术文档/高可用/img/1578043886303.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/高可用/img/1578043886303.png -------------------------------------------------------------------------------- /技术文档/高可用/img/1578043901270.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/高可用/img/1578043901270.png -------------------------------------------------------------------------------- /技术文档/高可用/img/1578043923325.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee501/go-notes/e33aba5d44ac1231b4345163ff6a90e0531c7c24/技术文档/高可用/img/1578043923325.png -------------------------------------------------------------------------------- /文件处理/copyfile.go: -------------------------------------------------------------------------------- 1 | package file 2 | 3 | import ( 4 | "io" 5 | "os" 6 | ) 7 | 8 | func CopyFile(toFile, fromFile string) (n int64, err error) { 9 | fromfile, err := os.Open(fromFile) 10 | if err != nil { 11 | return 12 | } 13 | defer fromfile.Close() 14 | 15 | tofile, err := os.Create(toFile) 16 | if err != nil { 17 | return 18 | } 19 | defer tofile.Close() 20 | 21 | return io.Copy(tofile, fromfile) 22 | } 23 | -------------------------------------------------------------------------------- /文件处理/file.md: -------------------------------------------------------------------------------- 1 | * File 2 | --- 3 | file is an interface to access the file part of a multipart message 4 | type File interface { 5 | io.Reader 6 | io.ReaderAt 7 | io.Seeker 8 | io.Closer 9 | } 10 | 11 | * FileHeader封装了文件的基本信息 12 | 13 | --- 14 | A FileHeader describes a file part of a multipart request. 15 | type FileHeader struct { 16 | Filename string //文件名 17 | Header textproto.MIMEHeader //MIME信息 18 | Size int64 //文件大小,单位bit 19 | content []byte //文件内容,类型[]byte 20 | tmpfile string //临时文件 21 | } 22 | 23 | 24 | 25 | ``` 26 | 使用os Openfile 创建一个文件并追加内容 27 | 参数os.O_CREATE|os.O_RDWR|os.O_APPEND, os.ModeAppend|os.ModePerm 28 | ``` -------------------------------------------------------------------------------- /文件处理/file_write.go: -------------------------------------------------------------------------------- 1 | package file 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "os" 7 | ) 8 | 9 | //写入文件 10 | func writeIntoFile(filename string) { 11 | outfile, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE, 0666) 12 | if err != nil { 13 | fmt.Printf("An error occurred with file opening or creation\n") 14 | return 15 | } 16 | defer outfile.Close() 17 | 18 | outWriter := bufio.NewWriter(outfile) 19 | 20 | for i := 0; i < 10; i++ { 21 | outWriter.WriteString("Hello golang") 22 | } 23 | outWriter.Flush() 24 | } 25 | -------------------------------------------------------------------------------- /文件处理/gzipped.go: -------------------------------------------------------------------------------- 1 | package file 2 | 3 | import ( 4 | "bufio" 5 | "compress/gzip" 6 | "fmt" 7 | "os" 8 | ) 9 | 10 | //读取压缩文件 11 | func ReadGzipFile(filename string) { 12 | var r *bufio.Reader 13 | file, err := os.Open(filename) 14 | if err != nil { 15 | fmt.Fscanf(os.Stderr, "%v, can't open %s: error: %s\n", os.Args[0], filename, err) 16 | os.Exit(0) 17 | } 18 | fz, err := gzip.NewReader(file) 19 | if err != nil { 20 | r = bufio.NewReader(file) 21 | } else { 22 | r = bufio.NewReader(fz) 23 | } 24 | 25 | for { 26 | line, err := r.ReadString('\n') 27 | if err != nil { 28 | println("done reading file") 29 | os.Exit(0) 30 | } 31 | fmt.Println(line) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /文件处理/line-read/read_by_line.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "io" 7 | "log" 8 | "os" 9 | "time" 10 | ) 11 | 12 | func readByLine(filepath string) { 13 | start := time.Now() 14 | file, err := os.Open(filepath) 15 | if err != nil { 16 | log.Println(err) 17 | return 18 | } 19 | defer file.Close() 20 | reader := bufio.NewReader(file) 21 | for { 22 | line, _, err := reader.ReadLine() 23 | if err == io.EOF { 24 | break 25 | } 26 | fmt.Println(string(line)) 27 | } 28 | fmt.Println("readEachLine spend : ", time.Now().Sub(start)) 29 | } 30 | 31 | func readLineByScanner(filepath string) { 32 | fileHandle, err := os.Open(filepath) 33 | if err != nil { 34 | log.Println(err) 35 | return 36 | } 37 | defer fileHandle.Close() 38 | lineScanner := bufio.NewScanner(fileHandle) 39 | for lineScanner.Scan() { 40 | // 如下代码打印每次读取的文件行内容 41 | fmt.Println(lineScanner.Text()) 42 | } 43 | fmt.Println("readLineByScanner spend : ", time.Now()) 44 | } 45 | -------------------------------------------------------------------------------- /文件处理/os-openfile/use-os-openfile-createfile.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | ) 7 | 8 | func main() { 9 | data := []byte("asdasdasd") 10 | fl, err := os.OpenFile("/Users/lichunliang/workspace/go/go-notes/text.txt", os.O_CREATE|os.O_RDWR|os.O_APPEND, os.ModeAppend|os.ModePerm) 11 | if err != nil { 12 | return 13 | } 14 | defer fl.Close() 15 | _, err = fl.Write(data) 16 | if err != nil { 17 | fmt.Println(err) 18 | } 19 | } -------------------------------------------------------------------------------- /文件处理/partial-read/part_read.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "log" 7 | "os" 8 | "time" 9 | ) 10 | 11 | var path = "/Users/lee/Downloads/tencent.dmg" 12 | 13 | func readBlock(filepath string) { 14 | start := time.Now() 15 | file, err := os.Open(filepath) 16 | if err != nil { 17 | log.Println(err) 18 | return 19 | } 20 | defer file.Close() 21 | //设置块大小 22 | buffer := make([]byte, 1024) 23 | //循环读取,处理读到数据的逻辑 24 | for { 25 | n, err := file.Read(buffer) 26 | if err != nil && err != io.EOF { 27 | log.Println(err) 28 | } 29 | if n == 0 { 30 | break 31 | } 32 | //处理读取到的数据 33 | } 34 | fmt.Println("the spend time :", time.Now().Sub(start)) 35 | } 36 | -------------------------------------------------------------------------------- /文件处理/printFilesUnderDir.go: -------------------------------------------------------------------------------- 1 | package file 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | ) 7 | 8 | func ListFiles(path string, level int) { 9 | fileInfo, err := ioutil.ReadDir(path) 10 | if err != nil { 11 | panic(err) 12 | } 13 | for _, info := range fileInfo { 14 | if info.IsDir() { 15 | for curHier := level; curHier > 0; curHier-- { 16 | fmt.Printf("|\t") 17 | } 18 | fmt.Println(info.Name()) 19 | ListFiles(path+"/"+info.Name(), level+1) 20 | } else { 21 | for curHier := level; curHier > 0; curHier-- { 22 | fmt.Printf("|\t") 23 | } 24 | fmt.Println(info.Name()) 25 | } 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /文件处理/whole-read/read_all.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "os" 7 | "time" 8 | ) 9 | 10 | var path = "/Users/lee/Downloads/tencent.dmg" 11 | 12 | func readAll(filepath string) { 13 | start := time.Now() 14 | //打开文件 15 | file, err := os.Open(path) 16 | if err != nil { 17 | log.Println(err) 18 | return 19 | } 20 | defer file.Close() 21 | //获取文件信息 22 | fileInfo , err := file.Stat() 23 | if err != nil { 24 | log.Println(err) 25 | return 26 | } 27 | //设置buffer大小 28 | buffer := make([]byte, fileInfo.Size()) 29 | //读取文件到buffer中 30 | n, err := file.Read(buffer) 31 | if err != nil { 32 | log.Println(err) 33 | return 34 | } 35 | fmt.Println(string(buffer[:n])) 36 | fmt.Println("the spend time :", time.Now().Sub(start)) 37 | } 38 | -------------------------------------------------------------------------------- /文件处理/wirte_info_type_file.go: -------------------------------------------------------------------------------- 1 | package file 2 | 3 | import ( 4 | "bufio" 5 | "encoding/json" 6 | "os" 7 | ) 8 | 9 | var filepath = "../test.info" 10 | 11 | type Info struct { 12 | Name string `json:"name"` 13 | Age int `json:"age"` 14 | Sex string `json:"sex"` 15 | } 16 | 17 | func saveInfo(filepath string) { 18 | info := Info{Name: "lee", Age: 22, Sex: "boy"} 19 | data, _ := json.Marshal(&info) 20 | file, _ := os.OpenFile(filepath, os.O_WRONLY|os.O_CREATE, 0666) 21 | defer file.Close() 22 | buf := bufio.NewWriter(file) 23 | buf.WriteString(string(data)) 24 | buf.Flush() 25 | } 26 | -------------------------------------------------------------------------------- /算法/hashmap/hashmap_test.go: -------------------------------------------------------------------------------- 1 | package hashmap 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestHashMap_AddKeyValue(t *testing.T) { 9 | hmap := CreateHashMap() 10 | fmt.Println(HashCode("test2")) 11 | hmap.AddKeyValue("test1", "value1") 12 | hmap.AddKeyValue("test2", "value2") 13 | fmt.Printf("hmap is %v\n", hmap.Buckets[17]) 14 | } 15 | 16 | func TestHashMap_GetValeuOfKey(t *testing.T) { 17 | hmap := CreateHashMap() 18 | hmap.AddKeyValue("test1", "value1") 19 | fmt.Println(hmap.GetValeuOfKey("test1")) 20 | } 21 | -------------------------------------------------------------------------------- /算法/leetcode/02-add-number-in-list/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | /* 4 | 连表相加算法 5 | input (2 -> 4 -> 3) + (5 -> 6 -> 4) 6 | output 7 -> 0 -> 8 7 | */ 8 | 9 | //定义连表 10 | type ListNode struct { 11 | Val int 12 | Next *ListNode 13 | } 14 | 15 | func AddTwoNumeber(left, right *ListNode) *ListNode { 16 | res := &ListNode{} 17 | cur := 0 18 | for left !=nil || right != nil { 19 | sum := cur 20 | if left != nil { 21 | sum += left.Val 22 | left = left.Next 23 | } 24 | if right != nil { 25 | sum += right.Val 26 | right = right.Next 27 | } 28 | //进位 29 | cur = sum / 10 30 | res.Next = &ListNode{Val: sum % 10} 31 | res = res.Next 32 | } 33 | return res.Next 34 | } 35 | -------------------------------------------------------------------------------- /算法/leetcode/03-substring-without-duplicate-char/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | 给定一个字符串,找出不不含有重复字符的最长字串的长度 7 | 8 | "pwwkew"的最长字串为"wke" 长度为3 9 | */ 10 | 11 | func SubString(s string) int { 12 | charMap := make(map[byte]bool, len(s)) 13 | curlen := 0 14 | for i:=0; i< len(s); i++ { 15 | if charMap[s[i]] == true { 16 | loop := i - curlen 17 | for loop < i { 18 | delete(charMap, s[loop]) 19 | curlen-- 20 | if s[loop] == s[i] { 21 | break 22 | } 23 | loop++ 24 | } 25 | } 26 | charMap[s[i]] = true 27 | curlen++ 28 | } 29 | return curlen 30 | } 31 | 32 | func main() { 33 | s := "pwwekew" 34 | fmt.Println(SubString(s)) 35 | } -------------------------------------------------------------------------------- /算法/leetcode/04-longest-substring-palindrome/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "math" 5 | ) 6 | 7 | /* 8 | 判断字符串的最长子回文 9 | "abcbdc" 10 | */ 11 | 12 | func LongestPalindrome(s string) string { 13 | l := len(s) 14 | if l <= 1 { 15 | return s 16 | } 17 | start, end := 0, 0 18 | for i := 0; i < l; i++ { 19 | //i为中心元素的下标 20 | len1 := cal(s, i, i) //中间回文为一个"abcbe" 21 | len2 := cal(s, i, i+1) //中间回文为两个 22 | len := int(math.Max(float64(len1), float64(len2))) 23 | //始终位置 24 | if len > end - start { 25 | //len=3, i=2 26 | start = i - (len- 1) / 2 27 | end = i + len/2 28 | } 29 | } 30 | return string(s[start:end+1]) 31 | } 32 | 33 | func cal(s string, i, j int) int { 34 | l, r := i, j 35 | for l >= 0 && r < len(s) && s[l] == s[r] { 36 | l-- 37 | r++ 38 | } 39 | return r - l - 1 40 | } 41 | -------------------------------------------------------------------------------- /算法/leetcode/04-longest-substring-palindrome/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestLongestPalindrome(t *testing.T) { 9 | s := "abcbdc" 10 | re := LongestPalindrome(s) 11 | fmt.Println(re) 12 | } 13 | -------------------------------------------------------------------------------- /算法/leetcode/05-median-of-two-sorted-arrays/median-of-two-sorted-arrays_test.go: -------------------------------------------------------------------------------- 1 | package median 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestFindMedianSortedArrays(t *testing.T) { 9 | nums1 := []int{1, 3, 6} 10 | nums2 := []int{3, 4, 5} 11 | re := FindMedianSortedArrays(nums1, nums2) 12 | if re != 3.5 { 13 | fmt.Println(re) 14 | t.Error("result is error, expected result is 3.5") 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /算法/leetcode/06-zigzag-conversion/zigzag-conversion.go: -------------------------------------------------------------------------------- 1 | package zigzag 2 | 3 | import "bytes" 4 | 5 | /* 6 | 按索引规律处理 7 | p = numRows * 2 - 2 8 | 第0行 0*p, 1*p 9 | 第r行 r, 1*p -r, 2*p + r 10 | 第n行 numRows - 1, numRows - 1 + p 11 | */ 12 | func ZigZagConvert(str string, numRows int) string { 13 | if numRows <= 1 || len(str) < numRows { 14 | return str 15 | } 16 | p := numRows * 2 - 2 17 | res := bytes.Buffer{} 18 | //处理第一行 19 | for i := 0; i < len(str); i += p { 20 | res.WriteByte(str[i]) 21 | } 22 | //处理中间行 23 | for r := 1; r < numRows - 1; r++ { 24 | //写入每行的第一个元素 25 | res.WriteByte(str[r]) 26 | for k := p; k - r < len(str); k += p { 27 | res.WriteByte(str[k-r]) 28 | if k + r < len(str) { 29 | res.WriteByte(str[k+r]) 30 | } 31 | } 32 | } 33 | 34 | //处理最后一行 35 | for i:=numRows -1; i 321 8 | -123 => 321 9 | */ 10 | func Reverse(x int) int { 11 | sign := 1 12 | res := 0 13 | if x < 0 { 14 | sign = -1 15 | x = x * sign 16 | } 17 | for x > 0 { 18 | temp := x % 10 19 | res = res * 10 + temp 20 | x = x / 10 21 | } 22 | res = res * sign 23 | if res > math.MaxInt32 || res < math.MinInt32 { 24 | res = 0 25 | } 26 | return res 27 | } 28 | -------------------------------------------------------------------------------- /算法/leetcode/07-reverse-int/reverse-int_test.go: -------------------------------------------------------------------------------- 1 | package reverse 2 | 3 | import "testing" 4 | 5 | func TestReverse(t *testing.T) { 6 | a := 123 7 | b := 2147483648 8 | a = Reverse(a) 9 | b = Reverse(b) 10 | if a != 321 { 11 | t.Error("reverse error, expected result is 321") 12 | } 13 | if b != 0 { 14 | t.Error("reverse error, expected result is 0") 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /算法/leetcode/08-string-into-int/string-to-int_test.go: -------------------------------------------------------------------------------- 1 | package atoi 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestMAtoi(t *testing.T) { 9 | str := " -123 bs" 10 | fmt.Println(MAtoi(str)) 11 | } 12 | -------------------------------------------------------------------------------- /算法/leetcode/09-number-palinfrome/palindrome-number.go: -------------------------------------------------------------------------------- 1 | package palinfrome 2 | 3 | import "strconv" 4 | 5 | func IsPalindrome(x int) bool { 6 | if x < 0 { 7 | return false 8 | } 9 | s := convert2String(x) 10 | for i, j := 0, len(s)-1; i < j; { 11 | if s[i] != s[j] { 12 | return false 13 | } 14 | i++ 15 | j-- 16 | } 17 | return true 18 | } 19 | 20 | func convert2String(x int) string { 21 | return strconv.Itoa(x) 22 | } 23 | -------------------------------------------------------------------------------- /算法/leetcode/09-number-palinfrome/palindrome-number_test.go: -------------------------------------------------------------------------------- 1 | package palinfrome 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestIsPalindrome(t *testing.T) { 9 | x := 1 10 | re := IsPalindrome(x) 11 | if !re { 12 | t.Error("check number is error, expected result is true") 13 | } 14 | x = 1221 15 | fmt.Println(IsPalindrome(x)) 16 | } 17 | -------------------------------------------------------------------------------- /算法/leetcode/10-regular-expression-match/regular-expression-match_test.go: -------------------------------------------------------------------------------- 1 | package regular 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestIsMatch(t *testing.T) { 9 | s := "abcd" 10 | p := "a.*" 11 | fmt.Println(IsMatch(s, p)) 12 | 13 | s = "a" 14 | p = "ab*" 15 | fmt.Println(IsMatch(s, p)) 16 | } 17 | -------------------------------------------------------------------------------- /算法/leetcode/11-container-with-most-area/most-area.go: -------------------------------------------------------------------------------- 1 | package container 2 | 3 | func MaxArea(height []int) int { 4 | i, j := 0, len(height) - 1 5 | max := 0 6 | 7 | //计算最大面积 8 | for i < j { 9 | l1, l2 := height[i], height[j] 10 | //最小值 11 | h := min(l1, l2) 12 | area := h * (j - i) 13 | if max < area { 14 | max = area 15 | } 16 | //移动游标 17 | if l1 < l2 { 18 | i++ 19 | } else { 20 | j-- 21 | } 22 | } 23 | return max 24 | } 25 | 26 | func min(a, b int) int { 27 | if a <= b { 28 | return a 29 | } 30 | return b 31 | } -------------------------------------------------------------------------------- /算法/leetcode/11-container-with-most-area/most-area_test.go: -------------------------------------------------------------------------------- 1 | package container 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestMaxArea(t *testing.T) { 9 | array := []int{4, 6, 8, 7, 3} 10 | re := MaxArea(array) 11 | fmt.Println(re) 12 | } 13 | -------------------------------------------------------------------------------- /算法/leetcode/12-integer-to-roman/integer-to-roman.go: -------------------------------------------------------------------------------- 1 | package roman 2 | 3 | //表驱动法:转换数字成罗马 4 | func IntToRoman(num int) string { 5 | d := [4][]string { 6 | {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"}, 7 | {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"}, 8 | {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"}, 9 | {"", "M", "MM", "MMM"}, 10 | } 11 | return d[3][num/1000] + d[2][num/100%10] + d[1][num/10%10] + d[0][num%10] 12 | } 13 | -------------------------------------------------------------------------------- /算法/leetcode/12-integer-to-roman/integer-to-roman_test.go: -------------------------------------------------------------------------------- 1 | package roman 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestIntToRoman(t *testing.T) { 9 | i := 3999 10 | m := IntToRoman(i) 11 | fmt.Println(m) 12 | } 13 | -------------------------------------------------------------------------------- /算法/leetcode/13-longestOnes/longestOnes.go: -------------------------------------------------------------------------------- 1 | package longestOnes 2 | 3 | /* 4 | 滑动窗口问题 5 | 最大连续1的个数 6 | 给定一个由若干 0 和 1 组成的数组 A,我们最多可以将 K 个值从 0 变成 1 。 7 | 返回仅包含 1 的最长(连续)子数组的长度 8 | 9 | 输入:A = [1,1,1,0,0,0,1,1,1,1,0], K = 2 10 | 输出:6 11 | 解释: 12 | [1,1,1,0,0,1,1,1,1,1,1] 13 | 粗体数字从 0 翻转到 1,最长的子数组长度为 6。 14 | 15 | 解题思路: 16 | 1,维持窗口内0的个数<=K 17 | 2,我们定义指针l,r分别表示窗口左右下标,移动r,当A[r]==0的时候我们增加0的个数记录sum,分两种情况 18 | A,sum>K 这个时候需要移动左指针,让0的个数减1 19 | B,sum<=K 无需处理,继续移动右指针 20 | */ 21 | func LongestOnes(array []int, K int) int { 22 | if K == 0 || len(array) < 1 { 23 | return 0 24 | } 25 | l := 0 26 | sum := 0 27 | max := 0 28 | 29 | for r := 0; r < len(array); r++ { 30 | if array[r]==0{ 31 | sum++ 32 | if sum>K{ 33 | for array[l]!=0{ 34 | l++ 35 | } 36 | l++ 37 | sum-- 38 | } 39 | } 40 | 41 | if r - l + 1 > max { 42 | max = r -l + 1 43 | } 44 | } 45 | 46 | return max 47 | } 48 | -------------------------------------------------------------------------------- /算法/leetcode/13-longestOnes/longestOnes_test.go: -------------------------------------------------------------------------------- 1 | package longestOnes 2 | 3 | import "testing" 4 | 5 | func TestLongestOnes(t *testing.T) { 6 | array := []int{1,1,0,0,0,0,1,1,1} 7 | K := 3 8 | re := LongestOnes(array, K) 9 | if re != 6 { 10 | t.Error("error, expected value is 6") 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /算法/leetcode/15-mirror-tree/mirror_tree.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type Tree struct { 4 | Val int 5 | Left *Tree 6 | Right *Tree 7 | } 8 | 9 | func isMirror(tree *Tree) bool { 10 | if tree == nil { 11 | return true 12 | } 13 | return checkTree(tree.Left, tree.Right) 14 | } 15 | 16 | func checkTree(left, right *Tree) bool { 17 | if left == nil && right == nil { 18 | return true 19 | } 20 | if (left == nil && right != nil) || (left != nil && right == nil) { 21 | return false 22 | } 23 | return left.Val == right.Val && checkTree(left.Left, left.Right) && checkTree(right.Left, right.Right) 24 | } 25 | -------------------------------------------------------------------------------- /算法/leetcode/15-mirror-tree/trans_mirror.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | /* 4 | 4 5 | / \ 6 | 2 7 7 | / \ / \ 8 | 1 3 6 9 9 | */ 10 | //输出镜像 11 | func transMirror(root *Tree) *Tree { 12 | if root != nil { 13 | root.Left, root.Right = root.Right, root.Left 14 | transMirror(root.Left) 15 | transMirror(root.Right) 16 | } 17 | return root 18 | } 19 | -------------------------------------------------------------------------------- /算法/leetcode/alternate-print.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | "sync" 7 | ) 8 | 9 | //交替打印算法 10 | func alternatePrint() { 11 | letter, number := make(chan bool), make(chan bool) 12 | wait := sync.WaitGroup{} 13 | go func() { 14 | i := 1 15 | for { 16 | select { 17 | case <-number: 18 | fmt.Println(i) 19 | i++ 20 | fmt.Println(i) 21 | i++ 22 | letter <- true 23 | break 24 | default: 25 | break 26 | } 27 | } 28 | }() 29 | wait.Add(1) 30 | go func(wait *sync.WaitGroup) { 31 | str := "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 32 | i := 0 33 | for { 34 | select { 35 | case <-letter: 36 | if i >= strings.Count(str, "")-1 { 37 | wait.Done() 38 | return 39 | } 40 | fmt.Println(str[i : i+1]) 41 | i++ 42 | fmt.Println(str[i : i+1]) 43 | i++ 44 | number <- true 45 | break 46 | default: 47 | break 48 | } 49 | } 50 | 51 | }(&wait) 52 | number <- true 53 | wait.Wait() 54 | } 55 | -------------------------------------------------------------------------------- /算法/leetcode/concurrency_merge_sort/mergeSortMulti_test.go: -------------------------------------------------------------------------------- 1 | package concurrency_merge_sort 2 | 3 | import "testing" 4 | 5 | var array []int 6 | 7 | func init() { 8 | for i := 0; i < 100000; i++ { 9 | array = append(array, i) 10 | } 11 | } 12 | 13 | func BenchmarkMergeSort(b *testing.B) { 14 | for n := 0; n < b.N; n++ { 15 | MergeSort(array) 16 | } 17 | } 18 | 19 | func BenchmarkMergeSortMulti(b *testing.B) { 20 | for n := 0; n < b.N; n++ { 21 | MergeSortMulti(array) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /算法/leetcode/concurrent_sum.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "sync" 5 | ) 6 | 7 | func sum(data []int) int { 8 | s := 0 9 | l := len(data) 10 | const N = 5 11 | seg := l / N 12 | 13 | var wg sync.WaitGroup 14 | wg.Add(N) // 直接加N个 15 | 16 | for i := 0; i < N; i++ { 17 | go func(i int) { 18 | tmpS := data[i*seg : (i+1)*seg] 19 | ll := len(tmpS) 20 | for j := 0; j < ll; j++ { 21 | s += tmpS[j] 22 | } 23 | wg.Done() // 一个goroutine运行完 24 | }(i) 25 | } 26 | wg.Wait() // 等N个goroutine都运行完 27 | 28 | return s 29 | } 30 | 31 | /* 32 | func main() { 33 | data := []int{1,2,3,4,5,6,7,7,8,8,8,7,9,10} 34 | s := sum(data) 35 | fmt.Println(s) 36 | } 37 | */ 38 | -------------------------------------------------------------------------------- /算法/leetcode/cstdio/cstdio.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | //var n int 7 | //step := 0 8 | //fmt.Println("请输入n值:") 9 | //fmt.Scan(&n) 10 | //n, step = getStep(n, step) 11 | //fmt.Println(n, step) 12 | var a, b int 13 | fmt.Scanf("%d-%d", &a, &b) 14 | fmt.Println(a, b) 15 | fmt.Println(getStep(a, b)) 16 | } 17 | 18 | func getStep(n, step int) (int, int) { 19 | for n != 1 { 20 | if n%2 == 0 { 21 | n = n / 2 22 | } else { 23 | n = (3*n + 1) / 2 24 | } 25 | step++ 26 | } 27 | return n, step 28 | } 29 | -------------------------------------------------------------------------------- /算法/leetcode/fetchNumber/fetchNum.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | nums := []int{1, 1, 2, 3, 4, 2, 3, 4, 5} 7 | fmt.Println(fetchNum(nums)) 8 | } 9 | 10 | func fetchNum(nums []int) int { 11 | l := len(nums) 12 | for i := 0; i < l; i++ { 13 | flag := false 14 | for j := 0; j < l; j++ { 15 | if nums[i] == nums[j] && i != j { 16 | flag = true 17 | } 18 | } 19 | if !flag { 20 | return nums[i] 21 | } 22 | } 23 | return -1 24 | } 25 | -------------------------------------------------------------------------------- /算法/leetcode/fisherYetes_shuffle/shuffle.go: -------------------------------------------------------------------------------- 1 | package fisherYetes_shuffle 2 | 3 | import ( 4 | "math/rand" 5 | "time" 6 | ) 7 | 8 | //洗牌算法 9 | func Shuffle(array []int) { 10 | rand.Seed(time.Now().UnixNano()) 11 | var i, j int 12 | for i = len(array) - 1; i > 0; i -- { 13 | j = rand.Intn(i + 1) 14 | array[i], array[j] = array[j], array[i] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /算法/leetcode/fisherYetes_shuffle/shuffle_test.go: -------------------------------------------------------------------------------- 1 | package fisherYetes_shuffle 2 | 3 | import ( 4 | "strconv" 5 | "testing" 6 | ) 7 | 8 | func TestShuffle(t *testing.T) { 9 | array := []int{1,2,3,4,5,6,7,8,9} 10 | //十次洗牌 11 | for i := 0; i < 10; i++ { 12 | t.Run(strconv.FormatInt(int64(i), 10) + "洗牌", func(t *testing.T) { 13 | Shuffle(array) 14 | t.Log(array) 15 | }) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /算法/leetcode/levelTraveTree/level_traves_tree.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | var res [][]int 6 | 7 | func main() { 8 | res = [][]int{} 9 | head := &TreeNode{} 10 | levelTree(head, 0) 11 | fmt.Println(res) 12 | } 13 | 14 | type TreeNode struct { 15 | Val int 16 | Left *TreeNode 17 | Right *TreeNode 18 | } 19 | 20 | /* 21 | 3 22 | / \ 23 | 9 20 24 | / \ 25 | 15 7 26 | */ 27 | func levelTree(head *TreeNode, level int) { 28 | if head != nil { 29 | //当前层初始化 30 | if len(res) == level { 31 | res = append(res, []int{}) 32 | } 33 | res[level] = append(res[level], head.Val) 34 | levelTree(head.Left, level+1) 35 | levelTree(head.Right, level+1) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /算法/leetcode/list-move-right-and-reverse-list.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | /* 4 | 旋转链表, 将每个节点向右移k位置 5 | */ 6 | 7 | type ListNode struct { 8 | Val int 9 | Next *ListNode 10 | } 11 | 12 | func rotateRight(head *ListNode, k int) *ListNode { 13 | if head == nil { 14 | return head 15 | } 16 | 17 | tail := head 18 | length := 1 19 | //计算链表长度 20 | for tail.Next != nil { 21 | tail = tail.Next 22 | length++ 23 | } 24 | //连成环 25 | tail.Next = head 26 | 27 | for i := 0; i < length-k%length; i++ { 28 | tail = tail.Next 29 | head = head.Next 30 | } 31 | //打断环 32 | tail.Next = nil 33 | return head 34 | } 35 | 36 | func reverseList(head *ListNode) *ListNode { 37 | cur := head 38 | var pre *ListNode = nil 39 | for cur != nil { 40 | pre, cur, cur.Next = cur, cur.Next, pre 41 | } 42 | return pre 43 | } 44 | -------------------------------------------------------------------------------- /算法/leetcode/mergeSort/mergeSort.go: -------------------------------------------------------------------------------- 1 | package main 2 | func main() { 3 | 4 | } 5 | func mergeSort(nums []int) []int { 6 | n := len(nums) 7 | if n < 2 { 8 | return nums 9 | } 10 | key := n / 2 11 | left := mergeSort(nums[0:key]) 12 | right := mergeSort(nums[key:]) 13 | return merge(left, right) 14 | } 15 | func merge(left, right []int) []int { 16 | newArr := make([]int, len(left)+len(right)) 17 | i, j, index := 0, 0, 0 18 | for { 19 | if left[i] > right[j] { 20 | newArr[index] = right[j] 21 | index++ 22 | j++ 23 | if j == len(right) { 24 | copy(newArr[index:], left[i:]) 25 | break 26 | } 27 | } else { 28 | newArr[index] = left[i] 29 | index++ 30 | i++ 31 | if i == len(left) { 32 | copy(newArr[index:], right[j:]) 33 | break 34 | } 35 | } 36 | } 37 | return newArr 38 | } 39 | -------------------------------------------------------------------------------- /算法/leetcode/red-packet/red_packet.go: -------------------------------------------------------------------------------- 1 | package red_packet 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "time" 7 | ) 8 | 9 | //a simple red packet algorithm 10 | /* 11 | count 红包数量 12 | money 红包金额 13 | */ 14 | func RedPacket(count, money int) { 15 | for i := 0; i < count; i++ { 16 | m := randomMoney(count - i, money) 17 | fmt.Printf("%d ", m) 18 | money -= m 19 | } 20 | } 21 | 22 | func randomMoney(remainCount, remainMoney int) int { 23 | if remainCount == 1 { 24 | return remainMoney 25 | } 26 | rand.Seed(time.Now().UnixNano()) 27 | 28 | //min最小红包 29 | min := 1 30 | max := remainMoney / remainCount * 2 31 | //rand 0~max 32 | money := rand.Intn(max) + min 33 | return money 34 | } 35 | -------------------------------------------------------------------------------- /算法/leetcode/red-packet/red_packet_test.go: -------------------------------------------------------------------------------- 1 | package red_packet 2 | 3 | import ( 4 | "strconv" 5 | "testing" 6 | ) 7 | 8 | func TestRedPacket(t *testing.T) { 9 | for i := 0; i < 10; i++ { 10 | t.Run(strconv.FormatInt(int64(i), 10)+"随机", func(t *testing.T) { 11 | RedPacket(10, 500) 12 | }) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /算法/leetcode/slide-win/slide_window.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | // test slidingWindow 5 | } 6 | 7 | func slidingWindow(data []int, k int) []int { 8 | var result []int 9 | if len(data) == 0 { 10 | return result 11 | } 12 | if len(data) <= k { 13 | result = append(result, getMax(data)) 14 | return result 15 | } 16 | var windowSlice []int 17 | index := 0 18 | for i := k; i <= len(data); i ++ { 19 | windowSlice = data[index:i] 20 | result = append(result, getMax(windowSlice)) 21 | index++ 22 | } 23 | return result 24 | } 25 | 26 | func getMax(data []int) int { 27 | max := data[0] 28 | for _, v := range data { 29 | if v > max { 30 | max = v 31 | } 32 | } 33 | return max 34 | } -------------------------------------------------------------------------------- /算法/leetcode/sort-algorithm/bubbleSort.go: -------------------------------------------------------------------------------- 1 | package sort_algorithm 2 | 3 | func bubbleSort(array []int) { 4 | if len(array) < 2 { 5 | return 6 | } 7 | for i := 0; i < len(array)-1; i++ { 8 | for j := 0; j < len(array)-1-i; j++ { 9 | if array[j] > array[j+1] { 10 | array[j], array[j+1] = array[j+1], array[j] 11 | } 12 | } 13 | } 14 | } 15 | 16 | /* 17 | func main() { 18 | var array []int = []int{1,9, 8,3,6} 19 | bubbleSort(array) 20 | fmt.Println(array) 21 | } 22 | */ 23 | -------------------------------------------------------------------------------- /算法/leetcode/sort-algorithm/insertSorted.go: -------------------------------------------------------------------------------- 1 | package sort_algorithm 2 | 3 | func insertSort(array []int) { 4 | if len(array) < 2 { 5 | return 6 | } 7 | for i := 1; i < len(array); i++ { 8 | key := array[i] 9 | for j := i; j > 0; j-- { 10 | if array[j-1] > key { 11 | array[j], array[j-1] = array[j-1], array[j] 12 | } 13 | } 14 | 15 | } 16 | } 17 | 18 | func binarySearch(s []int, key int) int { 19 | begin := 0 20 | end := len(s) - 1 21 | for { 22 | mid := (end - begin) / 2 23 | if s[mid] == key { 24 | return mid 25 | } else if s[mid] < key { 26 | begin = mid + 1 27 | } else { 28 | end = mid - 1 29 | } 30 | } 31 | return -1 32 | } 33 | 34 | /* 35 | func main() { 36 | arr := []int{6, 5, 4, 3, 2, 1} 37 | //i := binarySearch(arr, 3) 38 | insertSort(arr) 39 | fmt.Println(arr) 40 | //fmt.Println(binarySearch(arr, 3)) 41 | } 42 | */ 43 | -------------------------------------------------------------------------------- /算法/leetcode/sort-algorithm/selectsort/selectSort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | 5 | } 6 | 7 | func selectSort(array []int) { 8 | if len(array) < 2 { 9 | return 10 | } 11 | for i:=0; i < len(array); i++ { 12 | min := i 13 | for j := i+1; j < len(array); j++ { 14 | if array[min] > array[j] { 15 | min = j 16 | } 17 | } 18 | if min != i{ 19 | array[min], array[i] = array[i], array[min] 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /算法/leetcode/string-diff.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "strings" 5 | ) 6 | 7 | func isUniqueString(s string) bool { 8 | if strings.Count(s, "") > 256 { 9 | return false 10 | } 11 | for _, v := range s { 12 | if v > 127 { 13 | return false 14 | } 15 | if strings.Count(s, string(v)) > 1 { 16 | return false 17 | } 18 | } 19 | return true 20 | } 21 | 22 | /* 23 | func main() { 24 | s := "abcdeab" 25 | fmt.Println(strings.Count(s, "a")) 26 | fmt.Println(isUniqueString(s)) 27 | } 28 | */ 29 | -------------------------------------------------------------------------------- /算法/lru/lru_test.go: -------------------------------------------------------------------------------- 1 | package lru 2 | -------------------------------------------------------------------------------- /网络编程/socket_demo/accept-and-send-with-concurrency/client.go: -------------------------------------------------------------------------------- 1 | package concurrency 2 | 3 | // 4 | //import ( 5 | // "fmt" 6 | // "net" 7 | // "strconv" 8 | //) 9 | // 10 | //func client() { 11 | // //创建tcp address 12 | // addr, _ := net.ResolveTCPAddr("tcp4", "localhost:8899") 13 | // for i := 0; i < 5; i++ { 14 | // //链接服务器 15 | // tcpconn, _ := net.DialTCP("tcp4", nil, addr) 16 | // //向服务端发送数据 17 | // count, _ := tcpconn.Write([]byte("客户端发送的数据" + strconv.Itoa(i))) 18 | // fmt.Println("客户端向服务端发送的数据量为:", count) 19 | // //接收服务端返回数据 20 | // b := make([]byte, 1024) 21 | // n, _ := tcpconn.Read(b) 22 | // fmt.Println("来自服务端的信息", string(b[:n])) 23 | // //关闭链接 24 | // tcpconn.Close() 25 | // } 26 | //} 27 | // 28 | //func main() { 29 | // client() 30 | //} 31 | -------------------------------------------------------------------------------- /网络编程/socket_demo/accept-and-send-with-concurrency/server.go: -------------------------------------------------------------------------------- 1 | package concurrency 2 | 3 | // 4 | //import ( 5 | // "fmt" 6 | // "net" 7 | //) 8 | // 9 | //func serve() { 10 | // //创建tcp address, 指定tcp4协议和8899端口 11 | // address, _ := net.ResolveTCPAddr("tcp4", "localhost:8899") 12 | // //监听地址 13 | // tcplistener, _ := net.ListenTCP("tcp4", address) 14 | // 15 | // fmt.Println("服务已启动") 16 | // for { 17 | // 18 | // //等待接收客户端消息 19 | // conn, _ := tcplistener.Accept() 20 | // go func() { 21 | // //读取客户端消息 22 | // b := make([]byte, 1024) 23 | // n, _ := conn.Read(b) 24 | // fmt.Println("服务端接收的数据", string(b[:n])) 25 | // 26 | // //向客户端发送数据 27 | // conn.Write([]byte("来自服务端的消息")) 28 | // //关闭链接 29 | // conn.Close() 30 | // }() 31 | // } 32 | //} 33 | // 34 | //func main() { 35 | // serve() 36 | //} 37 | -------------------------------------------------------------------------------- /网络编程/tcpdemo/agent/agent.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "net" 7 | "os" 8 | ) 9 | 10 | // 处理从服务端接收消息的函数 11 | func receiveMessages(conn net.Conn) { 12 | scanner := bufio.NewScanner(conn) 13 | for scanner.Scan() { 14 | fmt.Printf("Received from server: %s\n", scanner.Text()) 15 | } 16 | } 17 | 18 | func main() { 19 | conn, err := net.Dial("tcp", "localhost:8090") 20 | if err != nil { 21 | fmt.Println("Error connecting to server:", err) 22 | os.Exit(1) 23 | } 24 | defer conn.Close() 25 | 26 | // 启动一个 goroutine 来接收消息 27 | go receiveMessages(conn) 28 | 29 | writer := bufio.NewWriter(conn) 30 | for { 31 | var message string 32 | fmt.Print("Send message to server: ") 33 | fmt.Scanln(&message) 34 | 35 | // 发送消息 36 | writer.WriteString(message + "\n") 37 | writer.Flush() 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /网络编程/tcp粘包/README.md: -------------------------------------------------------------------------------- 1 | #### tcp粘包的处理 2 | 3 | * 在tcp header 写入固定大小的字节 -------------------------------------------------------------------------------- /网络编程/tcp粘包/client/cli.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | 7 | log "github.com/sirupsen/logrus" 8 | 9 | "github.com/sevenelevenlee/go-notes/tcp_package/proto" 10 | ) 11 | 12 | func main() { 13 | conn, err := net.Dial("tcp", "127.0.0.1:10001") 14 | if err != nil { 15 | log.Info("dial failed, err", err) 16 | return 17 | } 18 | defer conn.Close() 19 | for i := 0; i < 20; i++ { 20 | msg := `Hello, Hello. How are you?` 21 | data, err := proto.Encode(msg) 22 | if err != nil { 23 | fmt.Println("encode msg failed, err:", err) 24 | return 25 | } 26 | conn.Write(data) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /网络编程/tcp粘包/serve/serve.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "io" 6 | "net" 7 | 8 | "github.com/sevenelevenlee/go-notes/tcp_package/proto" 9 | 10 | log "github.com/sirupsen/logrus" 11 | ) 12 | 13 | func main() { 14 | listen, err := net.Listen("tcp", "127.0.0.1:10001") 15 | if err != nil { 16 | log.Info("listen failed: ", err) 17 | return 18 | } 19 | defer listen.Close() 20 | for { 21 | conn, err := listen.Accept() 22 | if err != nil { 23 | log.Info("accept failed: ", err) 24 | continue 25 | } 26 | go processConn(conn) 27 | } 28 | } 29 | 30 | func processConn(conn net.Conn) { 31 | defer conn.Close() 32 | reader := bufio.NewReader(conn) 33 | for { 34 | msg, err := proto.Decode(reader) 35 | if err == io.EOF { 36 | return 37 | } 38 | if err != nil { 39 | log.Info("decode msg failed, err:", err) 40 | return 41 | } 42 | log.Info("收到client发来的数据:", msg) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /面试/01-defer-panic/defer-panic.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | 考点: 7 | defer和panic 8 | defer先入后出(类似栈的数据结构) 9 | defer在panic前可以执行 10 | */ 11 | func main() { 12 | deferCall() 13 | } 14 | 15 | func deferCall() { 16 | defer func() { 17 | fmt.Println("输入前") 18 | }() 19 | 20 | defer func() { 21 | fmt.Println("输入中") 22 | }() 23 | 24 | defer func() { 25 | fmt.Println("输入后") 26 | }() 27 | 28 | panic("检查到异常") 29 | } 30 | -------------------------------------------------------------------------------- /面试/02-for-range/for-range.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | 考点: 7 | for range循环,会创建每个元素的副本,所以v的地址是相同的 8 | range 表达式复制一个副本_, v := range slice, 这里的slice是副本引用 9 | */ 10 | 11 | func forRangeDemo() { 12 | slice := []int{1, 2, 3, 4} 13 | //这里的v是循环对象每个元素的副本 14 | for _, v := range slice { 15 | fmt.Printf("%p\n", &v) 16 | fmt.Println(v) 17 | } 18 | 19 | m := make(map[int]*int) 20 | for key, val := range slice { 21 | //将切片的每个地址作为map值,需要赋值一个新的变量 22 | value := val 23 | m[key] = &value 24 | } 25 | //此时得到的结果为0->1, 1->2 26 | for k, v := range m { 27 | fmt.Println(k, "----->", *v) 28 | } 29 | /* 30 | 1 31 | 0xc000094000 32 | 2 33 | 0xc000094000 34 | 3 35 | 0xc000094000 36 | 4 37 | 0xc000094000 38 | 0 -----> 1 39 | 1 -----> 2 40 | 2 -----> 3 41 | 3 -----> 4 42 | */ 43 | } 44 | -------------------------------------------------------------------------------- /面试/03-make-new/make-new.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | make和new区别 7 | new(T)返回一个指针*T,该指针指向新分配的类型为T的零值,适用于值类型:数组和结构体 8 | make(T)返回的是初始化后的T的引用, 适用于slice map channel 9 | new分配的空间被清零,make分配后,会进行初始化 10 | 声明指针不会开辟内存地址,只是准备要指向内存某个空间 11 | */ 12 | func main() { 13 | //声明值类型和引用类型区别 14 | //数组是值类型 15 | a := new([2]int) 16 | fmt.Println(a) 17 | //切片是引用类型, 不应该使用new 18 | b := new([]int) 19 | fmt.Println(b) 20 | //(*b)[0] = 1会报错, index out of range 21 | } 22 | -------------------------------------------------------------------------------- /面试/04-append-multi-params/append-multi-params.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | //考点: 7 | //不能使用new来初始化一个切片,append无法对*[]int类型的指针进行操作 8 | //list := new([]int) 9 | list := make([]int, 1) 10 | list = append(list, 1) 11 | fmt.Println(list) //输出[0,1] 12 | 13 | /* 14 | 考点:多参数,append不能直接对切片进行操作, 需要使用多参操作符处理 15 | */ 16 | s := []int{1,2,3,4} 17 | n := []int{5,6} 18 | s = append(s, n...) 19 | fmt.Println(s) 20 | } 21 | -------------------------------------------------------------------------------- /面试/05-struct-Equal-Issue/struct-Equal-Issue.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | 考点: 7 | 关于结构体相等问题 8 | 1. 相同类型的结构体才能进行比较,属性类型和顺序必须都要相同 9 | 2. 成员都为值类型才能比较 10 | */ 11 | func main() { 12 | s1 := struct { 13 | age int 14 | name string 15 | }{age: 11, name: "lee"} 16 | 17 | s2 := struct { 18 | age int 19 | name string 20 | }{age: 11, name: "lee"} 21 | 22 | //s1和s2可以比较 23 | if s1 == s2 { 24 | fmt.Println("s1 == s2") 25 | } 26 | 27 | n1 := struct { 28 | age int 29 | m map[string]string 30 | }{age: 12, m: map[string]string{"a": "1"}} 31 | 32 | n2 := struct { 33 | age int 34 | m map[string]string 35 | }{age: 12, m: map[string]string{"a": "1"}} 36 | 37 | fmt.Println(n1, n2) 38 | //n1 和 n2无法比较,不能通过编译 39 | //if n1 == n2 { 40 | // 41 | //} 42 | } 43 | -------------------------------------------------------------------------------- /面试/06-type-alias/type-alias.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | 考点: 7 | 指针变量p取值方式, 可以通过p.name 或(*p).name, 因为go将p.name转换成(*p).name 8 | */ 9 | type People struct { 10 | name string 11 | } 12 | 13 | func main() { 14 | p := new(People) 15 | p.name = "lee" 16 | fmt.Println(p.name) 17 | fmt.Println((*p).name) 18 | convert() 19 | } 20 | 21 | /* 22 | 考点: 23 | 类型别名和类型定义 24 | */ 25 | //定义新的类型 26 | type Mint int 27 | //类型别名 28 | type Nint = int 29 | 30 | func convert() { 31 | var i int = 1 32 | //类型定义需要强制转换 33 | var j Mint = Mint(i) 34 | //类型别名可以直接赋值 35 | var e Nint = i 36 | fmt.Println(j, e) 37 | } 38 | -------------------------------------------------------------------------------- /面试/07-append-and-slice/append-and-slice.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | append向切片追加元素,只有cap不够的情况下,底层数组才重新分配内存 7 | 在make初始化切片的时候给出了足够的容量,append操作不会创建新的切片 8 | 切片是引用类型,修改具体的元素,改变原切片 9 | 10 | slice的实现就是复制时, 11 | 如果不超过容量那么底层数组数据共享, 但是长度数据或者说有效位数是不共享的, 各玩各的. 12 | 13 | */ 14 | func main() { 15 | i := []int{1, 2, 3} 16 | fmt.Printf("append前地址%p\n", i) 17 | i = append(i, 4) 18 | fmt.Printf("append前地址%p\n", i) 19 | //app(i) 20 | fmt.Printf("%#v\n", i) 21 | ap(i) 22 | fmt.Printf("%#v\n", i) 23 | s := []int{1, 2, 3, 4} 24 | //fmt.Printf("append前地址%p\n", s) 25 | //s = s[:2 + copy(s[2:], s[3:])] 26 | //fmt.Printf("append前地址%p\n", s) 27 | //fmt.Println(s) 28 | b := make([]int, len(s)) 29 | copy(b, s) 30 | fmt.Println(b) 31 | } 32 | 33 | //append重新分配底层数组,i的地址不同了 34 | func app(i []int) { 35 | fmt.Printf("append前地址%p\n", i) 36 | i = append(i, 4) 37 | fmt.Printf("append后地址%p\n", i) 38 | } 39 | 40 | //修改切片元素 41 | func ap(i []int) { 42 | i[0] = 4 43 | } 44 | -------------------------------------------------------------------------------- /面试/08-interface-choose-and-nil-point/interface-choose-and-nil-point.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | 考点: 7 | nil的赋值问题 8 | nil只能赋值给指针, chan, map, slice, interface和func类型的变量 9 | error是内置接口类型,也可以赋值nil 10 | */ 11 | 12 | var m interface{} = nil 13 | 14 | /* 15 | 考点: init()函数 16 | 一个包中可以有多个init 函数 17 | 不同包的init函数是根据导入的依赖关系来执行的,如A import B, B import C, 此时执行顺序为C, B, A 18 | 一个包被多次引用, init只会执行一次 19 | */ 20 | 21 | /* 22 | 考点: 类型选择 23 | 类型选择语法 i.(type), i只能为interface 24 | */ 25 | 26 | func GetValue() interface{} { 27 | return 1 28 | } 29 | 30 | func main() { 31 | v := GetValue() 32 | switch v.(type) { 33 | case int: 34 | fmt.Println("int") 35 | case string: 36 | fmt.Println("string") 37 | case interface{}: 38 | fmt.Println("interface") 39 | default: 40 | fmt.Println("unknown") 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /面试/09-map-and-slice-as-param-unfold/map-and-slice-as-param-unfold.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | 考点:map中不存在key时,返回该元素类型的零值 7 | delete map中不存在的键值对时, 不会报错 8 | map的 key: 可以是很多种类型,比如 bool, 数字,string, 指针, channel , 9 | 还有只包含前面几个类型的 interface types, structs, arrays 10 | 11 | 显然,slice, map 还有 function 是不可以了,因为这几个没法用 == 来判断 12 | */ 13 | type person struct { 14 | name string 15 | } 16 | func mapIssue() { 17 | var m map[person]int 18 | p := person{name: "lee"} 19 | delete(m, p) 20 | fmt.Println(m[p]) 21 | //m[p] = 1 panic: assignment to entry in nil map 22 | } 23 | 24 | /* 25 | 考点: 可变函数 26 | 通过可变函数操作符..., 切片可以展开,多参数在函数中可以转成切片 27 | */ 28 | func params(nums ...int) { 29 | nums[0] = 1 30 | } 31 | 32 | func main() { 33 | //输出0值 34 | mapIssue() 35 | //通过可变函数来修改切片元素值 36 | i := []int{0,2,3} 37 | params(i...) 38 | fmt.Println(i) 39 | } 40 | -------------------------------------------------------------------------------- /面试/11-anonymous-combination/anonymous-combination.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | 考点:匿名组合, 7 | 外部类型可以引用内部类型的属性和方法 8 | 外部类型可以定义自己的属性和方法,如果同内部类型相同,则覆盖内部 9 | */ 10 | 11 | type People struct{} 12 | 13 | func (p *People) ShowA() { 14 | fmt.Println("showA") 15 | p.ShowB() 16 | } 17 | func (p *People) ShowB() { 18 | fmt.Println("showB") 19 | } 20 | 21 | type Teacher struct { 22 | People 23 | } 24 | 25 | func (t *Teacher) ShowB() { 26 | fmt.Println("teacher showB") 27 | } 28 | 29 | func main() { 30 | t := Teacher{} 31 | t.ShowA() 32 | } 33 | -------------------------------------------------------------------------------- /面试/12-nil-blank-slice-and-interface-polymorphic/nil-blank-slice-and-interface-polymorphic.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | 考点:nil切片和空切片 7 | */ 8 | func nilIssue() { 9 | //切片是引用类型, 声明指针,定义的是一个nil,没有具体指向值 10 | var i []int 11 | 12 | //i[0] = 1, 无法直接赋值 13 | 14 | //空切片, 空切片和 nil 不相等,表示一个空的集合 15 | var j = []int{} 16 | if j == nil { 17 | fmt.Println("空切片") 18 | } 19 | 20 | if i == nil { 21 | fmt.Println("nil") 22 | } 23 | } 24 | 25 | /* 26 | 考点:一个类型实现多个接口, 向上引用赋值给接口变量 27 | */ 28 | 29 | type A interface { 30 | ShowA() int 31 | } 32 | 33 | type B interface { 34 | ShowB() int 35 | } 36 | 37 | type Work struct { 38 | i int 39 | } 40 | 41 | func (w *Work) ShowA() int { 42 | return w.i + 10 43 | } 44 | 45 | func (w *Work) ShowB() int { 46 | return w.i + 20 47 | } 48 | 49 | func main() { 50 | nilIssue() 51 | w := &Work{5} 52 | var i A = w 53 | var j B = w 54 | fmt.Println(i.ShowA(), j.ShowB()) 55 | } 56 | -------------------------------------------------------------------------------- /面试/13-declare-point-variable/declare-point-variable.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | 考点: 关于引用类型的变量声明和赋值问题 7 | 1 使用var m map[string]int, 这种只声明了变量,没有分配内存空间,所以不能进行赋值 8 | 2 使用make或字面量来初始化map 9 | */ 10 | 11 | func main() { 12 | //错误示范 13 | //var i map[string]int 14 | //i["lee"] = 1 15 | //fmt.Println(i) 16 | 17 | // 正确初始化方法 18 | m := make(map[string]int) 19 | m["lee"] = 1 20 | 21 | if v, ok := m["lee"]; ok { 22 | fmt.Println(v) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /面试/14-defer-closure-point/defer-closure-point.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | 考点:defer 闭包 指针变量 7 | */ 8 | 9 | type Person struct { 10 | age int 11 | } 12 | 13 | func main() { 14 | //p是一个指针变量 15 | p := &Person{25} 16 | 17 | //此处的defer中p将当前age 25作为参数,缓存到栈中 18 | defer fmt.Println(p.age) 19 | 20 | //此处将p的引用地址,age最终被重新赋值 21 | defer func(p *Person) { 22 | fmt.Println(p.age) 23 | }(p) 24 | 25 | //闭包 最终引用的是外部变量 26 | defer func() { 27 | fmt.Println(p.age) 28 | }() 29 | 30 | p.age = 27 31 | fmt.Println(p) 32 | } 33 | -------------------------------------------------------------------------------- /面试/15-slice-delete-elem/slice-delete-elem.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | /* 9 | slice删除元素 10 | a = append(a[:i], a[i+1:]...) 11 | // or 12 | a = a[:i+copy(a[i:], a[i+1:])] 13 | */ 14 | 15 | func main() { 16 | s := []string{"a", "b", "c", "d"} 17 | begin := time.Now() 18 | _ = append(s[:1], s[2:]...) 19 | end := time.Now() 20 | fmt.Println(s) 21 | fmt.Println(end.UnixNano() - begin.UnixNano()) //0 22 | m := []string{"a", "b", "c", "d"} 23 | begin = time.Now() 24 | //开辟新的内存存放切片,防止更改问题 25 | var s2 []string 26 | for _, v := range m { 27 | if v != "b" { 28 | s2 = append(s2, v) 29 | } 30 | } 31 | end = time.Now() 32 | fmt.Println(end.UnixNano() - begin.UnixNano()) //1000~ 7000 33 | } 34 | -------------------------------------------------------------------------------- /面试/16-Ttype-and-pointT/Ttype-and-pointT.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | 考点: 7 | 基于类型定义的方法必须在同一个包内 8 | 错误示范 9 | func (i int) PrintInt() { 10 | fmt.Println(i) 11 | } 12 | */ 13 | 14 | type Mint int 15 | func (i Mint) PrintInt() { 16 | fmt.Println(i) 17 | } 18 | 19 | /* 20 | 考点:接口的*T和T的方法集 21 | *T类型的方法,只有*T可以接收 22 | T类型的方法,两者皆可接收 23 | */ 24 | type Person interface { 25 | Speak(string) string 26 | } 27 | 28 | type Student struct {} 29 | 30 | func (s Student) Speak(think string) (talk string) { 31 | talk = think 32 | return 33 | } 34 | 35 | func main() { 36 | var i Mint = 1 37 | i.PrintInt() 38 | 39 | var p Person = &Student{} 40 | think := "hi" 41 | p.Speak(think) 42 | } 43 | -------------------------------------------------------------------------------- /面试/17-iota-and-String-method/iota-and-String-method.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | 考点:iota用法和String()方法 7 | 类型定义String() 方法时候,fmt.Printf()、fmt.Print() 和 fmt.Println() 会自动使用 String() 方法 8 | */ 9 | 10 | type Direct int 11 | 12 | const ( 13 | East Direct = iota 14 | South 15 | West 16 | North 17 | ) 18 | 19 | func (d Direct) String() string { 20 | return [...]string{"East", "South", "West", "North"}[d] 21 | } 22 | 23 | /* 24 | 考点: 25 | map中的value本身不可以寻址 m["foo"].x = 1这种写法错误 26 | */ 27 | 28 | type Math struct { 29 | x, y int 30 | } 31 | //需要借助临时变量 32 | var m = map[string]Math{ 33 | "foo": Math{2, 3}, 34 | } 35 | //地址方法 36 | var n = map[string]*Math{"foo": &Math{1,2}} 37 | 38 | func main() { 39 | fmt.Println(South) 40 | //借助临时变量 41 | temp := m["foo"] 42 | temp.x = 3 43 | m["foo"] =temp 44 | //value为指针 45 | n["foo"].x = 2 46 | } 47 | -------------------------------------------------------------------------------- /面试/18-gorouttine-under-for-range/gorouttine-under-for-range.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | "reflect" 7 | ) 8 | 9 | func main() { 10 | //数组 11 | var m = [...]int{1,2,3} 12 | fmt.Println(m) 13 | fmt.Println(reflect.TypeOf(m)) 14 | //变量 i、v 是具体元素的副本,在每次循环体中都会被重用, 而不是重新被创建 15 | get(m) 16 | for i, v := range m { 17 | //内部的goroutine 此处可以理解为闭包 18 | go func() { 19 | fmt.Println(i, v) 20 | }() 21 | } 22 | 23 | time.Sleep(time.Second * 3) 24 | } 25 | 26 | func get(a interface{}) { 27 | fmt.Println(a) 28 | } 29 | /* 30 | 1。使用函数传递 31 | for i, v := range m { 32 | go func(i,v int) { 33 | fmt.Println(i, v) 34 | }(i,v) 35 | } 36 | 2。重新声明变量 37 | for i, v := range m { 38 | i := i // 这里的 := 会重新声明变量,而不是重用 39 | v := v 40 | go func() { 41 | fmt.Println(i, v) 42 | }() 43 | } 44 | */ -------------------------------------------------------------------------------- /面试/19-defer-recover-anonymous-func/defer-recover-anonymous-func.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | n := f(3) 7 | fmt.Println(n) 8 | } 9 | 10 | func f(n int) (r int) { 11 | defer func() { 12 | //此处闭包, n值为参数值 13 | r += n 14 | recover() 15 | }() 16 | 17 | var f func() 18 | //引发panic 19 | defer f() 20 | 21 | f = func() { 22 | r += 2 23 | } 24 | return n + 1 25 | } -------------------------------------------------------------------------------- /面试/20-append-slice-issue/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | /* 5 | append slice issue: 扩容的时候重新分配底层数组 6 | 不扩容的时用的是原数组 7 | */ 8 | func main() { 9 | slice := make([]int, 5, 5) 10 | //扩容 11 | change(slice...) 12 | fmt.Println(slice) 13 | //不扩容 14 | change(slice[0:2]...) 15 | fmt.Println(slice) 16 | } 17 | 18 | func change(s ...int) { 19 | s = append(s, 3) 20 | } -------------------------------------------------------------------------------- /面试/21-struct-slice/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type Foo struct { 6 | Bar string 7 | } 8 | 9 | func main() { 10 | s := []Foo{{"a"}, {"b"}, {"c"}} 11 | s1 := make([]*Foo, len(s)) 12 | 13 | for i, value := range s { 14 | s1[i] = &value 15 | } 16 | fmt.Println(s) 17 | fmt.Println(s1[1]) //[0xc000086030 0xc000086030 0xc000086030] c的地址 18 | 19 | //map的无序性 20 | var m = map[string]int{ 21 | "A": 21, 22 | "B": 22, 23 | "C": 23, 24 | } 25 | counter := 0 26 | for k, v := range m { 27 | if counter == 0 { 28 | delete(m, "A") 29 | } 30 | counter++ 31 | fmt.Println(k, v) 32 | } 33 | fmt.Println("counter is ", counter) 34 | } 35 | -------------------------------------------------------------------------------- /面试/22-learn-map-with-test/dictionary.go: -------------------------------------------------------------------------------- 1 | package dictionary 2 | 3 | import "errors" 4 | 5 | type Dictionary map[string]string 6 | 7 | var ErrNotFound = errors.New("could not find the word you were looking for") 8 | 9 | func (d Dictionary) Search(word string) (string, error){ 10 | dict, ok := d[word] 11 | if !ok { 12 | return "", ErrNotFound 13 | } 14 | return dict, nil 15 | } 16 | -------------------------------------------------------------------------------- /面试/22-learn-map-with-test/dictionary_test.go: -------------------------------------------------------------------------------- 1 | package dictionary 2 | 3 | import "testing" 4 | 5 | func TestSearch(t *testing.T) { 6 | dict := Dictionary{"test": "this is a test"} 7 | //got := dict.Search("test") 8 | //want := "this is a test" 9 | // 10 | //assertStrings(t, got, want) 11 | t.Run("known word", func(t *testing.T) { 12 | got, _ := dict.Search("test") 13 | want := "this is a test" 14 | assertStrings(t, got, want) 15 | }) 16 | 17 | t.Run("unknown word", func(t *testing.T) { 18 | _, got := dict.Search("unknown") 19 | assertErrors(t, got, ErrNotFound) 20 | }) 21 | } 22 | 23 | func assertErrors(t *testing.T, got, want error) { 24 | t.Helper() 25 | 26 | if got != want { 27 | t.Errorf("got '%s' want '%s'", got, want) 28 | } 29 | } 30 | 31 | func assertStrings(t *testing.T, got, want string) { 32 | t.Helper() 33 | 34 | if got != want { 35 | t.Errorf("got '%s' want '%s'", got, want) 36 | } 37 | } -------------------------------------------------------------------------------- /面试/23-alias-name/type-struct-aliase.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | 定义类型别名, 等价与原类型,类型别名与原类型拥有相同的方法 7 | */ 8 | type User struct {} 9 | //新的类型 10 | type User1 User 11 | //别名 12 | type User2 = User 13 | 14 | func (u User1) m1() { 15 | fmt.Println("m1") 16 | } 17 | 18 | func (u User) m2() { 19 | fmt.Println("m2") 20 | } 21 | func main() { 22 | var u1 User1 23 | var u2 User2 24 | u1.m1() 25 | u2.m2() 26 | } 27 | -------------------------------------------------------------------------------- /面试/24-point/point.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | 考点: 指针 7 | */ 8 | func incre(p *int) int { 9 | *p++ 10 | return *p 11 | } 12 | func main() { 13 | v := 1 14 | //传递引用地址 15 | incre(&v) 16 | fmt.Println(v) 17 | } 18 | -------------------------------------------------------------------------------- /面试/25-interface-nil-issue/interface-concrete-issue.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | interface内部结构包含静态类型动态类型以及动态值 7 | 当且仅当动态值和动态类型为nil,接口类型值才为nil 8 | 例子:var x *int = nil(动态类型为*int,值为nil) 9 | */ 10 | 11 | func Foo(x interface{}) { 12 | if x == nil { 13 | fmt.Println("empty interface") 14 | return 15 | } 16 | fmt.Println("non empty interface") 17 | } 18 | func main() { 19 | var x *int = nil 20 | //输出non empty 21 | Foo(x) 22 | } 23 | -------------------------------------------------------------------------------- /面试/26-goroutine-channel-demo/goroutine-channel.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | /* 9 | 协程和channel关闭的demo 10 | */ 11 | func main() { 12 | ch := make(chan int, 20) 13 | //A 14 | go func() { 15 | for i := 0; i < 10; i++{ 16 | ch <- i 17 | } 18 | //close(ch) 19 | }() 20 | //B 21 | go func() { 22 | for { 23 | a, ok := <-ch 24 | if !ok { 25 | fmt.Println("close") 26 | return 27 | } 28 | fmt.Println("a:", a) 29 | } 30 | }() 31 | defer close(ch) 32 | fmt.Println("ok") 33 | time.Sleep(time.Second * 5) 34 | } 35 | -------------------------------------------------------------------------------- /面试/27-string-method-issue/sturct-achieve-string-method.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | 类型实现String方法,当格式化输出时会自动使用String方法 7 | 如果在String方法中使用格式化输出,会导致递归调用,最终抛出错误 8 | */ 9 | 10 | type ConfigOne struct { 11 | Daemon string 12 | } 13 | 14 | func (c *ConfigOne) String() string { 15 | return c.Daemon 16 | } 17 | 18 | func main() { 19 | c := &ConfigOne{"test"} 20 | fmt.Println(c) 21 | } 22 | -------------------------------------------------------------------------------- /面试/29-delete-elem-in-slice/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | slice删除元素的坑 7 | copy复制会比等号复制慢。但是copy复制为值复制,改变原切片的值不会影响新切片。 8 | 而等号复制为指针复制,改变原切片或新切片都会对另一个产生影响。 9 | */ 10 | func main() { 11 | nums := []int{1,2,3,4} 12 | k := 2 13 | //res := append(nums[:k], nums[k+1:]...) 14 | //fmt.Println(res) // [1 2 4] 15 | //fmt.Println(nums) // [1 2 4 4] 16 | 17 | //正确处理方式 18 | temp := make([]int, len(nums[:k])) 19 | copy(temp, nums[:k]) 20 | temp = append(temp, nums[k+1:]...) 21 | fmt.Println(temp) 22 | fmt.Println(nums) 23 | } 24 | -------------------------------------------------------------------------------- /面试/30-select-single-channel/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 考点 6 | 注意map需要初始化才能使用 7 | 指针不支持索引 8 | */ 9 | //定义map类型 10 | type Param map[string]interface{} 11 | //定义结构体,属性为Param指针。 12 | type Show struct { 13 | *Param 14 | } 15 | 16 | func main() { 17 | s := new(Show) 18 | //初始化map 19 | p := make(Param) 20 | p["day"] = "21" 21 | s.Param = &p 22 | //指针不支持索引,需取值 23 | tmp := *s.Param 24 | fmt.Println(tmp["day"]) 25 | } 26 | 27 | /* 28 | channel: 29 | 单项channel不可关闭 30 | 31 | func Stop(stop <-chan bool) { 32 | close(stop) //错误示类 33 | } 34 | */ 35 | 36 | /* 37 | select机制 38 | * select机制用来处理异步IO问题 39 | * 每个case语句必须示一个IO操作 40 | * golang在语言级别上支持select关键字 41 | */ 42 | -------------------------------------------------------------------------------- /面试/31-interface-and-nil/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | 类型断言语法: i.(Type) 7 | 编译时会自动检测 i 的动态类型与 Type 是否一致 8 | */ 9 | func main() { 10 | x := interface{}(nil) 11 | fmt.Println("x:", x) 12 | 13 | y := (*int)(nil) 14 | fmt.Println(y) 15 | 16 | a := y == x 17 | b := y == nil 18 | _, c := x.(interface{}) 19 | fmt.Println(a, b, c) 20 | 21 | var m interface{} 22 | fmt.Println(m) 23 | } 24 | -------------------------------------------------------------------------------- /面试/32-nil-and-map-issue/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | ) 7 | 8 | /* 9 | 知识点: 10 | 1. cap函数适用于数组,数组指针,slice和channel, 不适用与map 11 | 2. nil用于表示interface、函数、map、slice、 channel的零值, 不指定变量类型的时候,编译报错 12 | */ 13 | func main() { 14 | // make 给map分配内存时,可以指定第二个参数,不过编译时会被忽略 15 | m := make(map[string]int, 2) 16 | fmt.Println(len(m)) 17 | 18 | //nil值需要指定变量类型 19 | var x interface{} = nil 20 | fmt.Println(x == nil) 21 | 22 | //不能使用短变量声明设置结构体字段值 23 | var data info 24 | var err error 25 | data.result, err = work() 26 | fmt.Printf("info: %+v\n", data) 27 | fmt.Println(err) 28 | } 29 | type info struct { 30 | result int 31 | } 32 | 33 | func work() (int, error){ 34 | return 2, errors.New("这是测试") 35 | } 36 | -------------------------------------------------------------------------------- /面试/33-const-issue/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | 常量在程序运行时,不会被修改,常量未使用是能编译通过的 7 | */ 8 | 9 | const ( 10 | x uint16 = 120 11 | y // 常量未赋值,跟上面值一样 12 | s = "abc" 13 | z 14 | ) 15 | func main() { 16 | const a = 123 17 | //量未使用是能编译通过的 18 | const b = 1.23 19 | fmt.Println(a) 20 | 21 | /* 22 | uint16 120 23 | string abc 24 | */ 25 | fmt.Printf("%T %v\n", y, y) 26 | fmt.Printf("%T %v\n", z, z) 27 | } 28 | -------------------------------------------------------------------------------- /面试/34-variable-issue/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | 变量简短声明符号:= 7 | 1. 作用域中, 导致变量隐藏问题 8 | 2. 左边赋值多个变量时,只需保证一个变量是新声明的即可 9 | */ 10 | func main() { 11 | x := 1 12 | fmt.Println(x) 13 | //x变量隐藏 14 | { 15 | fmt.Println(x) 16 | i, x := 2, 2 17 | fmt.Println(i, x) 18 | } 19 | fmt.Println(x) 20 | } 21 | -------------------------------------------------------------------------------- /面试/35-struct-assign-issue/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | 结构体字段不可以用简短符号赋值 7 | */ 8 | type foo struct { 9 | bar int 10 | } 11 | 12 | func main() { 13 | var f foo 14 | f.bar = 1 15 | fmt.Println(f) 16 | 17 | m := new(foo) 18 | m.bar = 1 19 | fmt.Println(m.bar) 20 | 21 | BitRever() 22 | } 23 | 24 | /* 25 | 有符号的整数来说,是按照补码进行取反操作的(快速计算方法:对数a取反,结果为 -(a+1) ) 26 | 27 | 左移右移: 通过原码操作的 28 | 位运算符: 使用的是补码 29 | */ 30 | 31 | func BitRever() { 32 | //00000011 33 | //11111100 34 | //11111101 35 | var a int8 = -3 36 | //00000010 37 | fmt.Println(^a) // => 2 38 | } 39 | -------------------------------------------------------------------------------- /面试/36-bit-operate-issue/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | 按位置零操作符: &^ 7 | z = x &^ y 表示如果y中的bit为1,则z对应的bit为0,否则z对应的bit等于x中的bit位的值 8 | z = x | y 或操作符可以理解为y的bit为1,则z也为1, 否则z与x的bit位相同 9 | */ 10 | func main() { 11 | var a int8 = 3 12 | var b int8 = 5 //00001001 13 | z := a &^ b 14 | fmt.Printf("z: %08b\n", z) 15 | conversePosition() 16 | } 17 | 18 | /* 19 | 按位取反之后返回一个每个 bit 位都取反的数, 20 | 对于有符号的整数来说,是按照补码进行取反操作的(快速计算方法:对数 a 取反,结果为 -(a+1) ), 21 | 对于无符号整数来说就是按位取反 22 | 23 | 作为二元运算符,^ 表示按位异或,即:对应位相同为 0,相异为 1 24 | */ 25 | 26 | func conversePosition() { 27 | //0000 0011 28 | //1111 1100 29 | //1111 1101 30 | var a int8 = -3 31 | //0000 0011 32 | //0000 0011 33 | //0000 0011 34 | var x int8 = 3 35 | 36 | b := x^a //11111110 => 11111101 => 0000 0010 37 | fmt.Printf("%08b\n", a) 38 | fmt.Println(b) 39 | } 40 | -------------------------------------------------------------------------------- /面试/37-const-and-string-issue/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | 常量考点 7 | 1. 常量在程序运行时不会被修改的量,未使用也可以编译通过 8 | 2. 常量组中如不指定类型和初始化值,则与上一行非空常量右值相同 9 | 10 | string考点 11 | string不能分配nil, 若空值使用"" 12 | */ 13 | 14 | const ( 15 | x uint16 = 120 16 | y 17 | s string = "abc" 18 | z 19 | ) 20 | func main() { 21 | const a = 123 22 | const b = 1.23 23 | fmt.Println(a) 24 | 25 | fmt.Printf("%T %v\n", y, y) 26 | } 27 | 28 | -------------------------------------------------------------------------------- /面试/38-variable-hidden-issue/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | 知识点:变量隐藏 7 | 1. 变量使用简短号:=时, 左边出现多个变量,只需保证至少有一个变量是新声明的。 8 | 2. 若出现作用域,会导致变量隐藏的问题 9 | 10 | */ 11 | 12 | func main() { 13 | x := 1 14 | //变量隐藏 15 | { 16 | fmt.Println(x) 17 | i, x := 2, 2 18 | fmt.Println(i, x) 19 | } 20 | fmt.Println(x) 21 | } 22 | -------------------------------------------------------------------------------- /面试/39-channel-and-json-issue/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | ) 7 | 8 | /* 9 | 1.channel为nil,读写都会阻塞 10 | 2.结构体访问控制,结构体中的属性大写,外部才能访问 11 | */ 12 | 13 | func main() { 14 | chanIssue() 15 | jsonToStruct() 16 | } 17 | 18 | func chanIssue() { 19 | //未分配内存,ch为nil 20 | var ch chan int 21 | select { 22 | case v, ok := <-ch: 23 | println(v, ok) 24 | default: 25 | println("default") 26 | } 27 | } 28 | 29 | type People struct { 30 | Name string `json: "name"` 31 | } 32 | 33 | func jsonToStruct() { 34 | js := `{ 35 | "name": "seekload" 36 | }` 37 | 38 | var p People 39 | err := json.Unmarshal([]byte(js), &p) 40 | if err != nil { 41 | fmt.Println("err:", err) 42 | return 43 | } 44 | fmt.Println(p) 45 | } 46 | -------------------------------------------------------------------------------- /面试/40-three-colon-syntax/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | ...语法: 7 | 1. 用于函数多个不定参数的情况 8 | 2. 将slice打散进入传递 9 | */ 10 | 11 | func main() { 12 | var strs = []string{ 13 | "test1", 14 | "test2", 15 | "test3", 16 | } 17 | importSlice(strs...) 18 | } 19 | 20 | func importSlice(args ...string) { 21 | for _, v := range args { 22 | fmt.Println(v) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /面试/41-func-parameter-issue/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | 考点: 7 | 结构体属性为引用类型时, 函数参数为结构体值传递,更改属性的时候,引用类型值变了会改变最终值 8 | */ 9 | 10 | type T struct { 11 | ls []int 12 | } 13 | 14 | type V struct { 15 | age int 16 | } 17 | //结构体值为切片 18 | func fo(t T) { 19 | t.ls[0] = 100 20 | } 21 | //结构体属性为普通 22 | func vo(v *V) { 23 | v.age = 20 24 | } 25 | func main() { 26 | t := new(T) 27 | t.ls = []int{1,2,3} 28 | fo(*t) 29 | fmt.Println(t.ls[0]) 30 | 31 | v := new(V) 32 | v.age = 10 33 | vo(v) 34 | fmt.Println(v.age) 35 | } 36 | -------------------------------------------------------------------------------- /面试/42-func-compare-with-nil/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | 考察点: 7 | func只能跟nil作比较 8 | */ 9 | func funcDemo() { 10 | var fn1 = func() {} 11 | var fn2 func() 12 | if fn1 != nil { 13 | fmt.Println("fn1 is not nil") 14 | } 15 | if fn2 == nil { 16 | fmt.Println("fn2 is nil") 17 | } 18 | } 19 | 20 | /* 21 | 考察点: 22 | 关于map值为结构体(map[key]struct) 23 | 需要初始化结构体,再赋值,否则struct是不可寻址的 24 | */ 25 | type T struct { 26 | n int 27 | } 28 | func mapStruct() { 29 | m := make(map[int]T) 30 | 31 | //初始化struct 32 | t := T{1} 33 | m[0] = t 34 | fmt.Println(m[0].n) 35 | } 36 | 37 | func main() { 38 | funcDemo() 39 | mapStruct() 40 | } 41 | -------------------------------------------------------------------------------- /面试/43-about-nil-struct-call-func/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | struct方法中,指针类型的接收者必须是合法指针(包括 nil),或能获取实例地址 7 | */ 8 | type X struct { 9 | 10 | } 11 | 12 | func (x *X) callmethod() { 13 | fmt.Println("test") 14 | } 15 | 16 | func main() { 17 | //nil是合法的调用 18 | var x *X 19 | x.callmethod() 20 | //cannot take the address of X literal, X{}是不可寻址的 21 | //X{}.callmethod() 22 | // 正确处理 23 | a := X{} 24 | a.callmethod() 25 | 26 | findItemInMap() 27 | 28 | //通过函数创建T 29 | //GetT().n = 1 无法寻址 30 | t := GetT() 31 | t.n = 1 //或 p := &(t.n) *p = 1 32 | fmt.Println(t) 33 | } 34 | 35 | func findItemInMap() { 36 | x := map[string]string{"one":"a","two":"","three":"c"} 37 | v := x["one"] 38 | fmt.Println(v) 39 | //检查map是否存在值,使用map返回的第二个参数 40 | if _, ok := x["once"]; !ok { 41 | fmt.Println("no once") 42 | } 43 | } 44 | 45 | type T struct { 46 | n int 47 | } 48 | 49 | func GetT() T { 50 | return T{} 51 | } -------------------------------------------------------------------------------- /面试/44-point-address-issue/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | 指针和地址转换的练习 7 | */ 8 | 9 | type T struct { 10 | x int 11 | y *int 12 | } 13 | 14 | func main() { 15 | i := 20 16 | t := T{10, &i} 17 | 18 | //p为x的地址 19 | p := &t.x 20 | 21 | //对p取值后操纵++ -- 22 | *p++ 23 | *p-- 24 | 25 | //更换结构体t中y的值 26 | t.y = p 27 | fmt.Println(*t.y) 28 | 29 | sliceIssue() 30 | } 31 | 32 | /* 33 | 切片的截取运算 34 | [i:j] 默认j的取值 j < 原切片的cap, 当j缺省时,默认是原数组的长度 35 | */ 36 | func sliceIssue() { 37 | x := make([]int, 2, 10) 38 | _ = x[6:10] 39 | //_ = x[6:] panic: runtime error: slice bounds out of rang 40 | } -------------------------------------------------------------------------------- /面试/45-point-receiver/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | 知识点: 7 | 当目标方法的接受者为指针类型时,被复制的是指针地址 8 | */ 9 | 10 | type N int 11 | 12 | func (n *N) test() { 13 | fmt.Println(*n) 14 | } 15 | func main() { 16 | var n N = 10 17 | p := &n 18 | 19 | n++ 20 | f1 := n.test 21 | 22 | n++ 23 | f2 := p.test 24 | 25 | n++ 26 | fmt.Println(n) 27 | f1() //13 28 | f2() //13 29 | //声明s切片,未初始化,值为nil,不能直接使用下标赋值 30 | var s []int 31 | fmt.Println(s) 32 | } 33 | -------------------------------------------------------------------------------- /面试/47-multi-equal-issue/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | 多重赋值的顺序 7 | 1. 先计算等号左边的索引表达式和取址表达式, 接着计算等号右边的表达式 8 | 2. 赋值 9 | */ 10 | 11 | func assignIssue() { 12 | var k = 1 13 | var s = []int{1, 2} 14 | k, s[k] = 0, 3 15 | fmt.Println(s[1]) 16 | } 17 | 18 | func main() { 19 | assignIssue() 20 | //s := []int{1,2,3} 21 | var k int = 9 22 | //range空切片不会遍历 23 | for k = range []int{} { 24 | fmt.Println(k+1) 25 | } 26 | //range nil指针数组 27 | fmt.Println((*[3]int)(nil)) 28 | 29 | for k = range (*[3]int)(nil) { 30 | fmt.Println(k) //输出0 1 2 31 | } 32 | fmt.Println(k) //输出为2 33 | 34 | //for循环 35 | for k = 0; k < 3; k++ { 36 | 37 | } 38 | fmt.Println(k) //输出为3 39 | } 40 | -------------------------------------------------------------------------------- /面试/48-overflow-issue/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | int8 取值范围 -128~127 7 | */ 8 | 9 | func main() { 10 | /* 11 | var x int8 = 128 // constant 128 overflows int8 12 | y := x/-1 13 | fmt.Println(y) 14 | */ 15 | } 16 | 17 | /* 18 | go 预定义的nil可以被覆盖 19 | */ 20 | 21 | func overNil() { 22 | nil := 123 23 | fmt.Println(nil) 24 | //var _ map[string]int = nil 这里nil被覆盖为int类型, 不能赋值给map 25 | } 26 | -------------------------------------------------------------------------------- /面试/49-valueOfmap-is-struct/map-init-and-use.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func mapInitUseDemo() { 6 | // 先声明map 7 | var m1 map[string]string 8 | // 再使用make函数创建一个非nil的map,nil map不能赋值 9 | m1 = make(map[string]string) 10 | // 最后给已声明的map赋值 11 | m1["a"] = "aa" 12 | m1["b"] = "bb" 13 | 14 | // 直接创建 15 | m2 := make(map[string]string) 16 | // 然后赋值 17 | m2["a"] = "aa" 18 | m2["b"] = "bb" 19 | 20 | // 初始化 + 赋值一体化 21 | m3 := map[string]string{ 22 | "a": "aa", 23 | "b": "bb", 24 | } 25 | 26 | // ========================================== 27 | // 查找键值是否存在 28 | if v, ok := m1["a"]; ok { 29 | fmt.Println(v) 30 | } else { 31 | fmt.Println("Key Not Found") 32 | } 33 | 34 | // 遍历map 35 | for k, v := range m3 { 36 | fmt.Println(k, v) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /面试/49-valueOfmap-is-struct/map-value-struct-issue.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type People struct { 6 | Name string 7 | } 8 | 9 | //map的value是struct, 注意不可寻址的问题 10 | //解决1: 结构体使用指针, 解决2:赋值给另一个变量temp, 修改temp.Name, 再将temp赋值给map[key] 11 | func main() { 12 | m := map[string]People{"key": {Name: "lee"}} 13 | //不可以使用m["key"].Name = "another"来赋值, 14 | temp := m["key"] 15 | temp.Name = "anne" 16 | m["key"] = temp 17 | fmt.Println(m["key"]) 18 | 19 | //或者 20 | n := map[string]*People{"key": &People{Name: "lee"}} 21 | n["key"].Name = "llll" 22 | fmt.Println(n["key"]) 23 | } 24 | -------------------------------------------------------------------------------- /面试/append-slice-issue.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | /* 6 | 函数传参为切片,通过append对slice追加元素,不改变原来值的变化 7 | 解决办法: 1. 通过返回值的方式处理 8 | 2. 通过传递指针的方式处理 9 | */ 10 | func appendSlice() { 11 | s := make([]int, 3, 4) 12 | change(s) 13 | fmt.Println(s) // [0, 0, 0] 14 | } 15 | 16 | func change(s []int) { 17 | s = append(s, 5) //此处没有扩容地址还是main中s的地址 18 | fmt.Println(s) //内部值为[0 0 0 5], 不改变main中的输出值 19 | s[0] = 1 // 未扩容的情况下,通过下标更改,外边值变为[1 0 0] 20 | s = append(s, 6) //此处扩容,地址改变 21 | s[1] = 2 // 不改变外部的值[1 0 0] 22 | fmt.Println(s) // [1, 2, 0, 5, 6] 23 | } 24 | 25 | //通过传递指针解决append slice issue 26 | func usePoint(s *[]int) { 27 | *s = append(*s, 5) 28 | *s = append(*s, 6) 29 | fmt.Println(s) //[0 0 0 5 6] 外部的值也为这个 30 | } 31 | --------------------------------------------------------------------------------