├── .gitignore ├── document ├── grpc ├── Concurrent Skiplist Based.pdf ├── mysql ├── go_module使用 ├── go优秀文章链接 ├── protobuffer使用文档 └── linux下安装go11 ├── serialize ├── person.txt ├── person.proto └── serialize_study_test.go ├── algorithm ├── top_k.txt ├── back_flash_test.go ├── b_tree_test.go ├── tree_test.go ├── bloom_filter_test.go ├── linkstack_test.go ├── bitmap_test.go ├── array_queue_test.go ├── load_balance_test.go ├── tire_test.go ├── funnel_rate_limiter_test.go ├── token_bucket_test.go ├── disk_merge_sort_test.go ├── skip_list_test.go ├── avltree1_test.go ├── int_heap_test.go ├── array_lru_test.go ├── hashmap_test.go ├── top_k_test.go ├── count_limiter_test.go ├── arraystack_test.go ├── array_queue.go ├── linkqueue_test.go ├── linklist_test.go ├── b_tree.go ├── linkqueue.go ├── linkstack.go ├── int_heap.go ├── array_lru.go ├── load_balance.go ├── tree.go ├── 时间空间复杂度笔记 ├── binarysearchtree_test.go ├── back_flash.go ├── bloom_filter.go ├── funnel_rate_limiter.go ├── avltree2_test.go ├── count_limiter.go ├── tire.go ├── bitmap.go ├── sort_test.go ├── token_bucket.go ├── one_link_list_test.go ├── ahocorasick_test.go ├── hashmap.go ├── arraystack.go ├── 树笔记 ├── ahocorasick.go ├── bfs.go └── avltree1.go ├── goframe └── frame_introduction.go ├── grpc └── helloworld_demo │ ├── register_center │ ├── config │ ├── register.go │ └── etcd_register.go │ ├── server │ ├── hello_world_server_test.go │ ├── hello_world_server_tls_test.go │ ├── hello_world_server_token_test.go │ ├── hello_world_server_register_test.go │ ├── hello_world_server_intercept_test.go │ ├── hello_world_server.go │ ├── hello_world_server_tls.go │ ├── hello_world_server_register.go │ ├── hello_world_server_token.go │ └── hello_world_server_intercept.go │ ├── client │ ├── hello_world_client_tls_test.go │ ├── hello_world_client_token_test.go │ ├── hello_world_client_register_test.go │ ├── hello_world_client_intercept_test.go │ ├── hello_world_client_test.go │ ├── hello_world_client_intercept.go │ ├── hello_world_client.go │ ├── hello_world_client_tls.go │ ├── hello_world_client_token.go │ └── hello_world_client_register.go │ ├── proto │ └── hello_world.proto │ └── impl │ └── hello_service_impl.go ├── protobuffer ├── test.txt ├── test.pb_test.go └── test.proto ├── cli ├── cli_study_test.go └── cli_study.go ├── basic ├── map_study_test.go ├── file_study_test.go ├── math_study_test.go ├── slice_study_test.go ├── http_server_test.go ├── net_client_test.go ├── net_server_test.go ├── rand_study_test.go ├── runtime_study_test.go ├── strconv_study_test.go ├── goroutine_study_test.go ├── time_study_test.go ├── websocket │ ├── server_test.go │ ├── client_test.go │ ├── client.go │ └── server.go ├── ast_study_test.go ├── list_study_test.go ├── string_study_test.go ├── atomic_study_test.go ├── scanner_study_test.go ├── fmt_study_test.go ├── unicode_study_test.go ├── gob_study_test.go ├── http_study_test.go ├── buffer_study_test.go ├── point_study_test.go ├── email_test.go ├── atomic_study.go ├── math_study.go ├── unicode_study.go ├── reflection_test.go ├── scanner_study.go ├── pprof_study_test.go ├── hash_test.go ├── net_client.go ├── ast_study.go ├── http_server.go ├── context_study_test.go ├── sync_study_test.go ├── runtime_study.go ├── rand_study.go ├── gob_study.go ├── net_server.go ├── chan_study_test.go ├── defer_recover_test.go ├── convert_test.go ├── point_study.go ├── httptest_study_test.go ├── goroutine_study.go ├── json_study_test.go ├── http_study.go ├── httptest_study.go ├── buffer_study.go ├── map_study.go ├── hash.go ├── sync_study.go ├── time_study.go ├── defer_recover.go ├── strconv_study.go ├── list_study.go ├── context_study.go ├── reflection.go ├── file_study.go ├── slice_study.go ├── email.go ├── string_study.go └── pprof_study.go ├── gnet └── gnet_http_test.go ├── reptile ├── colly_study_test.go └── colly_study.go ├── gleam ├── gleam_study_test.go └── gleam_study.go ├── charts ├── charts_sutdy_test.go └── charts_sutdy.go ├── mysql_binlog ├── binlog_linstener_test.go └── binlog_linstener.go ├── wechat ├── wechat_study_test.go └── wechat_study.go ├── image_watermark └── image_watermark_test.go ├── go_thinking ├── fibonacci_test.go ├── prime_number_test.go ├── fibonacci.go └── prime_number.go ├── boltdb ├── boltdb_study_test.go └── boltdb_study.go ├── hystrix ├── hystrix_study_test.go └── hystrix_study.go ├── gui └── gui_study.go ├── blockchain ├── blockchain_test.go └── blockchain.go ├── benchmark ├── recursion_test.go └── recursion.go ├── gotask ├── gotask_test.go └── gotask.go ├── README.md ├── gout ├── gout_study_test.go └── gout_study.go ├── pipleline └── pipleline_test.go ├── redis └── redis_go_test.go ├── tools ├── http_ sign_in_test.go ├── http_utils_test.go ├── http_ sign_in.go └── http_utils.go ├── array_utils └── array_utils_test.go ├── excel ├── read_and_write_excel_test.go └── read_and_write_excel.go ├── event_bus └── network_event_bus │ ├── network_bus.go │ ├── network_bus_test.go │ └── client.go └── string_utils └── string_utils_test.go /.gitignore: -------------------------------------------------------------------------------- 1 | .git/* 2 | /**/.idea 3 | *.iml 4 | .setting 5 | -------------------------------------------------------------------------------- /document/grpc: -------------------------------------------------------------------------------- 1 | 2 | 3 | ### gRPC基于Golang和Java的简单实现 4 | http://jia-shun.cn/2018/08/12/gRPC/ -------------------------------------------------------------------------------- /serialize/person.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awei0217/go_common/HEAD/serialize/person.txt -------------------------------------------------------------------------------- /algorithm/top_k.txt: -------------------------------------------------------------------------------- 1 | 10,31,22,1,4,1,3,1,2,4 2 | 45,31,13,10,4,1,5,9,0,9 3 | 450,310,13,10,4,1,5,9,56,90 -------------------------------------------------------------------------------- /goframe/frame_introduction.go: -------------------------------------------------------------------------------- 1 | package goframe 2 | 3 | func FrameIntroductionStudy() { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /grpc/helloworld_demo/register_center/config: -------------------------------------------------------------------------------- 1 | etcd: 2 | address: 3 | servicePrefix: 4 | 5 | 6 | -------------------------------------------------------------------------------- /protobuffer/test.txt: -------------------------------------------------------------------------------- 1 | 2 | &小张  111111111  222222222 3 | &小王  333333333  444444444 -------------------------------------------------------------------------------- /cli/cli_study_test.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import "testing" 4 | 5 | func TestCliStudy(t *testing.T) { 6 | CliStudy() 7 | } 8 | -------------------------------------------------------------------------------- /basic/map_study_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import "testing" 4 | 5 | func TestMapStudy(t *testing.T) { 6 | MapStudy() 7 | } 8 | -------------------------------------------------------------------------------- /document/Concurrent Skiplist Based.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awei0217/go_common/HEAD/document/Concurrent Skiplist Based.pdf -------------------------------------------------------------------------------- /gnet/gnet_http_test.go: -------------------------------------------------------------------------------- 1 | package gnet 2 | 3 | import "testing" 4 | 5 | func TestStartHttp(t *testing.T) { 6 | StartHttp() 7 | } 8 | -------------------------------------------------------------------------------- /reptile/colly_study_test.go: -------------------------------------------------------------------------------- 1 | package reptile 2 | 3 | import "testing" 4 | 5 | func TestStart(t *testing.T) { 6 | Start() 7 | } 8 | -------------------------------------------------------------------------------- /basic/file_study_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import "testing" 4 | 5 | func TestFileStudy(t *testing.T) { 6 | FileStudy() 7 | } 8 | -------------------------------------------------------------------------------- /basic/math_study_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import "testing" 4 | 5 | func TestMathStudy(t *testing.T) { 6 | MathStudy() 7 | } 8 | -------------------------------------------------------------------------------- /basic/slice_study_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import "testing" 4 | 5 | func TestSliceStudy(t *testing.T) { 6 | SliceStudy() 7 | } 8 | -------------------------------------------------------------------------------- /gleam/gleam_study_test.go: -------------------------------------------------------------------------------- 1 | package gleam 2 | 3 | import "testing" 4 | 5 | func TestGleamStudy(t *testing.T) { 6 | GleamStudy() 7 | } 8 | -------------------------------------------------------------------------------- /basic/http_server_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import "testing" 4 | 5 | func TestStartHttpServer(t *testing.T) { 6 | StartHttpServer() 7 | } -------------------------------------------------------------------------------- /basic/net_client_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import "testing" 4 | 5 | func TestStartClient(t *testing.T) { 6 | StartClient() 7 | } 8 | -------------------------------------------------------------------------------- /basic/net_server_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import "testing" 4 | 5 | func TestStartServer(t *testing.T) { 6 | StartServer() 7 | } 8 | -------------------------------------------------------------------------------- /basic/rand_study_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestRand(t *testing.T) { 8 | Rand() 9 | } 10 | -------------------------------------------------------------------------------- /basic/runtime_study_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import "testing" 4 | 5 | func TestStudyRuntime(t *testing.T) { 6 | StudyRuntime() 7 | } 8 | -------------------------------------------------------------------------------- /basic/strconv_study_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import "testing" 4 | 5 | func TestStrconvStudy(t *testing.T) { 6 | StrconvStudy() 7 | } 8 | -------------------------------------------------------------------------------- /charts/charts_sutdy_test.go: -------------------------------------------------------------------------------- 1 | package charts 2 | 3 | import "testing" 4 | 5 | func TestBarChartStudy(t *testing.T) { 6 | BarChartStudy() 7 | } 8 | -------------------------------------------------------------------------------- /basic/goroutine_study_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import "testing" 4 | 5 | func TestGoRoutineStudy(t *testing.T) { 6 | GoRoutineStudy() 7 | } 8 | -------------------------------------------------------------------------------- /basic/time_study_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestTimeStudy(t *testing.T) { 8 | TimeStudy() 9 | } 10 | -------------------------------------------------------------------------------- /basic/websocket/server_test.go: -------------------------------------------------------------------------------- 1 | package websocket 2 | 3 | import "testing" 4 | 5 | func TestServerWebSocket(t *testing.T) { 6 | ServerWebSocket() 7 | } 8 | -------------------------------------------------------------------------------- /basic/ast_study_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestAstStudy(t *testing.T) { 8 | AstStudy() 9 | 10 | } 11 | -------------------------------------------------------------------------------- /basic/list_study_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestQueueStudy(t *testing.T) { 8 | QueueStudy() 9 | } 10 | -------------------------------------------------------------------------------- /basic/string_study_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import "testing" 4 | 5 | func TestLetterCombinations(t *testing.T) { 6 | 7 | LetterCombinations("2") 8 | } 9 | -------------------------------------------------------------------------------- /basic/atomic_study_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestAtomicStudy(t *testing.T) { 8 | AtomicStudy() 9 | } 10 | -------------------------------------------------------------------------------- /mysql_binlog/binlog_linstener_test.go: -------------------------------------------------------------------------------- 1 | package mysql_binlog 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestStart(t *testing.T) { 8 | Start() 9 | } 10 | -------------------------------------------------------------------------------- /grpc/helloworld_demo/server/hello_world_server_test.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import "testing" 4 | 5 | func TestStartServer(t *testing.T) { 6 | 7 | StartServer() 8 | } 9 | -------------------------------------------------------------------------------- /basic/scanner_study_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | 8 | func TestScannerStudy(t *testing.T) { 9 | 10 | ScannerStudy() 11 | } 12 | -------------------------------------------------------------------------------- /basic/fmt_study_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | // fmt包学习 8 | 9 | func TestFmtStudy(t *testing.T) { 10 | 11 | FmtStudy() 12 | 13 | } 14 | -------------------------------------------------------------------------------- /basic/websocket/client_test.go: -------------------------------------------------------------------------------- 1 | package websocket 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestSendMessage(t *testing.T) { 8 | 9 | ClientWebSocket() 10 | 11 | } 12 | -------------------------------------------------------------------------------- /grpc/helloworld_demo/server/hello_world_server_tls_test.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import "testing" 4 | 5 | func TestStartServerTLS(t *testing.T) { 6 | 7 | StartServerTLS() 8 | } 9 | -------------------------------------------------------------------------------- /basic/unicode_study_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestIsTitle(t *testing.T) { 9 | 10 | fmt.Println(IsTitle('ᾨ')) 11 | } 12 | -------------------------------------------------------------------------------- /grpc/helloworld_demo/server/hello_world_server_token_test.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import "testing" 4 | 5 | func TestStartServerToken(t *testing.T) { 6 | 7 | StartServerToken() 8 | } 9 | -------------------------------------------------------------------------------- /grpc/helloworld_demo/server/hello_world_server_register_test.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import "testing" 4 | 5 | func TestStartServerRegister(t *testing.T) { 6 | StartServerRegister() 7 | } 8 | -------------------------------------------------------------------------------- /grpc/helloworld_demo/client/hello_world_client_tls_test.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestStartClientTLS(t *testing.T) { 8 | StartClientTLS() 9 | } 10 | -------------------------------------------------------------------------------- /grpc/helloworld_demo/server/hello_world_server_intercept_test.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import "testing" 4 | 5 | func TestStartServerIntercept(t *testing.T) { 6 | 7 | StartServerIntercept() 8 | } 9 | -------------------------------------------------------------------------------- /basic/gob_study_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import "testing" 4 | 5 | func TestEncoderAndDecoder(t *testing.T) { 6 | EncoderAndDecoder(P{ 7 | X: 10, 8 | Y: "spw", 9 | }, Q{}) 10 | } 11 | -------------------------------------------------------------------------------- /basic/http_study_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import "testing" 4 | 5 | func TestHttpGet(t *testing.T) { 6 | HttpGet() 7 | } 8 | 9 | func TestHttpPort(t *testing.T) { 10 | HttpPort() 11 | } 12 | -------------------------------------------------------------------------------- /grpc/helloworld_demo/client/hello_world_client_token_test.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestStartClientToken(t *testing.T) { 8 | StartClientToken() 9 | } 10 | -------------------------------------------------------------------------------- /grpc/helloworld_demo/client/hello_world_client_register_test.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestStartClientRegister(t *testing.T) { 8 | StartClientRegister() 9 | } 10 | -------------------------------------------------------------------------------- /basic/buffer_study_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import "testing" 4 | 5 | func TestBytesStudy(t *testing.T) { 6 | BytesStudy() 7 | } 8 | 9 | func TestBufferStudy(t *testing.T) { 10 | BufferStudy() 11 | } 12 | -------------------------------------------------------------------------------- /grpc/helloworld_demo/client/hello_world_client_intercept_test.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestStartClientIntercept(t *testing.T) { 8 | StartClientIntercept() 9 | } 10 | -------------------------------------------------------------------------------- /algorithm/back_flash_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import "testing" 4 | 5 | func TestCall8Queens(t *testing.T) { 6 | Call8Queens(0) 7 | } 8 | func TestF(t *testing.T) { 9 | F([]int{1, 2, 3, 4, 5, 6}, 0) 10 | } 11 | -------------------------------------------------------------------------------- /basic/point_study_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import "testing" 4 | 5 | func TestPointStudy(t *testing.T) { 6 | PointStudy() 7 | } 8 | 9 | func TestSlicePointStudy(t *testing.T) { 10 | SlicePointStudy() 11 | } 12 | -------------------------------------------------------------------------------- /wechat/wechat_study_test.go: -------------------------------------------------------------------------------- 1 | package wechat 2 | 3 | import ( 4 | "sync" 5 | "testing" 6 | ) 7 | 8 | func TestWeChat(t *testing.T) { 9 | 10 | wg := sync.WaitGroup{} 11 | wg.Add(1) 12 | WeChat() 13 | wg.Wait() 14 | } 15 | -------------------------------------------------------------------------------- /basic/email_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test_SendMail(t *testing.T) { 8 | 9 | SendMail(&Email{"sunpengwei1992@aliyun.com", "golang测试邮件", "朋伟:您好 \n \t这是golang的测试邮件"}) 10 | 11 | } 12 | -------------------------------------------------------------------------------- /image_watermark/image_watermark_test.go: -------------------------------------------------------------------------------- 1 | package image_watermark 2 | 3 | import "testing" 4 | 5 | //给图片加文字水印 6 | 7 | func TestAddImageFont(t *testing.T) { 8 | AddImageFont("E:\\golang_images\\指针1 - 副本.png", "sunpengwei") 9 | } 10 | -------------------------------------------------------------------------------- /basic/atomic_study.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "fmt" 5 | "sync/atomic" 6 | ) 7 | 8 | func AtomicStudy() { 9 | var m int32 = 9 10 | 11 | // 给i 加 2 返回加以后的值 12 | new := atomic.AddInt32(&m, 2) 13 | fmt.Println(new) 14 | 15 | } 16 | -------------------------------------------------------------------------------- /algorithm/b_tree_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestNewBTree(t *testing.T) { 9 | bt := NewBTree(4) 10 | 11 | for i := 1; i < 10; i++ { 12 | bt.Insert(i) 13 | } 14 | fmt.Println(bt) 15 | } 16 | -------------------------------------------------------------------------------- /grpc/helloworld_demo/client/hello_world_client_test.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestStartClient(t *testing.T) { 8 | StartClient() 9 | } 10 | 11 | func BenchmarkStartClient(b *testing.B) { 12 | StartClient() 13 | } 14 | -------------------------------------------------------------------------------- /algorithm/tree_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import "testing" 4 | 5 | func TestMinDepth(t *testing.T) { 6 | left := &TreeNode{1, nil, nil} 7 | right := &TreeNode{3, nil, nil} 8 | root := &TreeNode{2, left, right} 9 | 10 | t.Log(MinDepth(root)) 11 | } 12 | -------------------------------------------------------------------------------- /document/mysql: -------------------------------------------------------------------------------- 1 | 2 | 修改允许任何机器远程登录mysql 3 | mysql -u root -p 4 | use mysql; 5 | update user set host = ''%' where user = 'root'; 6 | flush privileges; 7 | 8 | 9 | 查看binlow是否开启 10 | show VARIABLES like "%log_bin%"; 11 | 查看binlog的格式 12 | show VARIABLES like "%binlog%"; -------------------------------------------------------------------------------- /wechat/wechat_study.go: -------------------------------------------------------------------------------- 1 | package wechat 2 | 3 | import ( 4 | "github.com/qianlnk/gobot" 5 | ) 6 | 7 | func WeChat() { 8 | cfg := gobot.Load() 9 | rebot, err := gobot.NewWecat(cfg) 10 | if err != nil { 11 | panic(err) 12 | } 13 | 14 | rebot.Start() 15 | } 16 | -------------------------------------------------------------------------------- /algorithm/bloom_filter_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestNewBloomFilter(t *testing.T) { 9 | bloomFilter := NewBloomFilter() 10 | bloomFilter.add("123") 11 | fmt.Println(bloomFilter.contains("123")) 12 | } 13 | -------------------------------------------------------------------------------- /basic/math_study.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import "math" 4 | 5 | func MathStudy() { 6 | a, b, c := 2.0, 1.0, 0.0 7 | x, y := a/c, b/c // infinity 8 | n := math.NaN() // not a number 9 | m := math.Sqrt(-1.0) // not a number 10 | println(x == y, m == n) 11 | } 12 | -------------------------------------------------------------------------------- /go_thinking/fibonacci_test.go: -------------------------------------------------------------------------------- 1 | package go_thinking 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestFibonacci(t *testing.T) { 9 | 10 | Fibonacci(10) 11 | 12 | } 13 | 14 | func TestFibonacciNew(t *testing.T) { 15 | fmt.Println(FibonacciNew(10)) 16 | } 17 | -------------------------------------------------------------------------------- /algorithm/linkstack_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import "testing" 4 | 5 | func TestLinkStack_Push(t *testing.T) { 6 | stack := &LinkStack{nil, 0} 7 | 8 | for i := 0; i < 10; i++ { 9 | stack.Push(i) 10 | } 11 | for { 12 | t.Log(stack.Pop()) 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /document/go_module使用: -------------------------------------------------------------------------------- 1 | 2 | #### go mod init module_name 初始化mod文件 3 | #### go mod tidy 下载依赖的包 4 | #### go get github.com/jtianling/goModule@latest 的形式更新到最新版 5 | #### go get -u 的形式升级所有的依赖库 6 | #### go mod edit -require="github.com/chromedp/chromedp@v0.1.0" 修改指定的版本,修改之后执行第二步 7 | 8 | https://goproxy.io -------------------------------------------------------------------------------- /algorithm/bitmap_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import "testing" 4 | 5 | func TestBitSet_Set(t *testing.T) { 6 | bitmap := NewBitMap(4) 7 | bitmap.Set(1) 8 | bitmap.Set(2) 9 | bitmap.Set(64) 10 | t.Log(bitmap.Get(1)) 11 | t.Log(bitmap.Get(2)) 12 | t.Log(bitmap.Get(3)) 13 | } 14 | -------------------------------------------------------------------------------- /algorithm/array_queue_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import "testing" 4 | 5 | func TestArrayLoopQueue_Add(t *testing.T) { 6 | alq := &ArrayLoopQueue{} 7 | for i := 0; i < 20; i++ { 8 | t.Log(alq.Add(i)) 9 | } 10 | for i := 0; i < 20; i++ { 11 | t.Log(alq.Take()) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /boltdb/boltdb_study_test.go: -------------------------------------------------------------------------------- 1 | package boltdb 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestOpenBolt(t *testing.T) { 8 | OpenBolt() 9 | } 10 | //370.10s 11 | func TestBoltUpdate(t *testing.T) { 12 | BoltUpdate() 13 | } 14 | //356.36s 15 | func TestBoltBatch(t *testing.T) { 16 | BoltBatch() 17 | } -------------------------------------------------------------------------------- /algorithm/load_balance_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import "testing" 4 | 5 | func TestNewWeightedRoundRobin(t *testing.T) { 6 | wrr := NewWeightedRoundRobin(map[string]int{"10.1": 7, "10.2": 2, "10.3": 1}) 7 | for i := 0; i < 10; i++ { 8 | sw := wrr.Select() 9 | t.Log(sw.Ip) 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /hystrix/hystrix_study_test.go: -------------------------------------------------------------------------------- 1 | package hystrix 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestHystrixAsyStudy(t *testing.T) { 8 | HystrixAsyStudy() 9 | } 10 | 11 | func TestHystrixSynStudy(t *testing.T) { 12 | HystrixSynStudy() 13 | } 14 | 15 | func TestHystrixCurrentStudy(t *testing.T) { 16 | HystrixCurrentStudy() 17 | } 18 | -------------------------------------------------------------------------------- /basic/unicode_study.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "unicode" 5 | ) 6 | 7 | //是否是字母 8 | func IsLetter(r rune) bool { 9 | 10 | return unicode.IsLetter(r) 11 | } 12 | 13 | //是否是数字 14 | func IsDigit(r rune) bool { 15 | 16 | return unicode.IsDigit(r) 17 | } 18 | 19 | //是否特殊字符 20 | func IsTitle(r rune) bool { 21 | 22 | return unicode.IsTitle(r) 23 | } 24 | -------------------------------------------------------------------------------- /gui/gui_study.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fyne.io/fyne/app" 5 | "fyne.io/fyne/widget" 6 | ) 7 | 8 | func main() { 9 | app := app.New() 10 | 11 | w := app.NewWindow("Hello") 12 | w.SetContent(widget.NewVBox( 13 | widget.NewLabel("Hello Fyne!"), 14 | widget.NewButton("Quit", func() { 15 | app.Quit() 16 | }), 17 | )) 18 | 19 | w.ShowAndRun() 20 | } 21 | -------------------------------------------------------------------------------- /algorithm/tire_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import "testing" 4 | 5 | func TestTireTree_Insert(t *testing.T) { 6 | tt := &TireTree{} 7 | tt.Insert("abbcd") 8 | tt.Insert("cd") 9 | tt.Insert("abr") 10 | tt.Insert("abcd") 11 | t.Log(tt.Query("cd")) 12 | t.Log(tt.Query("wer")) 13 | //tt.PreTraverse(tt.root) 14 | t.Log(tt.CountPrefix("c")) 15 | tt.PreTraverse(tt.root) 16 | } 17 | -------------------------------------------------------------------------------- /algorithm/funnel_rate_limiter_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | "testing" 7 | "time" 8 | ) 9 | 10 | func TestNewFunnelRateLimiter(t *testing.T) { 11 | var wg sync.WaitGroup 12 | wg.Add(1) 13 | limiter := NewFunnelRateLimiter(1000, 1000) 14 | for { 15 | fmt.Println(limiter.IsAllow()) 16 | time.Sleep(2 * time.Millisecond) 17 | } 18 | wg.Wait() 19 | } 20 | -------------------------------------------------------------------------------- /basic/reflection_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestReflectionStudy(t *testing.T) { 9 | ReflectionStudy() 10 | } 11 | 12 | func TestFuncReflection(t *testing.T) { 13 | FuncReflection(func(s string) { 14 | fmt.Println(s) 15 | }, "ss") 16 | } 17 | 18 | func TestReflect01(t *testing.T) { 19 | var num int64 = 10 20 | Reflect01(num) 21 | } 22 | -------------------------------------------------------------------------------- /basic/scanner_study.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "os" 7 | "text/scanner" 8 | "unicode/utf8" 9 | ) 10 | 11 | 12 | func ScannerStudy(){ 13 | 14 | var s scanner.Scanner 15 | file,_ := os.Open("E:\\新建文本文档.txt") 16 | s.Init(bufio.NewReader(file)) 17 | tok := s.Scan() 18 | fmt.Println(tok) 19 | //验证是不是utf8的字符 20 | fmt.Println(utf8.ValidRune(tok)) 21 | 22 | } 23 | -------------------------------------------------------------------------------- /algorithm/token_bucket_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | "testing" 7 | "time" 8 | ) 9 | 10 | func TestNewTokenBucket(t *testing.T) { 11 | var wg sync.WaitGroup 12 | wg.Add(1) 13 | tokenBucket := NewTokenBucket(1000) 14 | for { 15 | //模拟每隔10毫秒消费一个令牌 16 | fmt.Println(tokenBucket.PopToken()) 17 | time.Sleep(time.Millisecond * 10) 18 | } 19 | wg.Wait() 20 | } 21 | -------------------------------------------------------------------------------- /document/go优秀文章链接: -------------------------------------------------------------------------------- 1 | 2 | ### go编程容易犯的错误 3 | https://segmentfault.com/a/1190000013739000?utm_source=tag-newest 4 | 5 | ### go defer执行时机 6 | https://blog.csdn.net/dengming0922/article/details/80946420 7 | 8 | ### golang bufio 包中的用法 9 | https://studygolang.com/articles/4367 10 | 11 | ### golang 拆包,粘包 12 | https://www.cnblogs.com/yorkyang/p/7259919.html 13 | 14 | -------------------------------------------------------------------------------- /document/protobuffer使用文档: -------------------------------------------------------------------------------- 1 | ### protobuffer使用 2 | 3 | .代表生成的.go文件的目录,这里是当前目录,也可以指定,比如(E:\) 4 | route_guide.proto 是proto文件的名称 5 | protoc --go_out=. route_guide.proto 6 | 7 | -I 指的是route_guide.proto 这个文件所在的目录 ,如果在当前目录下,可以不指定,如上面的写法 8 | protoc -I ./proto --go_out=E:\ route_guide.proto 9 | 10 | grpc-go生成客户端服务器端代码 11 | protoc --go_out=plugins=grpc:. route_guide.proto 12 | 13 | -------------------------------------------------------------------------------- /algorithm/disk_merge_sort_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestRedFileSortWriteTempFile(t *testing.T) { 8 | RedFileSortWriteTempFile("E://number.txt") 9 | } 10 | 11 | func TestQuickSort2(t *testing.T) { 12 | t.Log(QuickSort2([]int{15, 3, 5, 2, 8, 0, 19, 21, 7, 65, 6, 76, 12, 17})) 13 | } 14 | 15 | func TestCreateSourceFile(t *testing.T) { 16 | CreateSourceFile() 17 | } 18 | -------------------------------------------------------------------------------- /basic/pprof_study_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "testing" 5 | 6 | _ "net/http/pprof" 7 | ) 8 | 9 | // 针对web性能监测 ,引入 _ "net/http/pprof" 就可以了 10 | 11 | func TestPprofWeb(t *testing.T) { 12 | 13 | PprofWeb() 14 | 15 | } 16 | 17 | func TestPProfCPUApplication(t *testing.T) { 18 | PProfCPUApplication() 19 | } 20 | 21 | func TestPProfMemApplication(t *testing.T) { 22 | PProfMemApplication() 23 | } 24 | -------------------------------------------------------------------------------- /basic/hash_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | /** 8 | golang hash函数学习 9 | */ 10 | 11 | func TestMd5(t *testing.T) { 12 | Md5() 13 | } 14 | 15 | func TestBase64(t *testing.T) { 16 | Base64() 17 | } 18 | 19 | func TestHash(t *testing.T) { 20 | HashTest() 21 | } 22 | 23 | func TestCrc(t *testing.T) { 24 | Crc() 25 | } 26 | 27 | func TestMapHashStudy(t *testing.T) { 28 | MapHashStudy() 29 | } 30 | -------------------------------------------------------------------------------- /basic/net_client.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "net" 7 | ) 8 | 9 | func StartClient() { 10 | 11 | conn, _ := net.Dial("tcp4", ":8080") 12 | len, _ := conn.Write([]byte("您好")) 13 | fmt.Println("发送成功,字节数为:", len) 14 | buffer := bytes.NewBuffer(make([]byte, 1024, 1024)) 15 | l, _ := conn.Read(buffer.Bytes()) 16 | fmt.Println("读取服务端数据:", buffer.String(), "字节数:", l) 17 | defer conn.Close() 18 | 19 | } 20 | -------------------------------------------------------------------------------- /go_thinking/prime_number_test.go: -------------------------------------------------------------------------------- 1 | // 用go思维实现求1-100的质数 2 | 3 | //质数又称素数。指整数在一个大于1的自然数中,除了1和此整数自身外,没法被其他自然数整除的数 4 | package go_thinking 5 | 6 | import ( 7 | "fmt" 8 | "testing" 9 | ) 10 | 11 | func TestSieve(t *testing.T) { 12 | Sieve() 13 | } 14 | 15 | func BenchmarkSieve(b *testing.B) { 16 | for i := 1; i < 100; i++ { 17 | Sieve() 18 | } 19 | } 20 | 21 | func TestSieveNew(t *testing.T) { 22 | fmt.Println(SieveNew(100)) 23 | } 24 | -------------------------------------------------------------------------------- /protobuffer/test.pb_test.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // source: test.proto 3 | 4 | package protobuffer 5 | 6 | import "testing" 7 | 8 | func TestWrite(t *testing.T) { 9 | 10 | Write() 11 | } 12 | 13 | func TestRead(t *testing.T) { 14 | Read() 15 | } 16 | 17 | func TestBenchMarkJson(t *testing.T) { 18 | BenchMarkJson() 19 | } 20 | 21 | func TestBenchMarkProto(t *testing.T) { 22 | BenchMarkProto() 23 | } 24 | -------------------------------------------------------------------------------- /algorithm/skip_list_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestNewSkipList(t *testing.T) { 8 | //创建一个32层的跳跃列表 9 | skip := NewSkipList(32) 10 | for i := 0; i < 10000000; i++ { 11 | skip.insert(uint64(i), i) 12 | } 13 | } 14 | 15 | func BenchmarkNewSkipList(b *testing.B) { 16 | //创建一个32层的跳跃列表 17 | skip := NewSkipList(32) 18 | for i := 0; i < 1000000; i++ { 19 | skip.insert(uint64(i), i) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /algorithm/avltree1_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestAvlInsert(t *testing.T) { 9 | avlTree := AvlInsert(nil, 8) 10 | avlTree = AvlInsert(avlTree, 4) 11 | avlTree = AvlInsert(avlTree, 15) 12 | avlTree = AvlInsert(avlTree, 5) 13 | avlTree = AvlInsert(avlTree, 6) 14 | 15 | fmt.Println(avlTree.high) 16 | t.Log(getAvlHeight(avlTree)) 17 | //MidOrder(avlTree) 18 | //PoOrder(avlTree) 19 | } 20 | -------------------------------------------------------------------------------- /basic/ast_study.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "go/ast" 5 | "go/parser" 6 | "go/token" 7 | ) 8 | 9 | func AstStudy() { 10 | 11 | // Create the AST by parsing src. 12 | fset := token.NewFileSet() // positions are relative to fset 13 | 14 | // 解析ast_study.go的代码 15 | f, err := parser.ParseFile(fset, "ast_study.go", nil, 0) 16 | if err != nil { 17 | panic(err) 18 | } 19 | 20 | // Print the AST. 21 | ast.Print(fset, f) 22 | 23 | } 24 | -------------------------------------------------------------------------------- /algorithm/int_heap_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestIntHeap_Len(t *testing.T) { 8 | heap := &IntHeap{} 9 | 10 | heap.Push(1) 11 | heap.Push(4) 12 | heap.Push(2) 13 | heap.Push(5) 14 | heap.Push(6) 15 | heap.Push(6) 16 | heap.Push(5) 17 | heap.Push(0) 18 | t.Log(heap) 19 | t.Log(heap.Pop()) 20 | t.Log(heap) 21 | t.Log(heap.Pop()) 22 | t.Log(heap) 23 | t.Log(heap.Pop()) 24 | t.Log(heap) 25 | 26 | } 27 | -------------------------------------------------------------------------------- /blockchain/blockchain_test.go: -------------------------------------------------------------------------------- 1 | package blockchain 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func Test_NewBlockChain(t *testing.T) { 9 | 10 | blockChain := NewBlockChain() 11 | blockChain.AddBlock("添加第一个区块") 12 | blockChain.AddBlock("添加第二个区块") 13 | 14 | for _, block := range blockChain.blocks { 15 | fmt.Println("PreHash: ", block.PrevBlockHash) 16 | fmt.Println("Data: ", string(block.Data)) 17 | fmt.Println("Hash: ", block.Hash) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /basic/http_server.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | ) 7 | 8 | //SET CGO_ENABLED=0 9 | //SET GOOS=linux 10 | //SET GOARCH=amd64 11 | //go build cron_delete_compute_result_uat.go 12 | func StartHttpServer() { 13 | 14 | http.HandleFunc("/", IndexHandler) 15 | http.ListenAndServe(":8080", nil) 16 | 17 | } 18 | 19 | func IndexHandler(w http.ResponseWriter, r *http.Request) { 20 | 21 | fmt.Fprintln(w, "hello world:"+r.Form.Get("key")) 22 | } 23 | -------------------------------------------------------------------------------- /algorithm/array_lru_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "strconv" 5 | "testing" 6 | ) 7 | 8 | func TestLRUArray_Put(t *testing.T) { 9 | lru := LRUArray{} 10 | 11 | for j := 1; j <= 11; j++ { 12 | lru.Put(strconv.Itoa(j), strconv.Itoa(j)) 13 | } 14 | t.Log(lru.keys) 15 | t.Log(lru.values) 16 | t.Log(lru.Get("5")) 17 | t.Log(lru.keys) 18 | t.Log(lru.values) 19 | t.Log(lru.Get("5")) 20 | t.Log(lru.keys) 21 | t.Log(lru.values) 22 | t.Log(lru.maxIndex) 23 | } 24 | -------------------------------------------------------------------------------- /grpc/helloworld_demo/register_center/register.go: -------------------------------------------------------------------------------- 1 | package register_center 2 | 3 | import "time" 4 | 5 | //服务描述信息 6 | type ServiceDescInfo struct { 7 | //服务名称 8 | ServiceName string 9 | //ip地址 10 | Host string 11 | //端口 12 | Port int 13 | //心跳间隔 秒 14 | IntervalTime time.Duration 15 | } 16 | 17 | //服务注册和下线的接口 18 | type RegisterI interface { 19 | 20 | //服务注册 21 | Register(serviceInfo ServiceDescInfo) error 22 | 23 | //服务下线 24 | UnRegister(serviceInfo ServiceDescInfo) error 25 | } 26 | -------------------------------------------------------------------------------- /basic/context_study_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import "testing" 4 | 5 | func TestContextWithTimeOutOne(t *testing.T) { 6 | ContextWithTimeOutOne() 7 | } 8 | 9 | func TestContextWithTimeOut(t *testing.T) { 10 | ContextWithTimeOut() 11 | } 12 | 13 | func TestContextWithCancel(t *testing.T) { 14 | ContextWithCancel() 15 | } 16 | 17 | func TestContextWithDeadLine(t *testing.T) { 18 | ContextWithDeadLine() 19 | } 20 | 21 | func TestContextWithValue(t *testing.T) { 22 | ContextWithValue() 23 | } 24 | -------------------------------------------------------------------------------- /benchmark/recursion_test.go: -------------------------------------------------------------------------------- 1 | package benchmark 2 | 3 | import "testing" 4 | 5 | func TestFib(t *testing.T) { 6 | Fib(45) 7 | } 8 | 9 | func BenchmarkFib(b *testing.B) { 10 | Fib(45) 11 | } 12 | 13 | func TestMethod(t *testing.T) { 14 | Method() 15 | } 16 | 17 | func BenchmarkMethod2(b *testing.B) { 18 | Method() 19 | } 20 | 21 | func BenchmarkMethod(b *testing.B) { 22 | Method() 23 | } 24 | 25 | func TestSort(t *testing.T) { 26 | Sort() 27 | } 28 | 29 | func TestSort1(t *testing.T) { 30 | Sort1() 31 | } 32 | -------------------------------------------------------------------------------- /gotask/gotask_test.go: -------------------------------------------------------------------------------- 1 | package gotask 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | var gotask = NewGoTask(1000, false) 9 | 10 | func TestNewGoTask(t *testing.T) { 11 | 12 | gotask.Add(compute, Student{Name: "spw", Age: 26}) 13 | 14 | gotask.Start() 15 | } 16 | 17 | type Student struct { 18 | Name string 19 | Age int 20 | } 21 | 22 | func compute(data ...interface{}) { 23 | 24 | stu := gotask.GetParamter(0, data).(Student) 25 | 26 | fmt.Println(stu.Name) 27 | fmt.Println(stu.Age) 28 | 29 | } 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ###包结构说明 2 | 3 | algorithm 常用算法包 4 | array_utils 数组操作工具包 5 | basic 基础学习包(golang基础库的学习用例) 6 | blockchain 区块链学习包 7 | excel excel学习包 8 | blotdb 开源框架学习 9 | document 一些文档 10 | event_bus golang的event_bus 11 | excel golang操作excel学习 12 | go_thinking go编程思想练习 13 | go_task go任务池练习 14 | grpc grpc学习 15 | image_watermark 给图片加水印 16 | pipleline 管道学习 17 | redis go的redis学习 18 | stream 流编程练习 19 | string_utils 字符串操作工具包 20 | tools 工具类 21 | charts 图表类 22 | -------------------------------------------------------------------------------- /protobuffer/test.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package protobuffer; 4 | 5 | 6 | // 手机类型 7 | // 枚举类型第一个字段必须是0 8 | enum PhoneType { 9 | 10 | HOME = 0; 11 | WORK = 1; 12 | 13 | } 14 | 15 | // 手机 16 | message Phone { 17 | PhoneType type = 1; 18 | string number = 2; 19 | } 20 | // 人 21 | message Person { 22 | int32 id = 1; 23 | string name = 2; 24 | // repeated 表示可以重复 可以有多个手机 25 | repeated Phone phones = 3; 26 | } 27 | // 联系簿 28 | message ContactBook { 29 | repeated Person persons = 1; 30 | } -------------------------------------------------------------------------------- /serialize/person.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package serialize; 4 | 5 | import "google/protobuf/timestamp.proto"; 6 | 7 | // 人 8 | message PersonProto3 { 9 | string name = 1; 10 | int64 age = 2; 11 | int64 sex = 3; 12 | repeated string like = 4; 13 | repeated PersonProto3 children = 5; 14 | repeated string address = 6; 15 | repeated string phone = 7; 16 | string card = 8; 17 | string qq = 9; 18 | string weChat = 10; 19 | google.protobuf.Timestamp birthday = 11; 20 | double money = 12; 21 | } 22 | -------------------------------------------------------------------------------- /algorithm/hashmap_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "strconv" 5 | "testing" 6 | ) 7 | 8 | func TestNewHashMap(t *testing.T) { 9 | hm := NewHashMap() 10 | hm.Put("spw", "Sun") 11 | hm.Put("spw", "Sun") 12 | hm.Put("spw", "Sun") 13 | 14 | t.Log(hm.Size()) 15 | for i := 0; i < 1000000; i++ { 16 | hm.Put("spw"+strconv.Itoa(i), "Sun") 17 | } 18 | t.Log(hm.Size()) 19 | t.Log("ss") 20 | } 21 | 22 | func BenchmarkHashMap_Put(b *testing.B) { 23 | hm := NewHashMap() 24 | for i := 0; i < b.N; i++ { 25 | hm.Put("spw", "Sun") 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /grpc/helloworld_demo/server/hello_world_server.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "go_common/grpc/helloworld_demo/impl" 5 | pb "go_common/grpc/helloworld_demo/proto" 6 | "log" 7 | "net" 8 | 9 | "google.golang.org/grpc" 10 | ) 11 | 12 | func StartServer() { 13 | lis, err := net.Listen("tcp", "127.0.0.1:8090") 14 | if err != nil { 15 | log.Fatalf("failed to listen: %v", err) 16 | } 17 | //创建一个grpc服务器对象 18 | gRpcServer := grpc.NewServer() 19 | 20 | pb.RegisterHelloServiceServer(gRpcServer, &impl.HelloServiceServer{}) 21 | //开启服务端 22 | gRpcServer.Serve(lis) 23 | } 24 | -------------------------------------------------------------------------------- /basic/sync_study_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import "testing" 4 | 5 | //sync 包的学习 6 | 7 | func TestSyncMap(t *testing.T) { 8 | for i := 0; i < 100; i++ { 9 | SyncMapPut(i, i) 10 | } 11 | for i := 150; i < 200; i++ { 12 | SyncMapUpdate(i, i) 13 | } 14 | for i := 0; i < 100; i++ { 15 | SyncMapRead(i) 16 | } 17 | 18 | SyncMapRange() 19 | } 20 | 21 | func TestStudyMutex(t *testing.T) { 22 | StudyMutex() 23 | } 24 | 25 | func TestStudySyncOnce(t *testing.T) { 26 | StudySyncOnce() 27 | } 28 | 29 | func TestStudySyncPool(t *testing.T) { 30 | StudySyncPool() 31 | 32 | } 33 | -------------------------------------------------------------------------------- /gout/gout_study_test.go: -------------------------------------------------------------------------------- 1 | package gout 2 | 3 | import "testing" 4 | 5 | func TestStudyGoutGet(t *testing.T) { 6 | StudyGoutGet() 7 | } 8 | 9 | func TestStudyGoutGetAndCallBack(t *testing.T) { 10 | StudyGoutCallBack() 11 | } 12 | 13 | func TestStudyGoutTimeOut(t *testing.T) { 14 | StudyGoutTimeOut() 15 | } 16 | 17 | func TestStudyGoutGetDebug(t *testing.T) { 18 | StudyGoutGetDebug() 19 | } 20 | func TestStudyGoutGetTraceInfo(t *testing.T) { 21 | StudyGoutGetTraceInfo() 22 | } 23 | 24 | func TestStudyGoutBenchmarkDuration(t *testing.T) { 25 | StudyGoutBenchmarkDuration() 26 | } 27 | -------------------------------------------------------------------------------- /basic/runtime_study.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "fmt" 5 | "runtime" 6 | ) 7 | 8 | func StudyRuntime() { 9 | 10 | fmt.Println("cpus:", runtime.NumCPU()) 11 | fmt.Println("goroot:", runtime.GOROOT()) 12 | fmt.Println("archive:", runtime.GOOS) 13 | 14 | exit := make(chan int) 15 | go func() { 16 | defer close(exit) 17 | go func() { 18 | fmt.Println("b") 19 | }() 20 | }() 21 | 22 | for i := 0; i < 4; i++ { 23 | fmt.Println("a:", i) 24 | 25 | if i == 2 { 26 | runtime.Gosched() //切换任务 27 | } 28 | } 29 | <-exit 30 | } 31 | 32 | func init() { 33 | runtime.GOMAXPROCS(8) //使用单核 34 | } 35 | -------------------------------------------------------------------------------- /algorithm/top_k_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestQuickSortTopK(t *testing.T) { 9 | t.Log(QuickSortTopK([]int{15, 3, 98, 2, 8, 87, 19, 21, 7, 65, 6, 76, 12, 100, 99}, 5)) 10 | } 11 | func TestSelectSortTopK(t *testing.T) { 12 | t.Log(SelectSortTopK([]int{15, 3, 5, 2, 8, 0, 19, 21, 7, 65, 6, 76, 12, 17}, 5)) 13 | } 14 | func TestHeadTopK(t *testing.T) { 15 | t.Log(HeadTopK([]int{1, 3, 5, 2, 18, 0, 19, 21, 7, 65, 6, 76, 12, 17}, 5)) 16 | } 17 | 18 | func TestHeapSortComputeTop10(t *testing.T) { 19 | result, err := HeapSortComputeTop10("D:\\github\\go_common\\algorithm\\top_k.txt") 20 | 21 | fmt.Println(result, err) 22 | } 23 | -------------------------------------------------------------------------------- /grpc/helloworld_demo/proto/hello_world.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package proto; 3 | //接口请求入参 4 | message HelloRequest{ 5 | string request = 1; 6 | } 7 | //接口返回出参 8 | message HelloResponse{ 9 | string response = 1; 10 | } 11 | //定义接口 12 | service HelloService{ 13 | //一个简单的rpc 14 | rpc HelloWorld(HelloRequest) returns (HelloResponse){} 15 | //一个服务器端流式rpc 16 | rpc HelloWorldServerStream(HelloRequest) returns (stream HelloResponse){} 17 | //一个客户端流式rpc 18 | rpc HelloWorldClientStream(stream HelloRequest) returns (HelloResponse){} 19 | //一个客户端和服务器端双向流式rpc 20 | rpc HelloWorldClientAndServerStream(stream HelloRequest) returns (stream HelloResponse){} 21 | } 22 | 23 | -------------------------------------------------------------------------------- /algorithm/count_limiter_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | "time" 7 | ) 8 | 9 | func TestNewCountLimiter(t *testing.T) { 10 | 11 | cl := NewCountLimiter(100, time.Second*1) 12 | for i := 0; i < 110; i++ { 13 | fmt.Println(cl.IsAllow()) 14 | } 15 | time.Sleep(1 * time.Second) 16 | for i := 0; i < 110; i++ { 17 | fmt.Println(cl.IsAllow()) 18 | } 19 | } 20 | 21 | func TestNewCountLimiterNew(t *testing.T) { 22 | cl := NewCountLimiterNew(100, time.Now().UnixNano()) 23 | for i := 0; i < 110; i++ { 24 | fmt.Println(cl.IsAllowNew()) 25 | } 26 | time.Sleep(1 * time.Second) 27 | for i := 0; i < 110; i++ { 28 | fmt.Println(cl.IsAllowNew()) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /grpc/helloworld_demo/client/hello_world_client_intercept.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | pb "go_common/grpc/helloworld_demo/proto" 7 | "log" 8 | 9 | "google.golang.org/grpc" 10 | ) 11 | 12 | func StartClientIntercept() { 13 | var opts []grpc.DialOption 14 | opts = append(opts, grpc.WithInsecure()) 15 | conn, err := grpc.Dial("127.0.0.1:8090", opts...) 16 | if err != nil { 17 | fmt.Println(err) 18 | return 19 | } 20 | c := pb.NewHelloServiceClient(conn) 21 | 22 | r, err := c.HelloWorld(context.Background(), &pb.HelloRequest{}) 23 | if err != nil { 24 | log.Fatalf("%v", err) 25 | return 26 | } 27 | fmt.Println(r.Response) 28 | defer conn.Close() 29 | } 30 | -------------------------------------------------------------------------------- /algorithm/arraystack_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import "testing" 4 | 5 | func TestPush(t *testing.T) { 6 | stack := Push(nil, 1) 7 | stack = Push(stack, 2) 8 | t.Log(stack.Size) 9 | Pop(stack) 10 | t.Log(stack.Size) 11 | } 12 | 13 | func TestPeek(t *testing.T) { 14 | t.Log(Peek(Push(&ArrayStack{}, 1))) 15 | } 16 | 17 | func TestIsEmpty(t *testing.T) { 18 | t.Log(IsEmpty(nil)) 19 | t.Log(IsEmpty(&ArrayStack{})) 20 | t.Log(IsEmpty(Push(&ArrayStack{}, 1))) 21 | } 22 | 23 | func TestNextGreaterElement(t *testing.T) { 24 | t.Log(NextGreaterElement([]int{4, 1, 2}, []int{1, 3, 4, 2})) 25 | } 26 | 27 | func TestCalPoints(t *testing.T) { 28 | t.Log(CalPoints([]string{"5", "2", "C", "D", "+"})) 29 | } 30 | -------------------------------------------------------------------------------- /grpc/helloworld_demo/server/hello_world_server_tls.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "go_common/grpc/helloworld_demo/impl" 5 | pb "go_common/grpc/helloworld_demo/proto" 6 | "log" 7 | "net" 8 | 9 | "google.golang.org/grpc" 10 | "google.golang.org/grpc/credentials" 11 | ) 12 | 13 | func StartServerTLS() { 14 | 15 | lis, err := net.Listen("tcp", "127.0.0.1:8090") 16 | if err != nil { 17 | log.Fatalf("failed to listen: %v", err) 18 | } 19 | // TLS认证 20 | creds, err := credentials.NewServerTLSFromFile("E:\\server.pem", "E:\\server.key") 21 | gRpcServer := grpc.NewServer(grpc.Creds(creds)) 22 | pb.RegisterHelloServiceServer(gRpcServer, &impl.HelloServiceServer{}) 23 | gRpcServer.Serve(lis) 24 | } 25 | -------------------------------------------------------------------------------- /basic/rand_study.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "time" 7 | ) 8 | 9 | func Rand(){ 10 | 11 | //设置一个随机数种子 12 | rand.Seed(time.Now().Unix()) 13 | 14 | 15 | //返回一个非负的伪随机int值。 16 | fmt.Println(rand.Int()) 17 | //返回一个int32类型的非负的31位伪随机数。 18 | fmt.Println(rand.Int31()) 19 | //返回一个int64类型的非负的63位伪随机数。 20 | fmt.Println(rand.Int63()) 21 | 22 | 23 | 24 | 25 | fmt.Println(rand.Intn(100)) 26 | fmt.Println(rand.Int31n(100)) 27 | fmt.Println(rand.Int63n(100)) 28 | 29 | //返回一个0.0 到1.0的float32随机数 30 | fmt.Println(rand.Float32()) 31 | //返回一个0.0 到1.0的float64随机数 32 | fmt.Println(rand.Float64()) 33 | 34 | 35 | //返回一个[0,10) 范围的10个随机数 36 | fmt.Println(rand.Perm(10)) 37 | 38 | } 39 | -------------------------------------------------------------------------------- /cli/cli_study.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "os" 7 | 8 | "github.com/urfave/cli/v2" 9 | ) 10 | 11 | func CliStudy() { 12 | app := &cli.App{ 13 | Flags: []cli.Flag{ 14 | &cli.StringFlag{ 15 | Name: "lang", 16 | Value: "english", 17 | Usage: "language for the greeting", 18 | }, 19 | }, 20 | Action: func(c *cli.Context) error { 21 | name := "Nefertiti" 22 | if c.NArg() > 0 { 23 | name = c.Args().Get(0) 24 | } 25 | if c.String("lang") == "spanish" { 26 | fmt.Println("Hola", name) 27 | } else { 28 | fmt.Println("Hello", name) 29 | } 30 | return nil 31 | }, 32 | } 33 | 34 | err := app.Run(os.Args) 35 | if err != nil { 36 | log.Fatal(err) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /algorithm/array_queue.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | /** 4 | 基于数组实现的循环队列 5 | */ 6 | 7 | type ArrayLoopQueue struct { 8 | data []interface{} 9 | head int 10 | tail int 11 | size int 12 | } 13 | 14 | func (alq *ArrayLoopQueue) Add(value interface{}) bool { 15 | if alq.data == nil { 16 | alq.data = make([]interface{}, 10, 10) 17 | } 18 | length := len(alq.data) 19 | if (alq.tail+1)%length == alq.head { 20 | return false 21 | } 22 | alq.data[alq.tail%length] = value 23 | alq.tail++ 24 | alq.size++ 25 | return true 26 | } 27 | 28 | func (alq *ArrayLoopQueue) Take() interface{} { 29 | length := len(alq.data) 30 | if alq.tail == alq.head { 31 | return nil 32 | } 33 | v := alq.data[alq.head%length] 34 | alq.size-- 35 | alq.head++ 36 | return v 37 | } 38 | -------------------------------------------------------------------------------- /algorithm/linkqueue_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | ) 7 | 8 | func TestLinkQueue_Add(t *testing.T) { 9 | queue := &LinkQueue{nil, nil, 0} 10 | start := time.Now().Unix() 11 | for i := 0; i < 10000000; i++ { 12 | queue.Add(i) 13 | } 14 | end := time.Now().Unix() 15 | result := end - start 16 | t.Log("添加1000万数据耗时:", result, " 秒") 17 | 18 | getStart := time.Now().Unix() 19 | for i := 0; i < 10000000; i++ { 20 | queue.Take() 21 | } 22 | getEnd := time.Now().Unix() 23 | getResult := getEnd - getStart 24 | t.Log("取出1000万数据耗时:", getResult, " 秒") 25 | } 26 | 27 | func BenchmarkLinkQueue_Add(b *testing.B) { 28 | queue := &LinkQueue{nil, nil, 0} 29 | for i := 0; i < b.N; i++ { 30 | queue.Add(i) 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /pipleline/pipleline_test.go: -------------------------------------------------------------------------------- 1 | package pipleline 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "testing" 7 | ) 8 | 9 | func TestPipeline_Async(t *testing.T) { 10 | 11 | //工序(1)在pipeline外执行,最后一个工序是保存checkpoint 12 | pipeline := NewPipeline(8, 32, 2, 1) 13 | for { 14 | i := 1 15 | //(1) 16 | //加载100条数据,并修改变量checkpoint 17 | //data是数组,每个元素是一条评论,之后的联表、NLP都直接修改data里的每条记录。 18 | ok := pipeline.Async(func() error { 19 | i = i + 1 20 | return nil 21 | }, func() error { 22 | i = i + 1 23 | return nil 24 | }, func() error { 25 | i = i + 1 26 | return nil 27 | }, func() error { 28 | fmt.Println(i) 29 | return nil 30 | }) 31 | if !ok { 32 | break 33 | } 34 | } 35 | err := pipeline.Wait() 36 | 37 | if err != nil { 38 | log.Print(err) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /basic/websocket/client.go: -------------------------------------------------------------------------------- 1 | package websocket 2 | 3 | import ( 4 | "fmt" 5 | "golang.org/x/net/websocket" 6 | "log" 7 | ) 8 | 9 | func ClientWebSocket() { 10 | var origin = "http://localhost:8080" 11 | var url = "wss://localhost:8080" 12 | 13 | ws, err := websocket.Dial(url, "", origin) 14 | 15 | if err != nil { 16 | log.Fatal(err) 17 | } 18 | for i := 0; i < 4; i++ { 19 | message := []byte("\u0002{\"bussinessType\":1,\"messageType\":5}\u0003") 20 | _, err = ws.Write(message) 21 | if err != nil { 22 | log.Fatal(err) 23 | } 24 | fmt.Printf("Send: %s\n", message) 25 | 26 | var msg = make([]byte, 512) 27 | m, err := ws.Read(msg) 28 | if err != nil { 29 | log.Fatal(err) 30 | } 31 | fmt.Printf("Receive: %s\n", msg[:m]) 32 | } 33 | ws.Close() //关闭连接 34 | } 35 | -------------------------------------------------------------------------------- /basic/websocket/server.go: -------------------------------------------------------------------------------- 1 | package websocket 2 | 3 | import ( 4 | "fmt" 5 | "golang.org/x/net/websocket" 6 | "log" 7 | "net/http" 8 | ) 9 | 10 | func msgHandler(ws *websocket.Conn) { 11 | msg := make([]byte, 512) 12 | n, err := ws.Read(msg) 13 | if err != nil { 14 | log.Fatal(err) 15 | } 16 | fmt.Printf("Receive: %s\n", msg[:n]) 17 | 18 | send_msg := "[" + string(msg[:n]) + "]" 19 | m, err := ws.Write([]byte(send_msg)) 20 | if err != nil { 21 | log.Fatal(err) 22 | } 23 | fmt.Printf("Send: %s\n", msg[:m]) 24 | } 25 | func ServerWebSocket() { 26 | http.Handle("/echo", websocket.Handler(msgHandler)) 27 | http.Handle("/", http.FileServer(http.Dir("."))) 28 | 29 | err := http.ListenAndServe("127.0.0.1:9091", nil) 30 | 31 | if err != nil { 32 | panic("ListenAndServe: " + err.Error()) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /basic/gob_study.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "bytes" 5 | "encoding/gob" 6 | "fmt" 7 | ) 8 | 9 | /** 10 | 各个类型的编解码规则 11 | 整型:分为sign int和usign int, 其中从上面例子也看到,int和uint是不能互相编解码的。float和int也是不能互相编解码的。 12 | Struct,array,slice是可以被编码的。但是function和channel是不能被编码的。 13 | bool类型是被当作uint来编码的,0是false,1是true。 14 | 浮点类型的值都是被当作float64类型的值来编码的 15 | String和[]byte传递是uint(byte个数) + byte[]的形式编码的 16 | Slice和array是按照uint(array个数) + 每个array编码 这样的形式进行编码的 17 | Maps是按照 uint(Map个数) + 键值对 这样的形式进行编码的 18 | */ 19 | type P struct { 20 | X int 21 | Y string 22 | } 23 | type Q struct { 24 | Y string 25 | X int 26 | Z string 27 | } 28 | 29 | /** 30 | 字段先后顺序不影响编解码 31 | */ 32 | func EncoderAndDecoder(p P, q Q) { 33 | buf := bytes.Buffer{} 34 | gob.NewEncoder(&buf).Encode(p) 35 | gob.NewDecoder(&buf).Decode(&q) 36 | fmt.Println(q) 37 | 38 | } 39 | -------------------------------------------------------------------------------- /redis/redis_go_test.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import "testing" 4 | 5 | func TestString(t *testing.T) { 6 | String() 7 | } 8 | 9 | func TestHash(t *testing.T) { 10 | Hash() 11 | } 12 | 13 | func TestList(t *testing.T) { 14 | List() 15 | } 16 | 17 | func TestSet(t *testing.T) { 18 | Set() 19 | } 20 | 21 | func TestSetDistributeLock(t *testing.T) { 22 | SetDistributeLock() 23 | } 24 | 25 | func TestReleaseDistributeLock(t *testing.T) { 26 | ReleaseDistributeLock() 27 | } 28 | 29 | func TestSortedSet(t *testing.T) { 30 | SortedSet() 31 | } 32 | 33 | func TestDelayedQueue(t *testing.T) { 34 | DelayedQueue() 35 | } 36 | 37 | func TestHyperLogLog(t *testing.T) { 38 | HyperLogLog() 39 | } 40 | 41 | func TestBitMap(t *testing.T) { 42 | BitMap() 43 | } 44 | 45 | func TestBloomFilter(t *testing.T) { 46 | BloomFilter() 47 | } 48 | -------------------------------------------------------------------------------- /basic/net_server.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "net" 7 | ) 8 | 9 | func StartServer() { 10 | addr, _ := net.ResolveTCPAddr("tcp4", ":8080") 11 | listener, _ := net.ListenTCP("tcp4", addr) 12 | fmt.Println("服务器", listener.Addr().Network(), "启动成功") 13 | for { 14 | conn, err := listener.Accept() 15 | if err != nil { 16 | fmt.Println("接受客户端连接错误:", err) 17 | continue 18 | } 19 | go handlerConn(conn) 20 | } 21 | } 22 | 23 | func handlerConn(conn net.Conn) { 24 | bs := make([]byte, 1024, 1024) 25 | for { 26 | n, err := conn.Read(bs) 27 | if err != nil { 28 | if err != io.EOF { 29 | } 30 | break 31 | } 32 | fmt.Println("读取到客户端数据:", string(bs), "数据大小:", n) 33 | } 34 | l, _ := conn.Write([]byte("服务端收到您发送的消息了")) 35 | fmt.Println("服务端发送给客户端消息成功,字节数为:", l) 36 | defer conn.Close() 37 | } 38 | -------------------------------------------------------------------------------- /tools/http_ sign_in_test.go: -------------------------------------------------------------------------------- 1 | package tools 2 | 3 | import ( 4 | "io/ioutil" 5 | "net/http" 6 | "testing" 7 | ) 8 | 9 | func TestLogin(t *testing.T) { 10 | param := make(map[string]string) 11 | 12 | param["userName"] = "32c3VucGVuZ3dlaTE=111" 13 | param["passWord"] = "32QWJjZDEyMw==222" 14 | param["domainCode"] = "GOMEDQ" 15 | client, authToken, err := Login(param, "http://office.gome.com.cn/newWeb/auth/domainsLogin.do") 16 | if err != nil { 17 | t.Error(err) 18 | } 19 | 20 | //利用登录成功返回的client继续发送请求 21 | req, _ := http.NewRequest("GET", "http://office.gome.com.cn/newWeb/data/gateway/site/getuserinfo.do?userId=1181345", nil) 22 | //添加请求认证信息 23 | req.Header.Add("Authorization", authToken) 24 | res, err := client.Do(req) 25 | defer res.Body.Close() 26 | bs, _ := ioutil.ReadAll(res.Body) 27 | result := string(bs) 28 | t.Log(result) 29 | } 30 | -------------------------------------------------------------------------------- /go_thinking/fibonacci.go: -------------------------------------------------------------------------------- 1 | package go_thinking 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // golang的思想求斐波那契数 8 | // 1,1,2,3,5,8,13,21、、、、 9 | func Fibonacci(n int) { 10 | 11 | c := make(chan int) 12 | quit := make(chan bool) 13 | go func() { 14 | for i := 0; i < n; i++ { 15 | num := <-c //这里读是因为防止select那里会阻塞 16 | fmt.Println(num) 17 | } 18 | //可以停止 19 | quit <- true 20 | }() 21 | 22 | x, y := 1, 1 23 | for { 24 | select { 25 | case c <- x: 26 | x, y = y, x+y 27 | case flag := <-quit: 28 | fmt.Println(flag) 29 | return 30 | } 31 | } 32 | close(c) 33 | close(quit) 34 | } 35 | 36 | // 1,1,2,3,5,8,13,21、、、、 37 | 38 | func FibonacciNew(n int) int { 39 | if n == 1 || n == 2 { 40 | return 1 41 | } 42 | x, y := 1, 1 43 | for i := 3; i <= n; i++ { 44 | temp := x 45 | x = y 46 | y = y + temp 47 | } 48 | return y 49 | } 50 | -------------------------------------------------------------------------------- /mysql_binlog/binlog_linstener.go: -------------------------------------------------------------------------------- 1 | package mysql_binlog 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/prometheus/common/log" 8 | "github.com/siddontang/go-mysql/mysql" 9 | "github.com/siddontang/go-mysql/replication" 10 | ) 11 | 12 | func Start() { 13 | cfg := replication.BinlogSyncerConfig{ 14 | ServerID: 100, 15 | Flavor: "mysql", 16 | Host: "47.94.195.36", 17 | Port: 3306, 18 | User: "root", 19 | Password: "root", 20 | } 21 | syncer := replication.NewBinlogSyncer(cfg) 22 | streamer, err := syncer.StartSync(mysql.Position{"mysql_binlog.000001", 0}) 23 | 24 | if err != nil { 25 | log.Fatalln(err) 26 | } 27 | 28 | for { 29 | ev, err := streamer.GetEvent(context.Background()) 30 | if err != nil { 31 | fmt.Println(err) 32 | continue 33 | } 34 | 35 | fmt.Println(string(ev.RawData)) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /algorithm/linklist_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import "testing" 4 | 5 | func TestLinkList_Add(t *testing.T) { 6 | linklist := &LinkList{ 7 | nil, nil, 0, 8 | } 9 | linklist.Add(1, 0) 10 | linklist.Add(2, 0) 11 | linklist.Add(3, 0) 12 | linklist.Add(4, 2) 13 | linklist.Add(4, 0) 14 | 15 | t.Log(linklist.Get(0)) 16 | t.Log(linklist.Get(1)) 17 | t.Log(linklist.Get(2)) 18 | t.Log(linklist.Get(3)) 19 | t.Log(linklist.Get(4)) 20 | t.Log("值为1的下标是:", linklist.IndexOfFirst(1)) 21 | t.Log("值为4的下标是:", linklist.IndexOfFirst(4)) 22 | t.Log(linklist.RemoveFirstPop()) 23 | t.Log(linklist.Get(0)) 24 | t.Log(linklist.Get(1)) 25 | t.Log(linklist.Get(2)) 26 | t.Log(linklist.Get(3)) 27 | } 28 | 29 | func TestLinkList_Reverse(t *testing.T) { 30 | list := &LinkList{} 31 | list.AddToFirst(1) 32 | list.AddToFirst(2) 33 | list.AddToFirst(3) 34 | list.Reverse() 35 | list.Print() 36 | } 37 | -------------------------------------------------------------------------------- /basic/chan_study_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import "testing" 4 | 5 | func TestChanStudyClose(t *testing.T) { 6 | ChanStudyClose() 7 | } 8 | 9 | func TestChanStudy1(t *testing.T) { 10 | ChanStudy1() 11 | } 12 | func TestChanStudy1_1(t *testing.T) { 13 | ChanStudy1_1() 14 | } 15 | 16 | func TestChanStudy2(t *testing.T) { 17 | ChanStudy2() 18 | } 19 | func TestChanStudy2_2(t *testing.T) { 20 | ChanStudy2_2() 21 | } 22 | 23 | func TestChanStudy3(t *testing.T) { 24 | ChanStudy3() 25 | } 26 | 27 | func TestReadAndWriteChanStudy(t *testing.T) { 28 | ReadAndWriteChanStudy() 29 | } 30 | 31 | func TestSelectStudy(t *testing.T) { 32 | SelectStudy() 33 | } 34 | 35 | func TestProductAndConsumer(t *testing.T) { 36 | ProductAndConsumer() 37 | } 38 | 39 | func TestStudyChannel10(t *testing.T) { 40 | StudyChannel10() 41 | } 42 | func TestChanClose(t *testing.T) { 43 | ChanClose() 44 | } 45 | -------------------------------------------------------------------------------- /basic/defer_recover_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | /** 8 | 执行顺序,先声明的后执行 9 | */ 10 | func TestDeferStudy(t *testing.T) { 11 | 12 | DeferStudy() 13 | } 14 | 15 | func TestRecoverStudy(t *testing.T) { 16 | t.Log(RecoverStudy()) 17 | } 18 | 19 | func TestRecoverA(t *testing.T) { 20 | l, err := RecoverA() 21 | t.Log("返回结果", l, err) 22 | } 23 | 24 | func TestA(t *testing.T) { 25 | t.Log(A()) 26 | //t.Log(B()) 27 | } 28 | 29 | // BenchmarkNoDefer-8 13953618 79.8 ns/op 30 | // BenchmarkDefer-8 13793086 81.7 ns/op 31 | 32 | // BenchmarkNoDefer-4   15759076     76.8 ns/op 33 | // BenchmarkDefer-4   11046517     105.4 ns/op 34 | func BenchmarkNoDefer(b *testing.B) { 35 | for i := 0; i < b.N; i++ { 36 | NoDefer() 37 | } 38 | } 39 | func BenchmarkDefer(b *testing.B) { 40 | for i := 0; i < b.N; i++ { 41 | Defer() 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /charts/charts_sutdy.go: -------------------------------------------------------------------------------- 1 | package charts 2 | 3 | import ( 4 | "fmt" 5 | "github.com/go-echarts/go-echarts/charts" 6 | "log" 7 | "os" 8 | ) 9 | 10 | //项目网址 11 | //https://go-echarts.github.io/go-echarts/docs/quickstart 12 | 13 | var nameItems = []string{"现状", "目标"} 14 | 15 | func randInt() []float64 { 16 | r := make([]float64, 0) 17 | 18 | for i := 0; i < len(nameItems); i++ { 19 | if i == 0 { 20 | r = append(r, float64(500.0*8/3600)) 21 | } 22 | if i == 1 { 23 | r = append(r, float64(500.0*3/3600)) 24 | } 25 | } 26 | fmt.Println(r) 27 | return r 28 | } 29 | 30 | func BarChartStudy() { 31 | bar := charts.NewBar() 32 | bar.SetGlobalOptions(charts.TitleOpts{Title: "Bar-示例图"}, charts.ToolboxOpts{Show: true}) 33 | bar.AddXAxis(nameItems). 34 | AddYAxis("入仓时间", randInt()) 35 | //生成一个html网页 36 | f, err := os.Create("./bar.html") 37 | if err != nil { 38 | log.Println(err) 39 | } 40 | bar.Render(f) 41 | } 42 | -------------------------------------------------------------------------------- /basic/convert_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import "testing" 4 | 5 | func TestStringType(t *testing.T) { 6 | StringTypeToRuneToByte() 7 | } 8 | 9 | func TestStringToRune(t *testing.T) { 10 | StringToRune() 11 | } 12 | 13 | func TestCustomType(t *testing.T) { 14 | CustomType() 15 | } 16 | 17 | func TestTestStruct(t *testing.T) { 18 | TestStruct() 19 | } 20 | 21 | func TestGetDiCengType(t *testing.T) { 22 | GetDiCengType() 23 | } 24 | 25 | func TestRuneToString(t *testing.T) { 26 | RuneToString() 27 | } 28 | 29 | func TestConvertType(t *testing.T) { 30 | ConvertType() 31 | } 32 | 33 | func TestStrConvertType(t *testing.T) { 34 | StrConvertType() 35 | } 36 | 37 | func TestInterfaceConvertType(t *testing.T) { 38 | InterfaceConvertType() 39 | } 40 | 41 | func TestUintptrAndUnsafe(t *testing.T) { 42 | UintptrAndUnsafe() 43 | } 44 | 45 | func TestUintptrAndPointerStudty(t *testing.T) { 46 | UintptrAndPointerStudty() 47 | } 48 | -------------------------------------------------------------------------------- /algorithm/b_tree.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | /** 4 | 一、B树的定义 5 | B树也称B-树,它是一颗多路平衡查找树。我们描述一颗B树时需要指定它的阶数,阶数表示了一个结点最多有多少个孩子结点,一般用字母m表示阶数。当m取2时,就是我们常见的二叉搜索树。 6 | 一颗m阶的B树定义如下: 7 | 1、每个结点最多有m-1个关键字。 8 | 2、根结点最少可以只有1个关键字。 9 | 3、非根结点至少有Math.ceil(m/2)-1个关键字。 10 | 4、每个结点中的关键字都按照从小到大的顺序排列,每个关键字的左子树中的所有关键字都小于它,而右子树中的所有关键字都大于它。 11 | 5、所有叶子结点都位于同一层,或者说根结点到每个叶子结点的长度都相同 12 | */ 13 | type BT struct { 14 | m int //树的度 15 | parent *BT //指向父节点的指针 16 | keyNum int //每个节点关键字的个数关键字个数 17 | key []int //关键字向量 18 | child []*BT //子树指针向量 19 | } 20 | 21 | /** 22 | m 为树的度数 23 | */ 24 | func NewBTree(m int) *BT { 25 | return &BT{ 26 | m: m, //b树的度 27 | parent: nil, 28 | keyNum: 0, 29 | key: make([]int, m-1, m-1), //每个节点的关键字个数 m/2-1 <= l <= m-1 30 | child: make([]*BT, m, m), //每个节点子节点个数 m/2 <= l <= m 31 | } 32 | } 33 | 34 | func (bt *BT) Insert(key int) bool { 35 | if bt == nil { 36 | return false 37 | } 38 | return true 39 | } 40 | func Split(bt *BT) { 41 | 42 | } 43 | -------------------------------------------------------------------------------- /algorithm/linkqueue.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | type NodeQueue struct { 4 | value interface{} 5 | prev *NodeQueue 6 | next *NodeQueue 7 | } 8 | 9 | /** 10 | 无界队列 11 | */ 12 | type LinkQueue struct { 13 | head *NodeQueue 14 | tail *NodeQueue 15 | size int 16 | } 17 | 18 | func (queue *LinkQueue) Add(value interface{}) { 19 | newNode := &NodeQueue{value, nil, nil} 20 | if queue.head == nil { 21 | queue.head = newNode 22 | queue.tail = newNode 23 | } else { 24 | currentNode := queue.tail 25 | queue.tail = newNode 26 | currentNode.prev = queue.tail 27 | currentNode = nil 28 | } 29 | newNode = nil 30 | queue.size++ 31 | } 32 | 33 | func (queue *LinkQueue) Take() interface{} { 34 | if queue.head == nil { 35 | panic("queue is empty") 36 | } 37 | current := queue.head 38 | prevNode := queue.head.prev 39 | queue.head = prevNode 40 | queue.size-- 41 | prevNode = nil 42 | return current.value 43 | } 44 | func (queue *LinkQueue) Size() int { 45 | return queue.size 46 | } 47 | -------------------------------------------------------------------------------- /grpc/helloworld_demo/server/hello_world_server_register.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "go_common/grpc/helloworld_demo/impl" 5 | pb "go_common/grpc/helloworld_demo/proto" 6 | "go_common/grpc/helloworld_demo/register_center" 7 | "log" 8 | "net" 9 | "time" 10 | 11 | "google.golang.org/grpc" 12 | ) 13 | 14 | func StartServerRegister() { 15 | 16 | lis, err := net.Listen("tcp", "127.0.0.1:8090") 17 | if err != nil { 18 | log.Fatalf("failed to listen: %v", err) 19 | } 20 | 21 | //构造注册中心对象 22 | etcdRegister := register_center.NewEtcdRegisterImpl("127.0.0.1:2379") 23 | 24 | //开始注册 25 | go func() { 26 | for { 27 | etcdRegister.Register(register_center.ServiceDescInfo{ServiceName: "HelloService", 28 | Host: "127.0.0.1", Port: 8090, IntervalTime: time.Duration(10)}) 29 | 30 | time.Sleep(time.Second * 5) 31 | } 32 | }() 33 | 34 | //创建一个grpc服务器对象 35 | gRpcServer := grpc.NewServer() 36 | pb.RegisterHelloServiceServer(gRpcServer, &impl.HelloServiceServer{}) 37 | 38 | //开启服务端 39 | gRpcServer.Serve(lis) 40 | } 41 | -------------------------------------------------------------------------------- /algorithm/linkstack.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | /** 4 | 链表实现栈 5 | */ 6 | 7 | type NodeStack struct { 8 | value interface{} 9 | next *NodeStack 10 | prev *NodeStack 11 | } 12 | type LinkStack struct { 13 | top *NodeStack 14 | size int //栈的大小 15 | } 16 | 17 | func (stack *LinkStack) Push(value interface{}) { 18 | if stack.top == nil { 19 | newNode := &NodeStack{value, nil, nil} 20 | stack.top = newNode 21 | } else { 22 | newNode := &NodeStack{value, nil, nil} 23 | current := stack.top 24 | current.next = newNode 25 | newNode.prev = current 26 | stack.top = newNode 27 | } 28 | stack.size++ 29 | } 30 | 31 | func (stack *LinkStack) Pop() interface{} { 32 | if stack.size == 0 { 33 | panic("stack is empty") 34 | } 35 | current := stack.top 36 | prevNode := current.prev 37 | if prevNode == nil { 38 | stack.size-- 39 | return current.value 40 | } 41 | stack.top = prevNode 42 | prevNode.next = nil 43 | stack.size-- 44 | return current.value 45 | } 46 | 47 | func (stack *LinkStack) Size() int { 48 | return stack.size 49 | } 50 | -------------------------------------------------------------------------------- /array_utils/array_utils_test.go: -------------------------------------------------------------------------------- 1 | package array_utils 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "testing" 7 | ) 8 | 9 | func TestMain(m *testing.M) { 10 | fmt.Println("初始化资源") 11 | result := m.Run() 12 | fmt.Println("释放资源") 13 | os.Exit(result) 14 | } 15 | func TestFindMaxSeqSum(t *testing.T) { 16 | t.Cleanup(func() { 17 | fmt.Println("clear resource") 18 | }) 19 | defer func() { 20 | fmt.Println("defer ") 21 | }() 22 | sum := FindMaxSeqSum([]int{1, 3, -9, 6, 8, -19}) 23 | if sum == 14 { 24 | t.Log("successful") 25 | } else { 26 | t.Error("failed") 27 | } 28 | } 29 | func TestCleanup(t *testing.T) { 30 | defer func() { t.Log("defer resource1") }() 31 | t.Cleanup(func() { 32 | t.Log("clear resource") 33 | }) 34 | defer func() { t.Log("defer resource2") }() 35 | t.Log("test cleanup") 36 | } 37 | func BenchmarkFindMaxSeqSum(b *testing.B) { 38 | for i := 0; i < b.N; i++ { 39 | FindMaxSeqSum([]int{1, 3, -9, 6, 8, -19}) 40 | } 41 | } 42 | 43 | //func ExampleFindMaxSeqSum() { 44 | // FindMaxSeqSum([]int{1, 3, -9, 6, 8, -19}) 45 | // // OutPut: 14 46 | //} 47 | -------------------------------------------------------------------------------- /tools/http_utils_test.go: -------------------------------------------------------------------------------- 1 | package tools 2 | 3 | import ( 4 | "fmt" 5 | "go_common/excel" 6 | "sync" 7 | "testing" 8 | ) 9 | 10 | func TestHttpGetFile(t *testing.T) { 11 | 12 | data, _ := excel.ReadExcel("E://spw.xlsx") 13 | for _, sheet := range data { 14 | for _, row := range sheet { 15 | for celIndex, cel := range row { 16 | if celIndex == 0 { 17 | if cel == "" { 18 | fmt.Println(row[0]) 19 | } else { 20 | fmt.Println(cel) 21 | HttpGetFile(""+cel, "E:\\oss\\") 22 | } 23 | } 24 | } 25 | } 26 | } 27 | } 28 | 29 | func BenchmarkPostRequest(b *testing.B) { 30 | for i := 0; i < b.N; i++ { 31 | go func() { 32 | url := "http://127.0.0.1:8081/api/calculation/theaReplenishment" 33 | PostRequest(url) 34 | }() 35 | } 36 | } 37 | 38 | func TestPostRequest(t *testing.T) { 39 | wg := sync.WaitGroup{} 40 | for i := 0; i < 100; i++ { 41 | wg.Add(1) 42 | go func() { 43 | url := "http://10.112.6.137/cs/api/calculation/theaReplenishment" 44 | PostRequest(url) 45 | wg.Done() 46 | }() 47 | } 48 | wg.Wait() 49 | } 50 | -------------------------------------------------------------------------------- /reptile/colly_study.go: -------------------------------------------------------------------------------- 1 | package reptile 2 | 3 | //爬虫 4 | 5 | import ( 6 | "fmt" 7 | "strings" 8 | 9 | "github.com/gocolly/colly" 10 | ) 11 | 12 | func Start() { 13 | // Instantiate default collector 14 | c := colly.NewCollector() 15 | 16 | // Visit only domains: hackerspaces.org, wiki.hackerspaces.org 17 | c.AllowedDomains = []string{"studygolang.com"} 18 | 19 | // On every a element which has href attribute call callback 20 | c.OnHTML("a[href]", func(e *colly.HTMLElement) { 21 | link := e.Attr("href") 22 | // Print link 23 | if strings.Contains(e.Text, "go") { 24 | fmt.Printf("Link found: %q -> %s\n", e.Text, e.Request.AbsoluteURL(link)) 25 | } 26 | // Visit link found on page 27 | // Only those links are visited which are in AllowedDomains 28 | c.Visit(e.Request.AbsoluteURL(link)) 29 | }) 30 | // Before making a request print "Visiting ..." 31 | //在请求之前打印请求路径 32 | c.OnRequest(func(r *colly.Request) { 33 | //fmt.Println("Visiting", r.URL.String()) 34 | }) 35 | // Start scraping on https://studygolang.com 36 | //开始爬虫 37 | c.Visit("https://studygolang.com") 38 | 39 | } 40 | -------------------------------------------------------------------------------- /go_thinking/prime_number.go: -------------------------------------------------------------------------------- 1 | // 用go思维实现求1-100的质数 2 | package go_thinking 3 | 4 | import "fmt" 5 | 6 | func generate(ch chan<- int) { 7 | for i := 2; i < 100; i++ { 8 | ch <- i // Send 'i' to channel 'ch'. 9 | } 10 | close(ch) 11 | } 12 | func filter(src <-chan int, dst chan<- int) { 13 | prime, ok := <-src 14 | if !ok { 15 | close(dst) 16 | return 17 | } 18 | fmt.Println(prime) 19 | out := make(chan int) 20 | go filter(out, dst) 21 | for num := range src { 22 | if num%prime != 0 { 23 | out <- num 24 | } 25 | } 26 | close(out) 27 | } 28 | 29 | //筛选素数 30 | func Sieve() { 31 | origin, wait := make(chan int), make(chan int) // Create a new channel. 32 | go generate(origin) 33 | go filter(origin, wait) 34 | <-wait 35 | } 36 | 37 | //1-100的质数 38 | func SieveNew(n int) []int { 39 | 40 | result := make([]int, 0) 41 | for i := 2; i <= n; i++ { 42 | if i == 2 { 43 | result = append(result, i) 44 | continue 45 | } 46 | count := 0 47 | for j := 1; j <= i; j++ { 48 | if count > 2 { 49 | break 50 | } 51 | if i%j == 0 { 52 | count++ 53 | } 54 | } 55 | if count == 2 { 56 | result = append(result, i) 57 | } 58 | } 59 | return result 60 | 61 | } 62 | -------------------------------------------------------------------------------- /grpc/helloworld_demo/client/hello_world_client.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | pb "go_common/grpc/helloworld_demo/proto" 7 | "log" 8 | "strconv" 9 | 10 | "google.golang.org/grpc" 11 | ) 12 | 13 | func StartClient() { 14 | 15 | conn, err := grpc.Dial("127.0.0.1:8090", grpc.WithInsecure()) 16 | if err != nil { 17 | fmt.Println(err) 18 | return 19 | } 20 | //创建客户端存根对象 21 | c := pb.NewHelloServiceClient(conn) 22 | 23 | res, err := c.HelloWorld(context.Background(), new(pb.HelloRequest), grpc.EmptyCallOption{}) 24 | 25 | fmt.Println(res, err) 26 | 27 | //客户端发起调用,返回一个流 28 | r, err := c.HelloWorldClientAndServerStream(context.Background(), grpc.EmptyCallOption{}) 29 | if err != nil { 30 | log.Fatalf("%v", err) 31 | return 32 | } 33 | //用流给服务端发送消息 34 | for i := 0; i < 10; i++ { 35 | r.Send(&pb.HelloRequest{Request: "my is golang gRpc client " + strconv.Itoa(i)}) 36 | } 37 | //流关闭 38 | r.CloseSend() 39 | for { 40 | res, err := r.Recv() 41 | if err != nil && err.Error() == "EOF" { 42 | break 43 | } 44 | if err != nil { 45 | log.Fatalf("%v", err) 46 | break 47 | } 48 | log.Printf("result:%v", res.Response) 49 | } 50 | defer conn.Close() 51 | } 52 | -------------------------------------------------------------------------------- /basic/point_study.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func PointStudy() { 8 | var pointInt1 = 1 9 | 10 | fmt.Println(pointInt1) 11 | //Go 语言的取地址符是 &,放到一个变量前使用就会返回相应变量的内存地址。 12 | fmt.Println(&pointInt1) 13 | 14 | // 使用指针 15 | var pointInt2 *int // 声明一个指针 16 | var pointInt3 = 1 //声明一个实际变量 17 | pointInt2 = &pointInt3 18 | 19 | // & 打印出来的是内存地址 * 打印出来的是值 20 | fmt.Println(pointInt2) 21 | fmt.Println(*pointInt2) 22 | 23 | // 指针数组 24 | var arrayPointInt1 [10]*int 25 | for i := 0; i < len(arrayPointInt1); i++ { 26 | arrayPointInt1[i] = &i //给数组赋值 27 | } 28 | fmt.Println(arrayPointInt1) 29 | 30 | for _, value := range arrayPointInt1 { 31 | fmt.Println(*value) //打印数组值 32 | } 33 | var x, y *int 34 | var c, d = 1, 1 35 | x, y = &c, &d 36 | pointMethod(x, y) 37 | 38 | } 39 | 40 | // 指针函数 41 | 42 | func pointMethod(x, y *int) { 43 | fmt.Println(x == nil) 44 | fmt.Println(y == nil) 45 | fmt.Println(*x + *y) 46 | } 47 | 48 | func SlicePointStudy() { 49 | slice := make([]int, 0, 0) 50 | slice = slicePoint(slice) 51 | fmt.Println(slice) 52 | } 53 | func slicePoint(slice []int) []int { 54 | for i := 0; i < 5; i++ { 55 | slicePoint(slice) 56 | } 57 | return slice 58 | 59 | } 60 | -------------------------------------------------------------------------------- /basic/httptest_study_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "net/http" 7 | "net/http/httptest" 8 | "testing" 9 | ) 10 | 11 | var personResponse = []PersonNew{ 12 | { 13 | Name: "wahaha", 14 | Address: "shanghai", 15 | Age: 20, 16 | }, 17 | { 18 | Name: "lebaishi", 19 | Address: "shanghai", 20 | Age: 10, 21 | }, 22 | } 23 | 24 | var personResponseBytes, _ = json.Marshal(personResponse) 25 | 26 | func TestPublishWrongResponseStatus(t *testing.T) { 27 | ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 28 | w.WriteHeader(http.StatusOK) 29 | w.Write(personResponseBytes) 30 | if r.Method != "GET" { 31 | t.Errorf("Expected 'GET' request, got '%s'", r.Method) 32 | } 33 | if r.URL.EscapedPath() != "/person" { 34 | t.Errorf("Expected request to '/person', got '%s'", r.URL.EscapedPath()) 35 | } 36 | r.ParseForm() 37 | topic := r.Form.Get("addr") 38 | if topic != "shanghai" { 39 | t.Errorf("Expected request to have 'addr=shanghai', got: '%s'", topic) 40 | } 41 | })) 42 | 43 | defer ts.Close() 44 | api := ts.URL 45 | fmt.Println("url:", api) 46 | resp, _ := GetInfo(api) 47 | 48 | fmt.Println("reps:", resp) 49 | } 50 | -------------------------------------------------------------------------------- /algorithm/int_heap.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | type IntHeap []int 4 | 5 | func (h IntHeap) Len() int { 6 | return len(h) 7 | } 8 | 9 | func (h IntHeap) Less(i, j int) bool { 10 | return h[i] < h[j] 11 | } 12 | 13 | func (h IntHeap) Swap(i, j int) { 14 | h[i], h[j] = h[j], h[i] 15 | } 16 | 17 | /** 18 | 构造一个小顶堆 ,数组下标为0的元素始终是最小的 19 | */ 20 | func (h *IntHeap) Push(x interface{}) { 21 | 22 | *h = append(*h, x.(int)) 23 | l := len(*h) - 1 24 | for (l-1)/2 >= 0 && (*h)[l] < (*h)[(l-1)/2] { 25 | h.Swap(l, (l-1)/2) 26 | l = (l - 1) / 2 27 | } 28 | } 29 | 30 | /** 31 | 返回堆顶的一个元素,并删除,重新调整堆,保证堆定的元素始终是最小的 32 | */ 33 | func (h *IntHeap) Pop() interface{} { 34 | if h.Len() == 0 { 35 | return nil 36 | } 37 | x := (*h)[0] 38 | if h.Len() == 1 { 39 | h = &IntHeap{} 40 | return x 41 | } 42 | (*h)[0] = (*h)[h.Len()-1] 43 | *h = (*h)[0 : h.Len()-1] 44 | adjustHelp(h) 45 | return x 46 | } 47 | 48 | func adjustHelp(h *IntHeap) { 49 | min := 0 50 | for i := 0; i < h.Len(); { 51 | if i*2+1 < h.Len() && !h.Less(i, i*2+1) { //顶节点 > 左节点 52 | min = i*2 + 1 53 | } 54 | if i*2+2 < h.Len() && h.Less(i*2+2, i*2+1) { //右节点 < 左节点 55 | min = i*2 + 2 56 | } 57 | if min == i { 58 | break 59 | } 60 | h.Swap(i, min) 61 | i = min 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /basic/goroutine_study.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import "fmt" 4 | 5 | func GoRoutineStudy() { 6 | fmt.Println("goroutine test") 7 | pages1 := make([]int, 50) 8 | pages2 := make([]int, 50) 9 | for i := 0; i < cap(pages1); i++ { 10 | pages1[i] = i * 2 11 | } 12 | for i := 0; i < cap(pages2); i++ { 13 | pages2[i] = i*2 + 1 14 | } 15 | pageSlice := make([]interface{}, 2) 16 | pageSlice[0] = pages1 17 | pageSlice[1] = pages2 18 | var channel chan string = make(chan string, 2) 19 | for i := 0; i < 2; i++ { 20 | // interface 类型到其他类型的转换 pageSlice[i].([]int) 21 | go findByPage(pageSlice[i].([]int), channel) 22 | } 23 | // 直到协成跑完取到消息 24 | for { 25 | message, ok := <-channel 26 | if !ok { 27 | break 28 | } 29 | fmt.Println(message) 30 | } 31 | } 32 | 33 | func findByPage(pages []int, channel chan string) { 34 | for i := 0; i < len(pages); i++ { 35 | fmt.Printf("查询第 %d 页成功\n", pages[i]) 36 | } 37 | channel <- "查询完毕" 38 | close(channel) 39 | } 40 | func StartGoRouting2() { 41 | channel := make(chan string, 1) 42 | 43 | go findByPage([]int{1, 2, 3}, channel) 44 | 45 | message, ok := <-channel 46 | if ok { 47 | fmt.Println(message) 48 | } 49 | } 50 | 51 | func StartGoRoutine2() { 52 | go func() { 53 | fmt.Println("start goroutines") 54 | }() 55 | } 56 | -------------------------------------------------------------------------------- /basic/json_study_test.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "testing" 7 | "time" 8 | ) 9 | 10 | var stu = &Student{ 11 | Id: 100001, 12 | Name: "sunpengwei", 13 | Age: 26, 14 | Phone: "18091772262", 15 | Score: map[string]float32{"语文": 99.12, "数学": 100}, 16 | Birthday: JsonTime(time.Now()), 17 | } 18 | 19 | func TestToJson(t *testing.T) { 20 | log.Println(ToJson(stu)) 21 | } 22 | 23 | var stuESC = &Student{ 24 | Id: 100001, 25 | Name: "", 26 | Age: 26, 27 | Phone: "18091772262", 28 | Score: map[string]float32{"语文": 99.12, "数学": 100}, 29 | Birthday: JsonTime(time.Now()), 30 | } 31 | 32 | func TestToJsonSkipESC(t *testing.T) { 33 | log.Println(ToJsonSkipESC(stuESC)) 34 | } 35 | 36 | func TestFromJson(t *testing.T) { 37 | jsonStr, err := ToJson(stu) 38 | if err != nil { 39 | log.Fatalln(err) 40 | } 41 | result := &Student{} 42 | err = FromJson([]byte(jsonStr), result) 43 | if err != nil { 44 | log.Fatalln(err) 45 | } 46 | fmt.Println(result) 47 | } 48 | 49 | func TestJsonMap(t *testing.T) { 50 | JsonMap() 51 | } 52 | 53 | func TestJsonGetValueByKey(t *testing.T) { 54 | JsonGetValueByKey() 55 | } 56 | 57 | func TestSimpleJsonStudy(t *testing.T) { 58 | SimpleJsonStudy() 59 | } 60 | -------------------------------------------------------------------------------- /algorithm/array_lru.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | /** 4 | 用数组实现LRU(最近最少使用)算法 5 | */ 6 | const DATA_SIZE = 10 7 | 8 | type LRUArray struct { 9 | //存储缓存的key 10 | keys []string 11 | //存储缓存的value 12 | values []string 13 | //下标值 14 | maxIndex int 15 | } 16 | 17 | func (lru *LRUArray) Put(key, value string) { 18 | if lru.keys == nil || lru.values == nil { 19 | lru.keys = make([]string, DATA_SIZE) 20 | lru.values = make([]string, DATA_SIZE) 21 | lru.maxIndex = DATA_SIZE - 1 22 | } 23 | // 缓存满了,需要淘汰 24 | if lru.maxIndex < 0 { 25 | i := len(lru.keys) / 2 26 | l := len(lru.keys) - 1 27 | for j := i; j >= 0; j-- { 28 | lru.keys[l] = lru.keys[j] 29 | lru.values[l] = lru.values[j] 30 | l-- 31 | } 32 | lru.maxIndex = len(lru.keys) - (i + 2) 33 | } 34 | lru.keys[lru.maxIndex] = key 35 | lru.values[lru.maxIndex] = value 36 | lru.maxIndex-- 37 | } 38 | 39 | func (lru *LRUArray) Get(key string) string { 40 | for i := lru.maxIndex; i < len(lru.keys); i++ { 41 | if key == lru.keys[i] { 42 | v := lru.values[i] 43 | j := i 44 | for j > lru.maxIndex+1 { 45 | lru.keys[j] = lru.keys[j-1] 46 | lru.values[j] = lru.values[j-1] 47 | j-- 48 | } 49 | lru.keys[j] = key 50 | lru.values[j] = v 51 | return v 52 | } 53 | } 54 | return "" 55 | } 56 | -------------------------------------------------------------------------------- /grpc/helloworld_demo/server/hello_world_server_token.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | "fmt" 7 | "go_common/grpc/helloworld_demo/impl" 8 | pb "go_common/grpc/helloworld_demo/proto" 9 | "log" 10 | "net" 11 | 12 | "google.golang.org/grpc" 13 | "google.golang.org/grpc/codes" 14 | "google.golang.org/grpc/metadata" 15 | ) 16 | 17 | // 服务端方法实现中调用check方法校验 18 | func check(ctx context.Context) error { 19 | md, ok := metadata.FromIncomingContext(ctx) 20 | if !ok { 21 | return errors.New("没有token细腻些") 22 | } 23 | 24 | fmt.Println(md, ok) 25 | var ( 26 | appid string 27 | appkey string 28 | ) 29 | if val, ok := md["appid"]; ok { 30 | appid = val[0] 31 | } 32 | if val, ok := md["appkey"]; ok { 33 | appkey = val[0] 34 | } 35 | if appid != "123" || appkey != "456" { 36 | return grpc.Errorf(codes.Unauthenticated, "Token认证信息无效: appid=%s, appkey=%s", appid, appkey) 37 | } 38 | fmt.Println(appid, appkey) 39 | return nil 40 | } 41 | func StartServerToken() { 42 | 43 | lis, err := net.Listen("tcp", "127.0.0.1:8090") 44 | if err != nil { 45 | log.Fatalf("failed to listen: %v", err) 46 | } 47 | 48 | gRpcServer := grpc.NewServer() 49 | pb.RegisterHelloServiceServer(gRpcServer, &impl.HelloServiceServer{}) 50 | gRpcServer.Serve(lis) 51 | } 52 | -------------------------------------------------------------------------------- /algorithm/load_balance.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | type SeverWeight struct { 4 | //配置的权重 5 | ConfigWeight int 6 | //当前权重 7 | CurrentWeight int 8 | //有效权重 9 | EffectiveWeight int 10 | //服务器ip 11 | Ip string 12 | } 13 | 14 | //加权轮询算法 15 | type WeightedRoundRobin struct { 16 | //机器ip和对应的权重 17 | IpAndWeightedConfig map[string]int 18 | //服务器和权重信息 19 | SwSlice []*SeverWeight 20 | } 21 | 22 | func NewWeightedRoundRobin(iwc map[string]int) *WeightedRoundRobin { 23 | if iwc == nil { 24 | return nil 25 | } 26 | SwSlice := make([]*SeverWeight, 0) 27 | for k, v := range iwc { 28 | sw := &SeverWeight{ConfigWeight: v, CurrentWeight: 0, EffectiveWeight: v, Ip: k} 29 | SwSlice = append(SwSlice, sw) 30 | } 31 | return &WeightedRoundRobin{IpAndWeightedConfig: iwc, SwSlice: SwSlice} 32 | } 33 | func (wrr *WeightedRoundRobin) Select() (sw *SeverWeight) { 34 | total := 0 35 | for _, v := range wrr.SwSlice { 36 | v.CurrentWeight += v.EffectiveWeight 37 | total += v.EffectiveWeight 38 | if v.EffectiveWeight < v.ConfigWeight { 39 | v.EffectiveWeight++ 40 | } 41 | if sw == nil || v.CurrentWeight > sw.CurrentWeight { 42 | sw = v 43 | } 44 | } 45 | sw.CurrentWeight = sw.CurrentWeight - total 46 | return sw 47 | } 48 | 49 | //一致性hash算法 50 | type ConsistencyHash struct { 51 | } 52 | -------------------------------------------------------------------------------- /grpc/helloworld_demo/client/hello_world_client_tls.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | pb "go_common/grpc/helloworld_demo/proto" 7 | "log" 8 | "strconv" 9 | "time" 10 | 11 | "google.golang.org/grpc" 12 | "google.golang.org/grpc/credentials" 13 | ) 14 | 15 | func StartClientTLS() { 16 | // TLS认证 17 | creds, err := credentials.NewClientTLSFromFile("E:\\server.pem", "") 18 | 19 | conn, err := grpc.Dial("127.0.0.1:8090", grpc.WithTransportCredentials(creds)) 20 | if err != nil { 21 | fmt.Println(err) 22 | return 23 | } 24 | c := pb.NewHelloServiceClient(conn) 25 | // Contact the server and print out its response. 26 | ctx, cancel := context.WithTimeout(context.Background(), time.Second) 27 | defer cancel() 28 | r, err := c.HelloWorldClientAndServerStream(ctx, grpc.EmptyCallOption{}) 29 | if err != nil { 30 | log.Fatalf("%v", err) 31 | return 32 | } 33 | for i := 0; i < 10; i++ { 34 | r.Send(&pb.HelloRequest{Request: "my is golang gRpc client " + strconv.Itoa(i)}) 35 | } 36 | r.CloseSend() 37 | for { 38 | res, err := r.Recv() 39 | if err != nil && err.Error() == "EOF" { 40 | break 41 | } 42 | if err != nil { 43 | log.Fatalf("%v", err) 44 | break 45 | } 46 | log.Printf("result:%v", res.Response) 47 | } 48 | defer conn.Close() 49 | } 50 | -------------------------------------------------------------------------------- /grpc/helloworld_demo/client/hello_world_client_token.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | pb "go_common/grpc/helloworld_demo/proto" 7 | "log" 8 | "time" 9 | 10 | "google.golang.org/grpc" 11 | ) 12 | 13 | //自定义认证,实现 PerRPCCredentials 接口 14 | type CustomerCredsAuth struct { 15 | } 16 | 17 | //获取元数据 18 | func (c CustomerCredsAuth) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { 19 | return map[string]string{ 20 | "appid": "123", 21 | "appkey": "456", 22 | }, nil 23 | } 24 | 25 | //是否开启传输安全 26 | func (c CustomerCredsAuth) RequireTransportSecurity() bool { 27 | return false 28 | } 29 | 30 | func StartClientToken() { 31 | var opts []grpc.DialOption 32 | opts = append(opts, grpc.WithInsecure()) 33 | opts = append(opts, grpc.WithPerRPCCredentials(new(CustomerCredsAuth))) 34 | 35 | conn, err := grpc.Dial("127.0.0.1:8090", opts...) 36 | if err != nil { 37 | fmt.Println(err) 38 | return 39 | } 40 | c := pb.NewHelloServiceClient(conn) 41 | // Contact the server and print out its response. 42 | ctx, cancel := context.WithTimeout(context.Background(), time.Second) 43 | defer cancel() 44 | r, err := c.HelloWorld(ctx, &pb.HelloRequest{}) 45 | if err != nil { 46 | log.Fatalf("%v", err) 47 | return 48 | } 49 | fmt.Println(r.Response) 50 | defer conn.Close() 51 | } 52 | -------------------------------------------------------------------------------- /algorithm/tree.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "container/list" 5 | ) 6 | 7 | type TreeNode struct { 8 | Val int 9 | Left *TreeNode 10 | Right *TreeNode 11 | } 12 | 13 | /** 14 | 获取二叉树的最小深度 15 | */ 16 | func MinDepth(root *TreeNode) int { 17 | if root == nil { 18 | return 0 19 | } 20 | queue := list.New() 21 | queue.PushBack(*root) 22 | minDepth := 0 23 | for queue.Len() > 0 { 24 | newQueue := list.New() 25 | minDepth++ 26 | for queue.Len() > 0 { 27 | e := queue.Front() 28 | queue.Remove(e) 29 | tempTree := e.Value.(TreeNode) 30 | if tempTree.Left == nil && tempTree.Right == nil { 31 | return minDepth 32 | } 33 | if tempTree.Left != nil { 34 | newQueue.PushBack(*tempTree.Left) 35 | } 36 | if tempTree.Right != nil { 37 | newQueue.PushBack(*tempTree.Right) 38 | } 39 | } 40 | queue.PushBackList(newQueue) 41 | } 42 | return minDepth 43 | } 44 | 45 | func LevelOrder(root *TreeNode) [][]int { 46 | res := make([][]int, 0, 0) 47 | res = order(root, res, 0) 48 | return res 49 | } 50 | 51 | func order(root *TreeNode, res [][]int, level int) [][]int { 52 | 53 | if root == nil { 54 | return res 55 | } 56 | if len(res)-1 < level { 57 | res = append(res, make([]int, 0, 0)) 58 | } 59 | res[level] = append(res[level], root.Val) 60 | res = order(root.Left, res, level+1) 61 | res = order(root.Right, res, level+1) 62 | return res 63 | } 64 | -------------------------------------------------------------------------------- /blockchain/blockchain.go: -------------------------------------------------------------------------------- 1 | package blockchain 2 | 3 | import ( 4 | "bytes" 5 | "crypto/sha256" 6 | "strconv" 7 | "time" 8 | ) 9 | 10 | /** 11 | 一个简单的区块链 12 | */ 13 | type Block struct { 14 | Timestamp int64 15 | Data []byte 16 | PrevBlockHash []byte 17 | Hash []byte 18 | } 19 | 20 | type BlockChain struct { 21 | blocks []*Block 22 | } 23 | 24 | func newBlock(data string, prevBlockHash []byte) *Block { 25 | block := &Block{ 26 | time.Now().Unix(), 27 | []byte(data), 28 | prevBlockHash, 29 | []byte{}, 30 | } 31 | block.setHash() 32 | return block 33 | } 34 | 35 | /** 36 | 给区块设置hash值 37 | */ 38 | func (b *Block) setHash() { 39 | timestamp := []byte(strconv.FormatInt(b.Timestamp, 10)) 40 | headers := bytes.Join([][]byte{b.PrevBlockHash, b.Data, timestamp}, []byte{}) 41 | hash := sha256.Sum256(headers) 42 | b.Hash = hash[:] 43 | } 44 | 45 | /** 46 | 添加一个新的区块 47 | */ 48 | func (blockChain *BlockChain) AddBlock(data string) { 49 | preBlock := blockChain.blocks[len(blockChain.blocks)-1] 50 | newBlock := newBlock(data, preBlock.Hash) 51 | blockChain.blocks = append(blockChain.blocks, newBlock) 52 | } 53 | 54 | /** 55 | 创始快 56 | */ 57 | func NewGenesisBlock() *Block { 58 | return newBlock("Genesis Block创始块", []byte{}) 59 | } 60 | 61 | /** 62 | 用创始块创建一个区块链函数 63 | */ 64 | func NewBlockChain() *BlockChain { 65 | return &BlockChain{ 66 | []*Block{NewGenesisBlock()}, 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /excel/read_and_write_excel_test.go: -------------------------------------------------------------------------------- 1 | package excel 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "strconv" 7 | "testing" 8 | ) 9 | 10 | func TestReadExcel(t *testing.T) { 11 | sql := "insert into io_1_201809 " + 12 | "(status, exp_date, cky_no, store_no, action_code, record_type, job_no, exp_no, goods_no, qty, " + 13 | " action_time, service_type, region_no, data_source, yn, create_time) values" 14 | var buf bytes.Buffer 15 | data, err := ReadExcel("E:\\test\\10166_2018-06-01-2018-06-30_BillingDetail1.xls") 16 | if err != nil { 17 | fmt.Println("excel读取失败", err) 18 | return 19 | } 20 | for i := 0; i < len(data); i++ { 21 | for j := 0; j < len(data[i]); j++ { 22 | for m := 0; m < len(data[i][j]); m++ { 23 | if m == 0 { 24 | buf.WriteString("(0," + "'" + data[i][j][m] + "'" + ",") 25 | } else if m == 9 { 26 | buf.WriteString("'" + data[i][j][m] + "',1,30,'bi_50_2',1,now()),") 27 | } else { 28 | buf.WriteString("'" + data[i][j][m] + "',") 29 | } 30 | } 31 | } 32 | } 33 | sql = sql + buf.String() 34 | t.Log(sql[0 : len(sql)-1]) 35 | } 36 | 37 | func TestUnZipFile(t *testing.T) { 38 | for i := 2; i <= 9; i++ { 39 | if i != 4 { 40 | UnZipFile("E:\\oss\\"+strconv.Itoa(i)+"\\", "E://oss_oss//"+strconv.Itoa(i)+"//") 41 | } 42 | } 43 | } 44 | 45 | func TestWriteExcel(t *testing.T) { 46 | 47 | WriteExcel([][]string{{"123", "456"}, {"789", "000"}}, "E:\\test.xlsx") 48 | } 49 | -------------------------------------------------------------------------------- /basic/http_study.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "io/ioutil" 7 | "log" 8 | "net/http" 9 | "net/http/cookiejar" 10 | "net/url" 11 | "os" 12 | "strings" 13 | ) 14 | 15 | func HttpGet() { 16 | 17 | res, err := http.Get("http://www.baidu.com") 18 | checkErr(err) 19 | //将http请求相应的内容复制到标准输出(控制台) 20 | io.Copy(os.Stdout, res.Body) 21 | defer res.Body.Close() 22 | } 23 | 24 | func HttpPort() { 25 | res, err := http.Post("http://www.baidu.com", 26 | "application/x-www-form-urlencoded", strings.NewReader("name=spw&pwd=123")) 27 | checkErr(err) 28 | io.Copy(os.Stdout, res.Body) 29 | defer res.Body.Close() 30 | } 31 | 32 | func HttpPortForm() { 33 | res, err := http.PostForm("http://wwww.baidu.com", url.Values{"name": {"spw"}, "pwd": {"123"}}) 34 | checkErr(err) 35 | io.Copy(os.Stdout, res.Body) 36 | defer res.Body.Close() 37 | } 38 | 39 | func HttpDo() { 40 | client := &http.Client{} 41 | jar, err := cookiejar.New(nil) 42 | checkErr(err) 43 | request, err := http.NewRequest("port", "http://www.baidu.com", strings.NewReader("name=spw&pwd=123")) 44 | checkErr(err) 45 | request.Header.Set("Content-Type", "application/x-www-form-urlencoded") 46 | client.Jar = jar 47 | resp, err := client.Do(request) 48 | body, err := ioutil.ReadAll(resp.Body) 49 | checkErr(err) 50 | fmt.Println(string(body)) 51 | defer resp.Body.Close() 52 | 53 | } 54 | 55 | func checkErr(err error) { 56 | if err != nil { 57 | log.Fatal("http err:", err) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /algorithm/时间空间复杂度笔记: -------------------------------------------------------------------------------- 1 | #### 算法的时间复杂度和空间复杂度称为算法的复杂度 2 | 时间复杂度 3 | 4 | 可以理解为一个算法在执行一个规模为n的问题时,所需要的时间,这个n可以理解一个函数的入参,比如排序时,n就是待排序的数组的大小 5 | 但实际上,一个算法的执行的时间从理论上是无法算出来的,除非上机测试,但是我们不可能也没必要对每一个改动,每一个算法都进行实际测试, 6 | 一个算法时间复杂度本质上与这个算法解决这个规模n的问题时所执行的语句次数有关系,而这个执行所需的次数是问题规模n的某个函数 7 | 8 | 我们假设问题规模为n , 算法解决这个规模n的问题需要的时间用函数 T(n) 表示 9 | 若存在一个辅助函数 f(n) ,使得 n趋于无穷大时, T(n) / f(n) 约等于一个不为0的常数 则f(n) 是 T(n) 的同数量级函数 10 | 记做 T(n) = O(f(n)) ,则称 O(f(n)) 为算法的渐进时间复杂度 11 | 常见的时间复杂度 有 O(1)常数阶 O(n)线性阶 O(log2n)对数阶 O(nlog2n)n倍对数阶 O(n2)平方阶 O(n3) 立方阶 O(2n) 指数阶 12 | O(1)指的是算法的时间复杂度不随着问题规模n的增加而增长,执行时间不过一个较大的常数 13 | 时间复杂度是总运算次数表达式中受n的变化影响最大的那一项(不含系数) 14 | 15 | 时间复杂度的常见分类 16 | 最好时间复杂度 17 | 最坏时间复杂度 18 | 平均时间复杂度(加权平均值) 19 | 均摊时间复杂度(一种特殊的平均时间复杂度) 20 | 时间复杂度常见的分析方法 21 | 只关注循环执行次数最多的一段代码 22 | 加法法则:总的时间复杂度等于量级最大的那段代码的时间复杂度 23 | 乘法法则:嵌套代码的复杂度等于嵌套内外代码复杂度的乘积 24 | 摊还分析法:把耗时最多的那次平均分摊在截下来的n次中 25 | 26 | 还有一种时间复杂度是由两个数据规模来决定的: 27 | O(m+n) 28 | O(m*n) 29 | 30 | 31 | 空间复杂度 32 | 33 | 可以理解为对一个算法在执行规模为n的问题时临时占用的存储空间的大小 记做 S(n) = O(f(n)) 34 | 关于O(1)的问题, O(1)是说数据规模和临时变量数目无关,并不是说仅仅定义一个临时变量。举例:无论数据规模多大,我都定义100个变量,这就叫做数据规模和临时变量数目无关。就是说空间复杂度是O(1) 35 | 36 | -------------------------------------------------------------------------------- /document/linux下安装go11: -------------------------------------------------------------------------------- 1 | 2 | ### linux 下载安装go1.11 3 | 1、下载 wget https://dl.google.com/go/go1.11.linux-amd64.tar.gz 4 | 2、解压 tar xf go1.11.linux-amd64.tar.gz 5 | 3、设置环境变量 6 | vi /etc/profile 7 | export GO111MODULE=on 8 | export GOROOT=/root/go 安装路径 9 | export PATH=$PATH:$GOROOT/bin 10 | source /etc/profile 11 | 4、验证是否成功 12 | go env 13 | 14 | ### 关于$GOPROXY 15 | 当我们使用go的时候,go默认会直接从代码库中去下载所需的相关依赖,GOPROXY 这个环境变量可以让我们控制自己从哪里去下载源代码,如果 GOPROXY 没有设置,go 会直接从代码库下载相关依赖代码。如果你像下面这样设置了这个环境变量,那么你就会通过 goproxy.io 下载所有的源代码。 16 | export GOPROXY=https://goproxy.io 17 | 你可以通过置空这个环境变量来关闭,export GOPROXY= 18 | 如果要开机、全局生效的就要在/etc/profile中也加入即可。 19 | 查看当前系统中的变量,这里过滤GO的配置 20 | export|grep "GO" 21 | declare -x GO111MODULE="on" 22 | declare -x GOPROXY="https://goproxy.io" 23 | declare -x GOROOT="/root/go/go.11" 24 | 25 | goproxy.io 是一个开源项目,当用户请求一个依赖库时,如果它发现本地没有这份代码就会自动请求源,然后cache到本地,用户就可以从 goproxy.io 请求到数据。当然, 26 | 这些都是在一个请求中完成的。goproxy.io 只支持 go module 模式。当用户执行 go get 命令时,会去检查$GOPROXY//@v/list这个文件中是否有用户想要获取的版本,如果有,就依次获取 $GOPROXY//@v/.info、$GOPROXY//@v/.mod、$GOPROXY//@v/.zip 等文件,如果没有就直接从源码库中去下载。 27 | 得益于 go module 在设计的时候非常重视安全这个领域,所以在启用了 go module 后,你会发现除了 go.mod 这个文件之外,还有一个 go.sum 文件,这个文件保存了每个依赖库的对应的hash值, 28 | 来保证下载回来的代码库是正确的,不被人篡改的。同时, goproxy.io 也是个开源的项目。可以自行部署到自己的IDC中,因为公司内部自己的代码库 goproxy.io 是无法访问到的。 29 | 开源地址:https://github.com/goproxyio/goproxy -------------------------------------------------------------------------------- /grpc/helloworld_demo/client/hello_world_client_register.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | pb "go_common/grpc/helloworld_demo/proto" 7 | "go_common/grpc/helloworld_demo/register_center" 8 | "log" 9 | "strconv" 10 | 11 | "google.golang.org/grpc/balancer/roundrobin" 12 | 13 | "google.golang.org/grpc" 14 | ) 15 | 16 | func StartClientRegister() { 17 | 18 | //连接etcd,得到名命名空间 19 | schema, err := register_center.GenerateAndRegisterEtcdResolver("127.0.0.1:2379", "HelloService") 20 | if err != nil { 21 | log.Fatal("init etcd resolver err:", err.Error()) 22 | } 23 | conn, err := grpc.Dial(fmt.Sprintf("%s:///HelloService", schema), grpc.WithInsecure(), grpc.WithBalancerName(roundrobin.Name)) 24 | if err != nil { 25 | fmt.Println(err) 26 | return 27 | } 28 | //创建客户端存根对象 29 | c := pb.NewHelloServiceClient(conn) 30 | //客户端发起调用,返回一个流 31 | r, err := c.HelloWorldClientAndServerStream(context.Background(), grpc.EmptyCallOption{}) 32 | if err != nil { 33 | log.Fatalf("%v", err) 34 | return 35 | } 36 | //用流给服务端发送消息 37 | for i := 0; i < 10; i++ { 38 | r.Send(&pb.HelloRequest{Request: "my is golang gRpc client " + strconv.Itoa(i)}) 39 | } 40 | //流关闭 41 | r.CloseSend() 42 | 43 | //接受服务端返回的消息 44 | for { 45 | res, err := r.Recv() 46 | if err != nil && err.Error() == "EOF" { 47 | break 48 | } 49 | if err != nil { 50 | log.Fatalf("%v", err) 51 | break 52 | } 53 | log.Printf("result:%v", res.Response) 54 | } 55 | defer conn.Close() 56 | } 57 | -------------------------------------------------------------------------------- /basic/httptest_study.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io/ioutil" 7 | "net/http" 8 | ) 9 | 10 | const ( 11 | ADDRESS = "shanghai" 12 | ) 13 | 14 | type PersonNew struct { 15 | Name string `json:"name"` 16 | Address string `json:"address"` 17 | Age int `json:"age"` 18 | } 19 | 20 | func GetInfo(api string) ([]PersonNew, error) { 21 | url := fmt.Sprintf("%s/person?addr=%s", api, ADDRESS) 22 | resp, err := http.Get(url) 23 | defer resp.Body.Close() 24 | if err != nil { 25 | return []PersonNew{}, err 26 | } 27 | if resp.StatusCode != http.StatusOK { 28 | return []PersonNew{}, fmt.Errorf("get info didn’t respond 200 OK: %s", resp.Status) 29 | } 30 | bodyBytes, _ := ioutil.ReadAll(resp.Body) 31 | personList := make([]PersonNew, 0) 32 | err = json.Unmarshal(bodyBytes, &personList) 33 | if err != nil { 34 | return []PersonNew{}, fmt.Errorf("decode data fail") 35 | } 36 | return personList, nil 37 | } 38 | 39 | //解释一下: 40 | // 41 | //>我们通过httptest.NewServer创建了一个测试的http server 42 | // 43 | //>读请求设置通过变量r *http.Request,写变量(也就是返回值)通过w http.ResponseWriter 44 | // 45 | //>通过ts.URL来获取请求的URL(一般都是) 46 | // 47 | //>通过r.Method来获取请求的方法,来测试判断我们的请求方法是否正确 48 | // 49 | //>获取请求路径:r.URL.EscapedPath(),本例中的请求路径就是"/person" 50 | // 51 | //>获取请求参数:r.ParseForm,r.Form.Get("addr") 52 | // 53 | //>设置返回的状态码:w.WriteHeader(http.StatusOK) 54 | // 55 | //>设置返回的内容(这就是我们想要的结果):w.Write(personResponseBytes),注意w.Write()接收的参数是[]byte,因此需要将object对象列表通过json.Marshal(personResponse)转换成字节。 56 | -------------------------------------------------------------------------------- /basic/buffer_study.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "bufio" 5 | "bytes" 6 | "fmt" 7 | "strings" 8 | ) 9 | 10 | func BytesStudy() { 11 | buffer := bytes.Buffer{} 12 | 13 | buffer.WriteString("sunpeng") 14 | buffer.WriteString("wei") 15 | readbytes := make([]byte, 3, 3) 16 | //读取buffer 中的数据 17 | buffer.Read(readbytes) 18 | fmt.Println(buffer.String()) 19 | fmt.Println(string(readbytes)) 20 | 21 | buffer1 := bytes.NewBuffer(make([]byte, 1, 1)) 22 | buffer1.WriteString("spw") 23 | fmt.Println(buffer1.String()) 24 | 25 | //创建一个read 26 | read := bytes.NewReader([]byte("sunpengwei")) 27 | bs := make([]byte, 3) 28 | //将read 中的数据读取到这个数组中 29 | read.Read(bs) 30 | fmt.Println(string(bs)) 31 | 32 | } 33 | 34 | func BufferStudy() { 35 | 36 | read := bufio.NewReader(strings.NewReader("sunpengwei")) 37 | // ReadLine 是一个低级的原始的行读取操作 38 | // 大多数情况下,应该使用 ReadBytes('\n') 或 ReadString('\n') 39 | // 或者使用一个 Scanner 40 | // 41 | // ReadLine 通过调用 ReadSlice 方法实现,返回的也是缓存的切片 42 | // ReadLine 尝试返回一个单行数据,不包括行尾标记(\n 或 \r\n) 43 | // 如果在缓存中找不到行尾标记,则设置 isPrefix 为 true,表示查找未完成 44 | // 同时读出缓存中的数据并作为切片返回 45 | // 只有在当前缓存中找到行尾标记,才将 isPrefix 设置为 false,表示查找完成 46 | // 可以多次调用 ReadLine 来读出一行 47 | // 返回的数据在下一次读取操作之前是有效的 48 | // 如果 ReadLine 无法获取任何数据,则返回一个错误信息(通常是 io.EOF) 49 | bs, flag, _ := read.ReadLine() 50 | fmt.Println(string(bs), flag) 51 | 52 | buf := bytes.NewBuffer(make([]byte, 0)) 53 | write := bufio.NewWriter(buf) 54 | i, _ := write.WriteString("sunpengwei999") 55 | write.Flush() 56 | fmt.Println(buf, i) 57 | 58 | } 59 | -------------------------------------------------------------------------------- /algorithm/binarysearchtree_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestBinarySearchTree_RecursionAdd(t *testing.T) { 8 | tree := &BinarySearchTree{0, nil, nil} 9 | tree.RecursionAdd(1) 10 | tree.RecursionAdd(2) 11 | tree.RecursionAdd(3) 12 | t.Log(tree) 13 | t.Log(tree.leftChild) 14 | t.Log(tree.leftChild.leftChild) 15 | t.Log(tree.rightChild) 16 | t.Log(tree.rightChild.rightChild) 17 | t.Log(tree.Deep()) 18 | t.Log(tree.Height()) 19 | } 20 | func TestBinarySearchTree_NotRecursionAdd(t *testing.T) { 21 | tree := &BinarySearchTree{0, nil, nil} 22 | for i := 1; i < 10; i++ { 23 | tree.RecursionAdd(i) 24 | } 25 | t.Log(tree.Search(5).value) 26 | t.Log(tree.Search(5).leftChild.value) 27 | t.Log(tree.GetMin()) 28 | tree.Remove(1) 29 | t.Log(tree.Search(1)) 30 | t.Log(tree.Deep()) 31 | t.Log(tree.Search(8).Deep()) 32 | t.Log(tree.Search(8).Height()) 33 | } 34 | 35 | func TestPreTraversalTree(t *testing.T) { 36 | PreTraversalTree([]int{0, 1, 2, 3, 4, 5}) 37 | } 38 | func TestPreTraversalRecursionTree(t *testing.T) { 39 | PreTraversalRecursionTree([]int{0, 1, 2, 3, 4, 5}) 40 | } 41 | func TestInTraversalTree(t *testing.T) { 42 | InTraversalTree([]int{0, 1, 2, 3, 4, 5}) 43 | } 44 | func TestInTraversalRecursionTree(t *testing.T) { 45 | InTraversalRecursionTree([]int{0, 1, 2, 3, 4, 5}) 46 | } 47 | func TestPoTraversalTree(t *testing.T) { 48 | PoTraversalTree([]int{0, 1, 2, 3, 4, 5}) 49 | } 50 | func TestPoTraversalRecursionTree(t *testing.T) { 51 | PoTraversalRecursionTree([]int{0, 1, 2, 3, 4, 5}) 52 | } 53 | -------------------------------------------------------------------------------- /basic/map_study.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import "fmt" 4 | 5 | /** 6 | go语言map学习 7 | Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值 8 | */ 9 | 10 | // 可以使用make函数 或者 map关键字 来定义map 11 | 12 | //声明一个map 13 | var mapInt1 map[int]string 14 | 15 | //使用make函数创建map 16 | var mapInt2 = make(map[int]string) 17 | 18 | func MapStudy() { 19 | mapInt1 = make(map[int]string, 10) 20 | fmt.Println(len(mapInt1)) //0 21 | 22 | // 为map插入键值对 23 | mapInt1[0] = "spw" 24 | mapInt1[1] = "wei" 25 | mapInt1[2] = "yyy" 26 | 27 | // 使用key输出map的值 28 | for key := range mapInt1 { 29 | fmt.Printf("map key %d value is %s\n", key, mapInt1[key]) 30 | } 31 | 32 | // 检查集合中元素是否存在 33 | value, ok := mapInt1[3] 34 | if ok { 35 | fmt.Println("map key 3 is " + value) 36 | } else { 37 | fmt.Println("map key 3 is null") 38 | } 39 | 40 | // delete 函数 ,用于删除集合元素 参数为map 和 key 41 | 42 | delete(mapInt1, 0) 43 | // 删除之后打印map 44 | for key, value := range mapInt1 { 45 | fmt.Printf("map key %d value is %s\n", key, value) 46 | } 47 | 48 | } 49 | 50 | type ListNode struct { 51 | Val int 52 | Next *ListNode 53 | } 54 | 55 | func detectCycle(head *ListNode) *ListNode { 56 | if head == nil { 57 | return nil 58 | } 59 | temp1 := head 60 | result := head 61 | m := make(map[ListNode]int) 62 | for temp1 != nil { 63 | current := *temp1 64 | if _, ok := m[current]; ok { 65 | result = temp1 66 | break 67 | } else { 68 | m[current] = 1 69 | } 70 | temp1 = temp1.Next 71 | fmt.Println(temp1) 72 | if temp1 == nil { 73 | return nil 74 | } 75 | 76 | } 77 | return result 78 | } 79 | -------------------------------------------------------------------------------- /algorithm/back_flash.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | /** 8 | 回溯算法 9 | */ 10 | var result []int = make([]int, 8, 8) 11 | 12 | //八皇后,result 下标表示行,值表示列 13 | func Call8Queens(row int) { 14 | if row == 8 { // 8个棋子都放置好了 15 | printResult(result) //打印结果 16 | return 17 | } 18 | for column := 0; column < 8; column++ { 19 | if isOk(row, column, result) { 20 | result[row] = column 21 | Call8Queens(row + 1) 22 | } 23 | } 24 | } 25 | 26 | func isOk(row int, column int, result []int) bool { 27 | left, right := column-1, column+1 28 | for i := row - 1; i >= 0; i-- { 29 | if result[i] == column { // 第i行和这一行是同一列 30 | return false 31 | } 32 | if left >= 0 { //考察左对角线 33 | if result[i] == left { 34 | return false 35 | } 36 | } 37 | if right < 8 { //考察右对角线 38 | if result[i] == right { 39 | return false 40 | } 41 | } 42 | left-- 43 | right++ 44 | } 45 | return true 46 | } 47 | 48 | func printResult(result []int) { 49 | for row := 0; row < 8; row++ { 50 | for column := 0; column < 8; column++ { 51 | if result[row] == column { 52 | fmt.Print("Q ") 53 | } else { 54 | fmt.Print("* ") 55 | } 56 | } 57 | fmt.Println() 58 | } 59 | fmt.Println() 60 | 61 | } 62 | 63 | /** 64 | 求数字的全排列 比如 1,2,3,4,5,6 65 | array 一组数字 temp 其实下标 66 | */ 67 | func F(array []int, temp int) { 68 | if temp == len(array) { 69 | fmt.Println(array) 70 | return 71 | } 72 | for i := temp; i < len(array); i++ { 73 | array[temp], array[i] = array[i], array[temp] 74 | F(array, temp+1) 75 | array[temp], array[i] = array[i], array[temp] 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /basic/hash.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "crypto/md5" 5 | "crypto/sha1" 6 | "crypto/sha256" 7 | "crypto/sha512" 8 | "encoding/base64" 9 | "encoding/hex" 10 | "fmt" 11 | "hash/crc32" 12 | "hash/crc64" 13 | "hash/maphash" 14 | ) 15 | 16 | /** 17 | golang hash函数学习 18 | */ 19 | 20 | // 生成32位MD5 21 | func Md5() { 22 | str := "sun_peng_wei" 23 | //方法一 24 | ctx := md5.New() 25 | ctx.Write([]byte(str)) 26 | fmt.Println(hex.EncodeToString(ctx.Sum(nil))) 27 | //方法二 28 | has := md5.Sum([]byte(str)) 29 | md5str1 := fmt.Sprintf("%x", has) //将[]byte转成16进制 30 | fmt.Println(md5str1) 31 | } 32 | 33 | func Base64() { 34 | //标准加密 35 | en := base64.StdEncoding.EncodeToString([]byte("sunpengwei")) 36 | //标准解密 37 | de, _ := base64.StdEncoding.DecodeString(en) 38 | fmt.Println(en, string(de)) 39 | } 40 | 41 | func HashTest() { 42 | // %x 16进制 43 | // %b 2进制 44 | // %s 字符串 45 | sha1 := sha1.Sum([]byte("sunpengwei")) 46 | fmt.Println(fmt.Sprintf("%x", sha1)) 47 | 48 | sha2 := sha256.Sum256([]byte("sunpengwei")) 49 | fmt.Println(fmt.Sprintf("%x", sha2)) 50 | 51 | sha3 := sha512.Sum512([]byte("sunpengwei")) 52 | fmt.Println(fmt.Sprintf("%x", sha3)) 53 | 54 | } 55 | 56 | func Crc() { 57 | crc32_1 := crc32.Checksum([]byte("sunpengwei"), &crc32.Table{}) 58 | crc32_2 := crc32.ChecksumIEEE([]byte("sunpengwei")) 59 | fmt.Println(crc32_1, crc32_2) 60 | 61 | crc64_1 := crc64.Checksum([]byte("sunpengwei"), &crc64.Table{}) 62 | fmt.Println(crc64_1) 63 | } 64 | 65 | func MapHashStudy() { 66 | b := []byte("foo") 67 | h1 := new(maphash.Hash) 68 | h1.Write(b) 69 | //输出字节数组的hash值 70 | fmt.Println(h1.Sum64()) 71 | } 72 | -------------------------------------------------------------------------------- /benchmark/recursion.go: -------------------------------------------------------------------------------- 1 | package benchmark 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func Fib(n int64) int64 { 9 | if n <= 2 { 10 | return 1 11 | } 12 | return Fib(n-1) + Fib(n-2) 13 | } 14 | 15 | type I interface { 16 | f() 17 | } 18 | 19 | type S struct { 20 | a int64 21 | } 22 | 23 | var a int 24 | 25 | func f() { 26 | a++ 27 | } 28 | 29 | func Method() { 30 | start := time.Now().UnixNano() 31 | for j := 0; j < 1; j++ { 32 | f() 33 | } 34 | end := time.Now().UnixNano() 35 | fmt.Println(end - start) 36 | } 37 | 38 | func bubbleSort(arr *[]int) { 39 | for j := 0; j < len(*arr)-1; j++ { 40 | for k := 0; k < len(*arr)-1-j; k++ { 41 | if (*arr)[k] < (*arr)[k+1] { 42 | temp := (*arr)[k] 43 | (*arr)[k] = (*arr)[k+1] 44 | (*arr)[k+1] = temp 45 | } 46 | } 47 | } 48 | } 49 | 50 | func Sort() { 51 | //7215441800 52 | const NUM = 100000000 53 | var arr []int 54 | start := time.Now().UnixNano() 55 | for i := 0; i < NUM; i++ { 56 | arr = []int{1, 2, 3, 4, 5, 6, 7, 8, 9} 57 | BubbleSort(arr) 58 | } 59 | fmt.Println(time.Now().UnixNano() - start) 60 | } 61 | 62 | func Sort1() { 63 | //4242922000 64 | const NUM = 100000000 65 | start := time.Now().UnixNano() 66 | for i := 0; i < NUM; i++ { 67 | arr := []int{1, 2, 3, 4, 5, 6, 7, 8, 9} 68 | BubbleSort(arr) 69 | } 70 | fmt.Println(time.Now().UnixNano() - start) 71 | } 72 | 73 | //排序 74 | func BubbleSort(arr []int) { 75 | for j := 0; j < len(arr)-1; j++ { 76 | for k := 0; k < len(arr)-1-j; k++ { 77 | if arr[k] < arr[k+1] { 78 | temp := arr[k] 79 | arr[k] = arr[k+1] 80 | arr[k+1] = temp 81 | } 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /algorithm/bloom_filter.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | /** 4 | 布隆过滤器 5 | */ 6 | import ( 7 | "fmt" 8 | "github.com/willf/bitset" 9 | ) 10 | 11 | const DEFAULT_SIZE = 2 << 24 12 | 13 | var seeds = []uint{3, 8, 13, 18, 21, 26} 14 | 15 | type BloomFilter struct { 16 | set *bitset.BitSet 17 | funcs [6]SimpleHash 18 | } 19 | 20 | func NewBloomFilter() *BloomFilter { 21 | bf := new(BloomFilter) 22 | for i := 0; i < len(bf.funcs); i++ { 23 | bf.funcs[i] = SimpleHash{DEFAULT_SIZE, seeds[i]} 24 | } 25 | bf.set = bitset.New(DEFAULT_SIZE) 26 | return bf 27 | } 28 | 29 | func (bf BloomFilter) add(value string) { 30 | for _, f := range bf.funcs { 31 | bf.set.Set(f.hash(value)) 32 | } 33 | } 34 | 35 | func (bf BloomFilter) contains(value string) bool { 36 | if value == "" { 37 | return false 38 | } 39 | ret := true 40 | for _, f := range bf.funcs { 41 | ret = ret && bf.set.Test(f.hash(value)) 42 | } 43 | return ret 44 | } 45 | 46 | type SimpleHash struct { 47 | cap uint 48 | seed uint 49 | } 50 | 51 | func (s SimpleHash) hash(value string) uint { 52 | var result uint = 0 53 | for i := 0; i < len(value); i++ { 54 | result = result*s.seed + uint(value[i]) 55 | } 56 | return (s.cap - 1) & result 57 | } 58 | 59 | func main() { 60 | filter := NewBloomFilter() 61 | fmt.Println(filter.funcs[1].seed) 62 | str1 := "hello,bloom filter!" 63 | filter.add(str1) 64 | str2 := "A happy day" 65 | filter.add(str2) 66 | str3 := "Greate wall" 67 | filter.add(str3) 68 | fmt.Println(filter.contains(str1)) 69 | fmt.Println(filter.contains(str2)) 70 | fmt.Println(filter.contains(str3)) 71 | fmt.Println(filter.contains("blockchain technology")) 72 | } 73 | -------------------------------------------------------------------------------- /tools/http_ sign_in.go: -------------------------------------------------------------------------------- 1 | package tools 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "io/ioutil" 7 | "log" 8 | "net/http" 9 | "net/http/cookiejar" 10 | "net/url" 11 | "strings" 12 | ) 13 | 14 | func NewClient() *http.Client { 15 | CurCookieJar, _ := cookiejar.New(nil) 16 | return &http.Client{ 17 | Jar: CurCookieJar, 18 | } 19 | } 20 | 21 | //登录结果实体 22 | type LoginResponse struct { 23 | Code int `json:"code"` 24 | Data AuthInfo `json:"data"` 25 | } 26 | 27 | type AuthInfo struct { 28 | AuthToken string `json:"authToken"` 29 | } 30 | 31 | /** 32 | client http请求客户端 33 | authToken 请求头中必须携带的token 34 | error 如果登陆失败,返回的错误信息 35 | */ 36 | func Login(param map[string]string, loginUrl string) (*http.Client, string, error) { 37 | 38 | values := url.Values{} 39 | for k, v := range param { 40 | values.Add(k, v) 41 | } 42 | req, err := http.NewRequest("POST", loginUrl, strings.NewReader(values.Encode())) 43 | req.Header.Add("Content-Type", "application/x-www-form-urlencoded") 44 | 45 | client := NewClient() 46 | // 执行登录操作 47 | res, err := client.Do(req) 48 | if nil != err { 49 | log.Fatal(err) 50 | } 51 | defer res.Body.Close() 52 | 53 | //登录返回结果 54 | bs, _ := ioutil.ReadAll(res.Body) 55 | result := string(bs) 56 | 57 | //对结果验证 58 | if !strings.Contains(result, "操作成功") { 59 | return nil, "", errors.New(result) 60 | } 61 | //将结果信息反序列化 62 | loginResponse := &LoginResponse{} 63 | err = json.Unmarshal(bs, loginResponse) 64 | if err != nil { 65 | return nil, "", errors.New("登录结果信息:" + result + "反序列化LoginResponse错误,错误信息:" + err.Error()) 66 | } 67 | //返回client,authToken 68 | return client, loginResponse.Data.AuthToken, nil 69 | } 70 | -------------------------------------------------------------------------------- /grpc/helloworld_demo/impl/hello_service_impl.go: -------------------------------------------------------------------------------- 1 | package impl 2 | 3 | import ( 4 | "context" 5 | pb "go_common/grpc/helloworld_demo/proto" 6 | "log" 7 | "time" 8 | ) 9 | 10 | type HelloServiceServer struct { 11 | } 12 | 13 | func (*HelloServiceServer) HelloWorld(ctx context.Context, req *pb.HelloRequest) (*pb.HelloResponse, error) { 14 | log.Printf("%v", req.Request) 15 | return &pb.HelloResponse{Response: "hello my is gRpcServer"}, nil 16 | } 17 | func (*HelloServiceServer) HelloWorldServerStream(req *pb.HelloRequest, srv pb.HelloService_HelloWorldServerStreamServer) error { 18 | log.Printf("%v", req.Request) 19 | srv.Send(&pb.HelloResponse{Response: "hello my is gRpcServer stream"}) 20 | return nil 21 | } 22 | func (*HelloServiceServer) HelloWorldClientStream(srv pb.HelloService_HelloWorldClientStreamServer) error { 23 | for { 24 | req, err := srv.Recv() 25 | if err != nil && err.Error() == "EOF" { 26 | break 27 | } 28 | if err != nil { 29 | log.Fatalf("%v", err) 30 | break 31 | } else { 32 | log.Printf("%v", req.Request) 33 | } 34 | } 35 | srv.SendAndClose(&pb.HelloResponse{Response: "hello my is gRpcServer"}) 36 | return nil 37 | } 38 | func (*HelloServiceServer) HelloWorldClientAndServerStream(srv pb.HelloService_HelloWorldClientAndServerStreamServer) error { 39 | for { 40 | req, err := srv.Recv() 41 | if err != nil && err.Error() == "EOF" { 42 | break 43 | } 44 | if err != nil { 45 | log.Fatalf("%v", err) 46 | break 47 | } else { 48 | log.Printf("%v", req.Request) 49 | time.Sleep(1 * time.Millisecond) 50 | srv.Send(&pb.HelloResponse{Response: "hello my is gRpcServer stream"}) 51 | } 52 | } 53 | return nil 54 | } 55 | -------------------------------------------------------------------------------- /algorithm/funnel_rate_limiter.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | /** 9 | 漏斗限流 10 | */ 11 | const ( 12 | FUNNEL_INTERVAL = time.Second * 1 13 | ) 14 | 15 | type FunnelRateLimiter struct { 16 | interval time.Duration //时间间隔 17 | cap int //漏斗容量 18 | rate int //漏斗流出速率 每秒流多少 19 | head int //放入水的指针 20 | tail int //漏水的指针 21 | ticker *time.Ticker //定时器 22 | } 23 | 24 | /** 25 | cap 漏斗的容量 代表最大容纳多少个请求 26 | rate 漏斗流出的速度 大于0 27 | 限流速度是 cap - rate 28 | */ 29 | func NewFunnelRateLimiter(cap int, rate int) *FunnelRateLimiter { 30 | limiter := &FunnelRateLimiter{ 31 | interval: FUNNEL_INTERVAL, 32 | cap: cap, 33 | rate: rate, 34 | head: 0, 35 | tail: 0, 36 | } 37 | go leakRate(limiter) 38 | return limiter 39 | } 40 | 41 | /** 42 | 是否允许请求通过(主要看漏斗是否满了) 43 | */ 44 | func (limiter *FunnelRateLimiter) IsAllow() bool { 45 | if limiter.head-limiter.tail >= limiter.cap { //说明漏斗满了 46 | return false 47 | } 48 | limiter.head++ 49 | return true 50 | } 51 | 52 | /** 53 | 模拟漏斗以一定的流速漏水 54 | */ 55 | func leakRate(limiter *FunnelRateLimiter) { 56 | limiter.ticker = time.NewTicker(limiter.interval) 57 | for { 58 | <-limiter.ticker.C 59 | 60 | //根本没有流量,不需要漏 61 | if limiter.tail >= limiter.head { 62 | fmt.Println("根本没有流量,不需要漏", limiter.head, limiter.tail) 63 | continue 64 | } 65 | if (limiter.head - limiter.tail) > limiter.rate { 66 | limiter.tail = limiter.tail + limiter.rate 67 | fmt.Println("每秒都在流水-1", limiter.head, limiter.tail) 68 | } else { 69 | limiter.tail = limiter.head 70 | fmt.Println("每秒都在流水-2", limiter.head, limiter.tail) 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /algorithm/avltree2_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | /** 9 | 左左,右右旋转 10 | */ 11 | func TestAvlTree_Insert(t *testing.T) { 12 | avlTree := &AvlTree{} 13 | 14 | avlTree.Insert(5) 15 | avlTree.Insert(3) 16 | avlTree.Insert(7) 17 | avlTree.Insert(2) 18 | avlTree.Insert(1) 19 | PrePrint(avlTree.root) 20 | fmt.Println() 21 | avlTree.Insert(0) 22 | PrePrint(avlTree.root) 23 | avlTree.Insert(8) 24 | fmt.Println() 25 | PrePrint(avlTree.root) 26 | fmt.Println() 27 | avlTree.Insert(9) 28 | PrePrint(avlTree.root) 29 | fmt.Println() 30 | avlTree.Insert(10) 31 | PrePrint(avlTree.root) 32 | fmt.Println() 33 | avlTree.Insert(11) 34 | PrePrint(avlTree.root) 35 | fmt.Println() 36 | avlTree.Insert(12) 37 | PrePrint(avlTree.root) 38 | fmt.Println() 39 | avlTree.Insert(-2) 40 | PrePrint(avlTree.root) 41 | fmt.Println() 42 | avlTree.Insert(-3) 43 | PrePrint(avlTree.root) 44 | } 45 | 46 | /** 47 | 左右旋转 48 | */ 49 | func TestAvlInsert2(t *testing.T) { 50 | avlTree := &AvlTree{} 51 | avlTree.Insert(5) 52 | avlTree.Insert(4) 53 | avlTree.Insert(7) 54 | avlTree.Insert(1) 55 | avlTree.Insert(2) 56 | 57 | PrePrint(avlTree.root) 58 | } 59 | 60 | /** 61 | 右左旋转 62 | */ 63 | func TestAvlInsert3(t *testing.T) { 64 | avlTree := &AvlTree{} 65 | avlTree.Insert(5) 66 | avlTree.Insert(4) 67 | avlTree.Insert(7) 68 | avlTree.Insert(9) 69 | avlTree.Insert(8) 70 | 71 | PrePrint(avlTree.root) 72 | } 73 | 74 | /** 75 | 这个avl的树实现有问题 76 | */ 77 | func TestGetHeight(t *testing.T) { 78 | avlTree := &AvlTree{} 79 | avlTree.Insert(8) 80 | avlTree.Insert(4) 81 | avlTree.Insert(15) 82 | avlTree.Insert(5) 83 | avlTree.Insert(6) 84 | 85 | PrePrint(avlTree.root) 86 | fmt.Println(GetHeight(avlTree.root)) 87 | 88 | } 89 | -------------------------------------------------------------------------------- /basic/sync_study.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "fmt" 5 | "runtime" 6 | "sync" 7 | "sync/atomic" 8 | "time" 9 | ) 10 | 11 | //sync 包的学习 12 | 13 | //线程安全map学习 14 | /** 15 | 添加数据 16 | */ 17 | var m sync.Map 18 | 19 | func SyncMapPut(key int, value interface{}) { 20 | m.Store(key, value) 21 | } 22 | 23 | /** 24 | 返回键的现有值(如果存在),否则存储并返回给定的值,如果是读取则返回true,如果是存储返回false。 25 | */ 26 | func SyncMapUpdate(key int, value interface{}) { 27 | actual, ok := m.LoadOrStore(key, value) 28 | fmt.Println(actual, ok) 29 | 30 | } 31 | 32 | /** 33 | 删除指定的key 34 | */ 35 | func SyncMapDel(key int) { 36 | m.Delete(key) 37 | } 38 | 39 | /** 40 | 读取key的值,如果不存在,返回 nil,false 41 | */ 42 | func SyncMapRead(key int) { 43 | v, ok := m.Load(key) 44 | fmt.Println(v, ok) 45 | } 46 | func SyncMapRange() { 47 | m.Range(func(key, value interface{}) bool { 48 | fmt.Println(key, value) 49 | return true 50 | }) 51 | } 52 | 53 | //互斥锁 54 | var mutex sync.Mutex 55 | 56 | func StudyMutex() { 57 | runtime.GOMAXPROCS(4) 58 | wait := sync.WaitGroup{} 59 | wait.Add(1) 60 | mutex.Lock() 61 | 62 | fmt.Println(1 | 2 | 4) 63 | 64 | go func() { 65 | mutex.Lock() 66 | }() 67 | time.Sleep(10 * time.Second) 68 | mutex.Unlock() 69 | } 70 | 71 | func StudySyncOnce() { 72 | 73 | val := 0 74 | once := sync.Once{} 75 | f := func() { 76 | val++ 77 | } 78 | for i := 0; i < 10; i++ { 79 | //虽然循环了10次,但只是执行了一次 80 | once.Do(f) 81 | } 82 | fmt.Println(val) //结果是1 83 | } 84 | 85 | func StudySyncPool() { 86 | runtime.GOMAXPROCS(0) 87 | pool := sync.Pool{} 88 | 89 | pool.Put(1) 90 | 91 | delta := 1 92 | t := uint64(delta) << 32 93 | s := uint64(0) 94 | state := atomic.AddUint64(&s, t) 95 | t1 := int32(state << 32) 96 | w := uint32(state) 97 | fmt.Println(t, t1, w, state) 98 | } 99 | -------------------------------------------------------------------------------- /algorithm/count_limiter.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "time" 5 | 6 | "go.uber.org/atomic" 7 | ) 8 | 9 | //计数器限流 开启一个新的协程监控每经过一秒index清0 10 | type CountLimiter struct { 11 | count int64 12 | unitTime time.Duration 13 | index *atomic.Int64 14 | } 15 | 16 | //计数器限流,不用新开协程, 每次判断时, 17 | // 先看当前时间和上次时间差是否大于1秒,如果大于则计数器清零0,重新开始,如果小与1秒,则判断计数器到达阈值,返回false,否则返回true 18 | type CountLimiterNew struct { 19 | count int64 20 | lastTime int64 21 | index *atomic.Int64 22 | nano int64 23 | } 24 | 25 | func NewCountLimiter(count int64, unitTime time.Duration) *CountLimiter { 26 | countLimiter := &CountLimiter{ 27 | count: count, 28 | unitTime: unitTime, 29 | index: atomic.NewInt64(0), 30 | } 31 | go timer(countLimiter) 32 | return countLimiter 33 | } 34 | 35 | func NewCountLimiterNew(count int64, lastTime int64) *CountLimiterNew { 36 | countLimiterNew := &CountLimiterNew{ 37 | count: count, 38 | lastTime: time.Now().UnixNano(), 39 | index: atomic.NewInt64(0), 40 | nano: 1000 * 1000 * 1000, 41 | } 42 | return countLimiterNew 43 | } 44 | 45 | func (cl *CountLimiterNew) IsAllowNew() bool { 46 | //已经进入到下一秒中了 47 | if time.Now().UnixNano()-cl.lastTime > cl.nano { 48 | cl.lastTime = time.Now().UnixNano() 49 | cl.index.Store(1) 50 | return true 51 | } 52 | //当前这一秒钟计数器到达阈值了,进行限流 53 | if cl.index.Load() > cl.count { 54 | return false 55 | } 56 | //计数器加1 57 | cl.index.Add(1) 58 | return true 59 | } 60 | 61 | func timer(limiter *CountLimiter) { 62 | ticker := time.NewTicker(limiter.unitTime) 63 | for { 64 | <-ticker.C 65 | limiter.index.Store(0) 66 | } 67 | } 68 | 69 | func (cl *CountLimiter) IsAllow() bool { 70 | if cl.index.Load() >= cl.count { 71 | return false 72 | } 73 | cl.index.Add(1) 74 | return true 75 | } 76 | -------------------------------------------------------------------------------- /gout/gout_study.go: -------------------------------------------------------------------------------- 1 | package gout 2 | 3 | import ( 4 | "fmt" 5 | "github.com/guonaihong/gout" 6 | "github.com/guonaihong/gout/dataflow" 7 | "time" 8 | ) 9 | 10 | var url = "https://www.baidu.com" 11 | 12 | //GET请求发送 13 | func StudyGoutGet() { 14 | 15 | result := "" 16 | // 发送GET方法 17 | gout.GET(url).BindBody(&result).Do() 18 | 19 | fmt.Println(result) 20 | } 21 | 22 | //请求回调处理 23 | func StudyGoutCallBack() { 24 | 25 | result := "" 26 | // 发送GET方法,对返回的结果进行回调处理,可以判断http的code码做出不同的处理 27 | err := gout.GET(url).Callback(func(context *dataflow.Context) error { 28 | 29 | switch context.Code { 30 | 31 | case 200: 32 | context.BindBody(&result) 33 | case 404: 34 | context.BindBody(&result) 35 | 36 | } 37 | 38 | return nil 39 | }).Do() 40 | 41 | fmt.Println(err, result) 42 | } 43 | 44 | //超时设置 45 | func StudyGoutTimeOut() { 46 | 47 | result := "" 48 | //设置1毫秒的超时,模拟超时 49 | err := gout.GET(url).SetTimeout(time.Millisecond * 1).BindBody(&result).Do() 50 | if err != nil { 51 | fmt.Println(err) 52 | } else { 53 | fmt.Println(result) 54 | } 55 | } 56 | 57 | //debug设置 58 | func StudyGoutGetDebug() { 59 | result := "" 60 | // 发送GET方法 61 | gout.GET(url).Debug(true).BindBody(&result).Do() 62 | 63 | fmt.Println(result) 64 | } 65 | 66 | //跟踪请求耗时时间 67 | func StudyGoutGetTraceInfo() { 68 | result := "" 69 | // 发送GET方法 70 | gout.GET(url).Debug(gout.Trace()).BindBody(&result).Do() 71 | 72 | fmt.Println(result) 73 | } 74 | 75 | // 指定并发数的情况下持续一段时间的压测 76 | func StudyGoutBenchmarkDuration() { 77 | err := gout. 78 | POST(url). //压测本机8080端口 79 | Filter(). //打开过滤器 80 | Bench(). //选择bench功能 81 | Concurrent(20). //并发数 82 | Durations(10 * time.Second). //压测时间 83 | Do() 84 | 85 | if err != nil { 86 | fmt.Printf("%v\n", err) 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /gleam/gleam_study.go: -------------------------------------------------------------------------------- 1 | package gleam 2 | 3 | import ( 4 | "flag" 5 | "strings" 6 | 7 | "github.com/chrislusf/gleam/distributed" 8 | "github.com/chrislusf/gleam/flow" 9 | "github.com/chrislusf/gleam/gio" 10 | "github.com/chrislusf/gleam/plugins/file" 11 | ) 12 | 13 | var ( 14 | isDistributed = flag.Bool("distributed", false, "run in distributed or not") 15 | Tokenize = gio.RegisterMapper(tokenize) 16 | AppendOne = gio.RegisterMapper(appendOne) 17 | Sum = gio.RegisterReducer(sum) 18 | ) 19 | 20 | func GleamStudy() { 21 | 22 | gio.Init() // If the command line invokes the mapper or reducer, execute it and exit. 23 | flag.Parse() // optional, since gio.Init() will call this also. 24 | 25 | f := flow.New("top5 words in passwd"). 26 | Read(file.Txt("/etc/passwd", 2)). // read a txt file and partitioned to 2 shards 27 | Map("tokenize", Tokenize). // invoke the registered "tokenize" mapper function. 28 | Map("appendOne", AppendOne). // invoke the registered "appendOne" mapper function. 29 | ReduceByKey("sum", Sum). // invoke the registered "sum" reducer function. 30 | Sort("sortBySum", flow.OrderBy(2, true)). 31 | Top("top5", 5, flow.OrderBy(2, false)). 32 | Printlnf("%s\t%d") 33 | 34 | if *isDistributed { 35 | f.Run(distributed.Option()) 36 | } else { 37 | f.Run() 38 | } 39 | 40 | } 41 | 42 | func tokenize(row []interface{}) error { 43 | line := gio.ToString(row[0]) 44 | for _, s := range strings.FieldsFunc(line, func(r rune) bool { 45 | return !('A' <= r && r <= 'Z' || 'a' <= r && r <= 'z' || '0' <= r && r <= '9') 46 | }) { 47 | gio.Emit(s) 48 | } 49 | return nil 50 | } 51 | 52 | func appendOne(row []interface{}) error { 53 | row = append(row, 1) 54 | gio.Emit(row...) 55 | return nil 56 | } 57 | 58 | func sum(x, y interface{}) (interface{}, error) { 59 | return gio.ToInt64(x) + gio.ToInt64(y), nil 60 | } 61 | -------------------------------------------------------------------------------- /tools/http_utils.go: -------------------------------------------------------------------------------- 1 | package tools 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "fmt" 7 | "io" 8 | "log" 9 | "net/http" 10 | "net/url" 11 | "os" 12 | "path" 13 | ) 14 | 15 | /** 16 | 使用httpUrl下载文件 17 | 第一个参数,http连接 18 | 第二参数,下载下来的文件存放路径 19 | */ 20 | func HttpGetFile(httpUrl string, filePath string) { 21 | if httpUrl == "" { 22 | return 23 | } 24 | uri, _ := url.ParseRequestURI(httpUrl) 25 | fileName := path.Base(uri.Path) 26 | res, err := http.Get(httpUrl) 27 | if err != nil { 28 | fmt.Println(httpUrl, "访问错误", err) 29 | } 30 | file, _ := os.Create(filePath + fileName) 31 | io.Copy(file, res.Body) 32 | } 33 | 34 | /** 35 | 如果返回的错误为nil,说明文件或文件夹存在 36 | 如果返回的错误类型使用os.IsNotExist()判断为true,说明文件或文件夹不存在 37 | 如果返回的错误为其它类型,则不确定是否在存在 38 | */ 39 | func PathExists(path string) (bool, error) { 40 | _, err := os.Stat(path) 41 | if err == nil { 42 | return true, nil 43 | } 44 | if os.IsNotExist(err) { 45 | return false, nil 46 | } 47 | return false, err 48 | } 49 | 50 | func PostRequest(httpUrl string) { 51 | 52 | params := make(map[string]interface{}) 53 | params["createTime"] = "2019-09-09 12:12:12" 54 | params["salegrpCodes"] = []string{"100"} 55 | params["modelCode"] = 1 56 | params["dealCode"] = 1 57 | params["skuCodeArray"] = []string{"000000000100461042"} 58 | params["businessUnitCode"] = "舒适家事业部" 59 | params["saleChannelType"] = "1" 60 | params["buyorg"] = 103 61 | params["purchaseType"] = "0001" 62 | 63 | data, err := json.Marshal(params) 64 | if err != nil { 65 | log.Println("序列化错误", err) 66 | return 67 | } 68 | body := bytes.NewBuffer(data) 69 | req, err := http.NewRequest("POST", httpUrl, body) 70 | req.Header.Set("Content-Type", "application/json;charset=utf-8") 71 | client := NewClient() 72 | // 执行登录操作 73 | res, err := client.Do(req) 74 | if nil != err { 75 | log.Println("请求错误", err) 76 | } 77 | defer res.Body.Close() 78 | } 79 | -------------------------------------------------------------------------------- /algorithm/tire.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import "fmt" 4 | 5 | type TireNode struct { 6 | num int // 有多少个单词通过这个节点 7 | son []*TireNode // 子节点 8 | isEnd bool // 是否最后一个节点 9 | val rune // 节点的值 10 | } 11 | 12 | const SIZE = 26 13 | 14 | type TireTree struct { 15 | root *TireNode // 根节点 16 | } 17 | 18 | /** 19 | 字典树添加 20 | */ 21 | func (tt *TireTree) Insert(str string) { 22 | if len(str) == 0 { 23 | return 24 | } 25 | if tt.root == nil { 26 | tt.root = &TireNode{} 27 | } 28 | tn := tt.root 29 | for _, v := range str { 30 | index := v - 'a' // 计算字符的下标 31 | if tn.son == nil { 32 | tn.son = make([]*TireNode, SIZE) 33 | } 34 | if tn.son[index] == nil { 35 | tn.son[index] = &TireNode{ 36 | val: v, 37 | num: 1, 38 | } 39 | } else { 40 | tn.son[index].num++ 41 | } 42 | tn = tn.son[index] 43 | } 44 | tn.isEnd = true 45 | } 46 | 47 | /** 48 | 查找字符串是否存在 49 | */ 50 | func (tt *TireTree) Query(str string) bool { 51 | if tt.root == nil { 52 | return false 53 | } 54 | tn := tt.root 55 | for _, v := range str { 56 | index := v - 'a' 57 | if tn.son == nil { 58 | break 59 | } 60 | if tn.son[index] == nil || tn.son[index].val != v { 61 | break 62 | } 63 | tn = tn.son[index] 64 | } 65 | return tn.isEnd 66 | } 67 | 68 | // 前序遍历字典树. 69 | func (tt *TireTree) PreTraverse(tn *TireNode) { 70 | if tn == nil { 71 | return 72 | } 73 | fmt.Print(string(tn.val)) 74 | for i := 0; i < len(tn.son); i++ { 75 | tt.PreTraverse(tn.son[i]) 76 | } 77 | } 78 | 79 | /** 80 | 统计以prefix开头的单词有多少个 81 | */ 82 | func (tt *TireTree) CountPrefix(prefix string) int { 83 | tn := tt.root 84 | if tn == nil { 85 | return 0 86 | } 87 | for _, v := range prefix { 88 | index := v - 'a' 89 | if tn.son[index] == nil { 90 | return 0 91 | } 92 | if tn.son[index].val != v { 93 | return 0 94 | } 95 | tn = tn.son[index] 96 | } 97 | return tn.num 98 | } 99 | -------------------------------------------------------------------------------- /basic/time_study.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | "time" 7 | ) 8 | 9 | func TimeStudy() { 10 | // 获取当前时间的对象 11 | t := time.Now() 12 | // 获取当前的时间戳 秒 13 | fmt.Println(t.Unix()) 14 | // 获取当前时间戳 纳秒,没有毫秒的方法 1秒 = 1000 毫秒 = 1000 * 1000微妙 = 1000 * 1000 *1000纳秒 15 | fmt.Println(t.UnixNano()) 16 | 17 | fmt.Println(t.Year()) // 年 2018 18 | fmt.Println(t.Month()) // 月 April 19 | fmt.Println(t.Day()) // 日 22 20 | fmt.Println(t.Hour()) // 小时 20 21 | fmt.Println(t.Minute()) // 分钟 20 22 | fmt.Println(t.Second()) // 秒 20 23 | fmt.Println(t.Nanosecond()) // 纳秒 20 24 | 25 | fmt.Println(t.Date()) // 结果 : 2018 April 22 26 | fmt.Println(t.Local()) // 本地时间:2018-04-22 20:19:33.0960854 +0800 CST 27 | fmt.Println(t.Format("2006-01-02 15:04:05")) // 必须使用这个固定的字符串格式化日期,时间 28 | fmt.Println(time.Now().AddDate(0, 0, -1).Format("2006-01-02 15:04:05")) // 必须使用这个固定的字符串格式化日期,时间 29 | 30 | var wg sync.WaitGroup 31 | wg.Add(2) 32 | //NewTimer 创建一个 Timer,它会在最少过去时间段 d 后到期,向其自身的 C 字段发送当时的时间 33 | timer1 := time.NewTimer(2 * time.Second) 34 | 35 | //NewTicker 返回一个新的 Ticker,该 Ticker 包含一个通道字段,并会每隔时间段 d 就向该通道发送当时的时间。它会调 36 | //整时间间隔或者丢弃 tick 信息以适应反应慢的接收者。如果d <= 0会触发panic。关闭该 Ticker 可 37 | //以释放相关资源。 38 | ticker1 := time.NewTicker(2 * time.Second) 39 | 40 | go func(t *time.Ticker) { 41 | defer wg.Done() 42 | for { 43 | <-t.C 44 | fmt.Println("get ticker1", time.Now().Format("2006-01-02 15:04:05")) 45 | } 46 | }(ticker1) 47 | 48 | go func(t *time.Timer) { 49 | defer wg.Done() 50 | for { 51 | <-t.C 52 | fmt.Println("get timer", time.Now().Format("2006-01-02 15:04:05")) 53 | //Reset 使 t 重新开始计时,(本方法返回后再)等待时间段 d 过去后到期。如果调用时t 54 | //还在等待中会返回真;如果 t已经到期或者被停止了会返回假。 55 | t.Reset(2 * time.Second) 56 | } 57 | }(timer1) 58 | wg.Wait() 59 | } 60 | -------------------------------------------------------------------------------- /basic/defer_recover.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | /** 8 | 执行顺序,先声明的后执行 9 | */ 10 | func DeferStudy() { 11 | defer fmt.Println("defer 1") 12 | defer func() { 13 | fmt.Println("defer 2") 14 | }() 15 | defer func(str string) { 16 | fmt.Println(str) 17 | }(string("带入参的defer 3")) 18 | } 19 | 20 | func RecoverStudy() error { 21 | /** 22 | defer 必须声明到panic之前 23 | */ 24 | defer func() { 25 | if err := recover(); err != nil { 26 | fmt.Println("捕捉到panic:", err) 27 | } 28 | }() 29 | panic("模拟发生错误") 30 | 31 | } 32 | 33 | func RecoverA() (i int, err error) { 34 | defer func() { 35 | if r := recover(); r != nil { 36 | fmt.Println("捕捉到panic:", r) 37 | err = r.(error) 38 | } 39 | }() 40 | panicA() 41 | return 0, err 42 | } 43 | 44 | func panicA() { 45 | bs := make([]byte, 4, 4) 46 | bs[10] = 0 47 | } 48 | 49 | /** 50 | 先来假设出结论,帮助大家理解原因: 51 | 多个defer的执行顺序为“后进先出”; 52 | defer、return、返回值三者的执行逻辑应该是:return最先执行,return负责将结果写入返回值中;接着defer开始执行一些收尾工作;最后函数携带当前返回值退出。 53 | 54 | 如何解释两种结果的不同: 55 | 上面两段代码的返回结果之所以不同,其实从上面第2条结论很好理解。 56 | a()int 函数的返回值没有被提前声名,其值来自于其他变量的赋值,而defer中修改的也是其他变量,而非返回值本身,因此函数退出时返回值并没有被改变。 57 | b()(i int) 函数的返回值被提前声名,也就意味着defer中是可以调用到真实返回值的,因此defer在return赋值返回值 i 之后,再一次地修改了 i 的值,最终函数退出后的返回值才会是defer修改过的值 58 | */ 59 | func A() int { //返回0 60 | var i int 61 | defer func() { 62 | i++ 63 | fmt.Println("defer2:", i) // 打印结果为 defer: 2 64 | }() 65 | defer func() { 66 | i++ 67 | fmt.Println("defer1:", i) // 打印结果为 defer: 1 68 | }() 69 | return i 70 | } 71 | 72 | func B() (i int) { //返回2 73 | defer func() { 74 | i++ 75 | fmt.Println("defer2:", i) // 打印结果为 defer: 2 76 | }() 77 | defer func() { 78 | i++ 79 | fmt.Println("defer1:", i) // 打印结果为 defer: 1 80 | }() 81 | return i 82 | } 83 | 84 | //测试defer性能和正常关闭性能 85 | type channel chan int 86 | 87 | func NoDefer() { 88 | ch1 := make(channel, 10) 89 | close(ch1) 90 | } 91 | func Defer() { 92 | ch2 := make(channel, 10) 93 | defer close(ch2) 94 | } 95 | -------------------------------------------------------------------------------- /grpc/helloworld_demo/server/hello_world_server_intercept.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "context" 5 | "go_common/grpc/helloworld_demo/impl" 6 | pb "go_common/grpc/helloworld_demo/proto" 7 | "log" 8 | "net" 9 | 10 | "google.golang.org/grpc" 11 | ) 12 | 13 | func StartServerIntercept() { 14 | 15 | lis, err := net.Listen("tcp", "127.0.0.1:8090") 16 | if err != nil { 17 | log.Fatalf("failed to listen: %v", err) 18 | } 19 | //创建grpc拦截器 20 | serverIntercept1 := func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { 21 | //做自己想做的事 22 | err = do(ctx) 23 | if err != nil { 24 | return 25 | } 26 | // 校验通过后继续处理请求 27 | return handler(ctx, req) 28 | } 29 | var opts []grpc.ServerOption 30 | opts = append(opts, grpc.UnaryInterceptor(serverIntercept1)) 31 | //将拦截器添加进去 32 | gRpcServer := grpc.NewServer(opts...) 33 | pb.RegisterHelloServiceServer(gRpcServer, &impl.HelloServiceServer{}) 34 | gRpcServer.Serve(lis) 35 | } 36 | 37 | /** 38 | 自定义方法,做自己想做的事,比如记录请求入参,出参 39 | */ 40 | func do(ctx context.Context) error { 41 | return nil 42 | } 43 | 44 | //创建拦截器链(思想是递归) 45 | func InterceptChain(intercepts ...grpc.UnaryServerInterceptor) grpc.UnaryServerInterceptor { 46 | //获取拦截器的长度 47 | l := len(intercepts) 48 | //如下我们返回一个拦截器 49 | return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { 50 | //在这个拦截器中,我们做一些操作 51 | //构造一个链 52 | chain := func(currentInter grpc.UnaryServerInterceptor, currentHandler grpc.UnaryHandler) grpc.UnaryHandler { 53 | return func(currentCtx context.Context, currentReq interface{}) (interface{}, error) { 54 | return currentInter(currentCtx, currentReq, info, currentHandler) 55 | } 56 | } 57 | //声明一个handler 58 | chainHandler := handler 59 | for i := l - 1; i >= 0; i-- { 60 | //递归一层一层调用 61 | chainHandler = chain(intercepts[i], chainHandler) 62 | } 63 | //返回结果 64 | return chainHandler(ctx, req) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /boltdb/boltdb_study.go: -------------------------------------------------------------------------------- 1 | package boltdb 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "math/rand" 7 | "os" 8 | "strconv" 9 | "time" 10 | 11 | "github.com/boltdb/bolt" 12 | ) 13 | 14 | //以读写的方式打开一个数据库 15 | func OpenBolt() { 16 | fileDB, err := bolt.Open("my.db", os.FileMode(0600), nil) 17 | if err != nil { 18 | log.Fatal("open boltdb error:", err) 19 | } 20 | defer fileDB.Close() 21 | } 22 | 23 | //以读写的方式打开一个数据库,带有超时时间 24 | func OpenBoltOption() { 25 | fileDB, err := bolt.Open("my.db", os.FileMode(0600), &bolt.Options{Timeout: 1 * time.Second}) 26 | 27 | if err != nil { 28 | log.Fatal("open boltdb error:", err) 29 | } 30 | defer fileDB.Close() 31 | } 32 | 33 | func BoltUpdate() { 34 | fmt.Println(os.Getpagesize()) 35 | fileDB, err := bolt.Open("my.db", os.FileMode(0600), &bolt.Options{Timeout: 1 * time.Second}) 36 | defer fileDB.Close() 37 | if err != nil { 38 | log.Fatal("open boltdb error:", err) 39 | } 40 | start := time.Now().Unix() 41 | fileDB.Update(func(tx *bolt.Tx) error { 42 | //创建一个bucket,如果存在什么也不做 43 | bucket, err := tx.CreateBucketIfNotExists([]byte("test.bucket")) 44 | if err != nil { 45 | log.Fatal("create bucket error:", err) 46 | } 47 | //设置一个随机数种子 48 | rand.Seed(time.Now().Unix()) 49 | for i := 0; i < 1000000; i++ { 50 | bucket.Put([]byte("EMG"+strconv.Itoa(rand.Intn(1000000)+1000000)), []byte("ss")) 51 | } 52 | return nil 53 | }) 54 | end := time.Now().Unix() 55 | 56 | log.Println(end - start) 57 | } 58 | 59 | func BoltBatch() { 60 | fileDB, err := bolt.Open("my.db", os.FileMode(0600), &bolt.Options{Timeout: 1 * time.Second}) 61 | defer fileDB.Close() 62 | if err != nil { 63 | log.Fatal("open boltdb error:", err) 64 | } 65 | fileDB.Batch(func(tx *bolt.Tx) error { 66 | //创建一个bucket,如果存在什么也不做 67 | bucket, err := tx.CreateBucketIfNotExists([]byte("test1.bucket")) 68 | if err != nil { 69 | log.Fatal("create bucket error:", err) 70 | } 71 | for i := 0; i < 1000000; i++ { 72 | bucket.Put([]byte(strconv.Itoa(i)), []byte("ss")) 73 | } 74 | return nil 75 | }) 76 | } 77 | -------------------------------------------------------------------------------- /algorithm/bitmap.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "bytes" 5 | ) 6 | 7 | //BitMap实现 8 | type BitMap []uint64 9 | 10 | const ( 11 | Address_Bits_Per_Word uint8 = 6 12 | Words_Per_Size uint64 = 64 //64位 13 | ) 14 | 15 | /** 16 | 创建指定初始化大小的BitMap 17 | */ 18 | func NewBitMap(nbits int) *BitMap { 19 | //得出需要多少个unit64的长度, 一个unit64 占8个字节,一个字节占8位 20 | //右移6位相当于处于64 21 | wordsLen := (nbits - 1) >> Address_Bits_Per_Word 22 | temp := BitMap(make([]uint64, wordsLen+1, wordsLen+1)) 23 | return &temp 24 | } 25 | 26 | /** 27 | 把指定位置设为ture 28 | */ 29 | func (this *BitMap) Set(bitIndex uint64) { 30 | wIndex := this.wordIndex(bitIndex) 31 | this.expandTo(wIndex) 32 | (*this)[wIndex] |= (uint64(0x01) << (bitIndex % Words_Per_Size)) 33 | } 34 | 35 | //设置指定位置为false 36 | func (this *BitMap) Clear(bitIndex uint64) { 37 | wIndex := this.wordIndex(bitIndex) 38 | if wIndex < len(*this) { 39 | (*this)[wIndex] &^= uint64(0x01) << (bitIndex % Words_Per_Size) 40 | } 41 | } 42 | 43 | //获取指定位置的值 44 | func (this *BitMap) Get(bitIndex uint64) bool { 45 | wIndex := this.wordIndex(bitIndex) 46 | return (wIndex < len(*this)) && ((*this)[wIndex]&(uint64(0x01)<<(bitIndex%Words_Per_Size)) != 0) 47 | } 48 | 49 | /** 50 | 以二进制串的格式打印bitMap内容 51 | */ 52 | func (this *BitMap) ToString() string { 53 | var temp uint64 54 | strAppend := &bytes.Buffer{} 55 | for i := 0; i < len(*this); i++ { 56 | temp = (*this)[i] 57 | for j := 0; j < 64; j++ { 58 | if temp&(uint64(0x01)<> Address_Bits_Per_Word) 71 | } 72 | 73 | //扩容:每次扩容两倍 74 | func (this *BitMap) expandTo(wordIndex int) { 75 | wordsRequired := wordIndex + 1 76 | if len(*this) < wordsRequired { 77 | if wordsRequired < 2*len(*this) { 78 | wordsRequired = 2 * len(*this) 79 | } 80 | newCap := make([]uint64, wordsRequired, wordsRequired) 81 | copy(newCap, *this) 82 | (*this) = newCap 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /algorithm/sort_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func Test_MaoPaoSort(t *testing.T) { 9 | intArray := MaoPaoSort([]int{1, 3, 2, 5, 0, 7}) 10 | t.Log(intArray) 11 | // Output: 12 | // [0,1,2,3,5,7] 13 | } 14 | 15 | //http://blog.studygolang.com/2017/10/how-to-test-with-go/ golang 单元测试 16 | func ExampleMaoPaoSort() { 17 | intArray := MaoPaoSort([]int{1, 3, 2, 5, 0, 7}) 18 | fmt.Println(intArray) 19 | // Output: 20 | // [0 1 2 3 5 7] 21 | } 22 | 23 | func Test_SelectSort(t *testing.T) { 24 | intArray := SelectSort([]int{1, 3, 2, 5}) 25 | t.Log(intArray) 26 | } 27 | 28 | func TestQuickSort(t *testing.T) { 29 | t.Log(QuickSort([]int{9, 243, 1, 7, 9, 3, 6, 0})) 30 | } 31 | 32 | func Test_InsertSort(t *testing.T) { 33 | intArray := InsertSort([]int{1, 3, 2, 5}) 34 | t.Log(intArray) 35 | } 36 | 37 | func Test_ShellSort(t *testing.T) { 38 | intArray := ShellSort([]int{0, 8, 5, 1, 3, 2}) 39 | t.Log(intArray) 40 | } 41 | func Test_SmallHeapSort(t *testing.T) { 42 | intArray := SmallHeapSort([]int{1, 2}) 43 | t.Log(intArray) 44 | } 45 | 46 | func Test_BigHeapSort(t *testing.T) { 47 | intArray := BigHeapSort([]int{3, 2, 3, 1, 2, 4, 5, 5, 6}) 48 | t.Log(intArray) 49 | } 50 | 51 | func TestMergeSort(t *testing.T) { 52 | t.Log(MergeSort([]int{3, 5, 1, 7, 2})) 53 | } 54 | func TestMergerSortNotRecursion(t *testing.T) { 55 | t.Log(MergerSortNotRecursion([]int{1, 3, -9, 6, 8, -19, 20, -20})) 56 | } 57 | func TestQuickSortNotRecursion(t *testing.T) { 58 | t.Log(QuickSortNotRecursion([]int{1, 3, -9, 6, 8, -19, 20, -20})) 59 | } 60 | 61 | func TestBucketSort(t *testing.T) { 62 | t.Log(BucketSort([]int{1, 4, 2, 5, 9, 2, 4, 5, 7, 8, 1})) 63 | } 64 | 65 | func TestStringMergerSort(t *testing.T) { 66 | d := StringMergerSort([]string{"asd", "ssssw", "s", "mmwdsasdw", "sdas"}) 67 | t.Log(d) 68 | } 69 | 70 | func TestQuickSort3(t *testing.T) { 71 | QuickSort3([][]int{{1, 3}, {1, 3}}) 72 | } 73 | 74 | func TestReorganizeString(t *testing.T) { 75 | ReorganizeString("aabbvfadqw") 76 | } 77 | 78 | func TestRadixSort(t *testing.T) { 79 | RadixSort([]string{"18091772262", "19083123122", "11083128312"}) 80 | } 81 | 82 | func TestBigHeapSort11(t *testing.T) { 83 | BigHeapSort11([]int{1, 3, -9, 6, 8, -1, 20, -20}) 84 | } 85 | -------------------------------------------------------------------------------- /basic/strconv_study.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | ) 7 | 8 | func StrconvStudy() { 9 | //ParseBoll 将字符串转换为布尔值 10 | // 它接受真值:1, t, T, TRUE, true, True 11 | // 它接受假值:0, f, F, FALSE, false, False. 12 | // 其它任何值都返回一个错误 13 | //func ParseBool(str string) (value bool, err error) 14 | fmt.Println(strconv.ParseBool("1")) 15 | fmt.Println(strconv.ParseBool("0")) 16 | // FormatBool 将布尔值转换为字符串 "true" 或 "false" 17 | fmt.Println(strconv.FormatBool(true)) 18 | fmt.Println(strconv.FormatBool(false)) 19 | // ParseFloat 将字符串转换为浮点数 20 | //s:要转换的字符串 21 | // bitSize:指定浮点类型(32:float32、64:float64) 22 | // 如果 s 是合法的格式,而且接近一个浮点值, 23 | // 则返回浮点数的四舍五入值(依据 IEEE754 的四舍五入标准) 24 | // 如果 s 不是合法的格式,则返回“语法错误” 25 | // 如果转换结果超出 bitSize 范围,则返回“超出范围” 26 | fmt.Println(strconv.ParseFloat("2.333", 32)) 27 | fmt.Println(strconv.ParseFloat("2.333", 64)) 28 | 29 | // ParseInt 将字符串转换为 int 类型 30 | // s:要转换的字符串 31 | // base:进位制(2 进制到 36 进制) 32 | // bitSize:指定整数类型(0:int、8:int8、16:int16、32:int32、64:int64) 33 | // 返回转换后的结果和转换时遇到的错误 34 | // 如果 base 为 0,则根据字符串的前缀判断进位制(0x:16,0:8,其它:10) 35 | fmt.Println(strconv.ParseInt("20", 10, 0)) 36 | fmt.Println(strconv.ParseInt("0xFFF", 0, 0)) 37 | // 将字符串转化为int 38 | fmt.Println(strconv.Atoi("1")) 39 | fmt.Println(strconv.Atoi("-5")) 40 | 41 | // FormatUint 将 int 型整数 i 转换为字符串形式 42 | // base:进位制(2 进制到 36 进制) 43 | // 大于 10 进制的数,返回值使用小写字母 'a' 到 'z' 44 | //func FormatInt(i int64, base int) string 45 | fmt.Println(strconv.FormatInt(1, 10)) 46 | // 将int 转化为字符串 47 | fmt.Println(strconv.Itoa(-3)) 48 | 49 | // FormatFloat 将浮点数 f 转换为字符串值 50 | // f:要转换的浮点数 51 | // fmt:格式标记(b、e、E、f、g、G) 52 | // prec:精度(数字部分的长度,不包括指数部分) 53 | // bitSize:指定浮点类型(32:float32、64:float64) 54 | // 格式标记: 55 | // 'b' (-ddddp±ddd,二进制指数) 56 | // 'e' (-d.dddde±dd,十进制指数) 57 | // 'E' (-d.ddddE±dd,十进制指数) 58 | // 'f' (-ddd.dddd,没有指数) 59 | // 'g' ('e':大指数,'f':其它情况) 60 | // 'G' ('E':大指数,'f':其它情况) 61 | // 如果格式标记为 'e','E'和'f',则 prec 表示小数点后的数字位数 62 | // 如果格式标记为 'g','G',则 prec 表示总的数字位数(整数部分+小数部分) 63 | //func FormatFloat(f float64, fmt byte, prec, bitSize int) string 64 | 65 | fmt.Println(strconv.FormatFloat(2.44, 'f', 10, 64)) //2.4400000000 66 | fmt.Println(strconv.FormatFloat(2.44, 'g', 10, 64)) //2.44 67 | fmt.Println(strconv.FormatFloat(2.44, 'G', 10, 64)) //2.44 68 | 69 | } 70 | -------------------------------------------------------------------------------- /grpc/helloworld_demo/register_center/etcd_register.go: -------------------------------------------------------------------------------- 1 | package register_center 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "log" 7 | 8 | "github.com/coreos/etcd/clientv3" 9 | "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes" 10 | ) 11 | 12 | type etcdRegisterImpl struct { 13 | Address string 14 | } 15 | 16 | //创建etcd的注册结构体 17 | func NewEtcdRegisterImpl(target string) *etcdRegisterImpl { 18 | return &etcdRegisterImpl{Address: target} 19 | } 20 | 21 | //etcd 实现注册接口 22 | func (etcd *etcdRegisterImpl) Register(info ServiceDescInfo) error { 23 | 24 | client, err := clientv3.NewFromURL(etcd.Address) 25 | if err != nil { 26 | log.Println("连接etcd失败:", err) 27 | return err 28 | } 29 | // minimum lease TTL is ttl-second 30 | resp, err := client.Grant(context.TODO(), int64(info.IntervalTime)) 31 | if err != nil { 32 | log.Println("创建租约失败:", err) 33 | return err 34 | } 35 | // should get first, if not exist, set it 36 | _, err = client.Get(context.Background(), info.ServiceName) 37 | serviceValue := fmt.Sprintf("%s:%d", info.Host, info.Port) 38 | if err != nil { 39 | if err == rpctypes.ErrKeyNotFound { 40 | if _, err := client.Put(context.TODO(), info.ServiceName, serviceValue, clientv3.WithLease(resp.ID)); err != nil { 41 | log.Printf("etcd: set service '%s' with ttl to etcd3 failed: %s", info.ServiceName, err.Error()) 42 | } 43 | } else { 44 | log.Printf("etcd: service '%s' connect to etcd3 failed: %s", info.ServiceName, err.Error()) 45 | return err 46 | } 47 | } else { 48 | // refresh set to true for not notifying the watcher 49 | if _, err := client.Put(context.Background(), info.ServiceName, serviceValue, clientv3.WithLease(resp.ID)); err != nil { 50 | log.Printf("etcd: refresh service '%s' with ttl to etcd3 failed: %s", info.ServiceName, err.Error()) 51 | return err 52 | } 53 | } 54 | log.Println("register successful") 55 | return nil 56 | } 57 | 58 | //etcd 实现下线接口 59 | func (etcd *etcdRegisterImpl) UnRegister(info ServiceDescInfo) error { 60 | client, err := clientv3.NewFromURL(etcd.Address) 61 | if _, err := client.Delete(context.Background(), info.ServiceName); err != nil { 62 | log.Printf("etcd: deregister '%s' failed: %s", info.ServiceName, err.Error()) 63 | } else { 64 | log.Printf("etcd: deregister '%s' ok.", info.ServiceName) 65 | } 66 | return err 67 | } 68 | -------------------------------------------------------------------------------- /event_bus/network_event_bus/network_bus.go: -------------------------------------------------------------------------------- 1 | package EventBus 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "net" 7 | "net/http" 8 | "net/rpc" 9 | "sync" 10 | "go_common/event_bus" 11 | ) 12 | 13 | // NetworkBus - object capable of subscribing to remote event buses in addition to remote event 14 | // busses subscribing to it's local event bus. Compoed of a server and client 15 | type NetworkBus struct { 16 | *Client 17 | *Server 18 | service *NetworkBusService 19 | sharedBus EventBus.Bus 20 | address string 21 | path string 22 | } 23 | 24 | // NewNetworkBus - returns a new network bus object at the server address and path 25 | func NewNetworkBus(address, path string) *NetworkBus { 26 | bus := new(NetworkBus) 27 | bus.sharedBus = EventBus.New() 28 | bus.Server = NewServer(address, path, bus.sharedBus) 29 | bus.Client = NewClient(address, path, bus.sharedBus) 30 | bus.service = &NetworkBusService{&sync.WaitGroup{}, false} 31 | bus.address = address 32 | bus.path = path 33 | return bus 34 | } 35 | 36 | // EventBus - returns wrapped event bus 37 | func (networkBus *NetworkBus) EventBus() EventBus.Bus { 38 | return networkBus.sharedBus 39 | } 40 | 41 | // NetworkBusService - object capable of serving the network bus 42 | type NetworkBusService struct { 43 | wg *sync.WaitGroup 44 | started bool 45 | } 46 | 47 | // Start - helper method to serve a network bus service 48 | func (networkBus *NetworkBus) Start() error { 49 | var err error 50 | service := networkBus.service 51 | clientService := networkBus.Client.service 52 | serverService := networkBus.Server.service 53 | if !service.started { 54 | server := rpc.NewServer() 55 | server.RegisterName("ServerService", serverService) 56 | server.RegisterName("ClientService", clientService) 57 | server.HandleHTTP(networkBus.path, "/debug"+networkBus.path) 58 | l, e := net.Listen("tcp", networkBus.address) 59 | if e != nil { 60 | err = fmt.Errorf("listen error: %v", e) 61 | } 62 | service.wg.Add(1) 63 | go http.Serve(l, nil) 64 | } else { 65 | err = errors.New("Server bus already started") 66 | } 67 | return err 68 | } 69 | 70 | // Stop - signal for the service to stop serving 71 | func (networkBus *NetworkBus) Stop() { 72 | service := networkBus.service 73 | if service.started { 74 | service.wg.Done() 75 | service.started = false 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /basic/list_study.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "container/list" 5 | "fmt" 6 | ) 7 | 8 | type TreeNodeNew struct { 9 | Val int 10 | Left *TreeNodeNew 11 | Right *TreeNodeNew 12 | } 13 | 14 | func QueueStudy() { 15 | 16 | queue := list.New() 17 | 18 | left := &TreeNodeNew{1, nil, nil} 19 | right := &TreeNodeNew{3, nil, nil} 20 | root := &TreeNodeNew{2, left, right} 21 | 22 | //往队列末尾添加一个 23 | queue.PushBack(*root) 24 | //从队列头部区取一个 25 | e := queue.Front() 26 | // 将取出的元素转换为struct类型 27 | temp := e.Value.(TreeNodeNew) 28 | //删除一个元素 29 | queue.Remove(e) 30 | fmt.Println(temp) 31 | 32 | queue.PushBack(1) 33 | queue.PushBack(2) 34 | queue.PushBack(3) 35 | queue.PushBack(4) 36 | backE := queue.Back() 37 | // 将元素backE移动到list的首部 38 | queue.MoveToFront(backE) 39 | fmt.Println(queue.Front().Value) 40 | 41 | //func (l *List) MoveAfter(e, mark *Element) //将元素e移动到元素mark之后,如果元素e或者mark不属于list l,或者e==mark,则list l不改变。 42 | //func (l *List) MoveBefore(e, mark *Element)//将元素e移动到元素mark之前,如果元素e或者mark不属于list l,或者e==mark,则list l不改变。 43 | 44 | //func (l *List) MoveToBack(e *Element)//将元素e移动到list l的末尾,如果e不属于list l,则list不改变。 45 | //func (l *List) MoveToFront(e *Element)//将元素e移动到list l的首部,如果e不属于list l,则list不改变。 46 | //func (l *List) PushBack(v interface{}) *Element//在list l的末尾插入值为v的元素,并返回该元素。 47 | //func (l *List) PushBackList(other *List)//在list l的尾部插入另外一个list,其中l和other可以相等。 48 | //func (l *List) PushFront(v interface{}) *Element//在list l的首部插入值为v的元素,并返回该元素。 49 | //func (l *List) PushFrontList(other *List)//在list l的首部插入另外一个list,其中l和other可以相等。 50 | //func (l *List) Remove(e *Element) interface{}//如果元素e属于list l,将其从list中删除,并返回元素e的值。 51 | } 52 | 53 | type TreeNode struct { 54 | Val int 55 | Left *TreeNode 56 | Right *TreeNode 57 | } 58 | 59 | func rightSideView(root *TreeNode) []int { 60 | res := make([]int, 0, 0) 61 | if root == nil { 62 | return res 63 | } 64 | queue := list.New() 65 | queue.PushBack(*root) 66 | for queue.Len() > 0 { 67 | res = append(res, queue.Back().Value.(TreeNode).Val) 68 | newQueue := list.New() 69 | for queue.Len() > 0 { 70 | e := queue.Front() 71 | temp := e.Value.(TreeNode) 72 | queue.Remove(e) 73 | if temp.Left != nil { 74 | newQueue.PushBack(*temp.Left) 75 | } 76 | if temp.Right != nil { 77 | newQueue.PushBack(*temp.Right) 78 | } 79 | } 80 | queue.PushBackList(newQueue) 81 | } 82 | return res 83 | } 84 | -------------------------------------------------------------------------------- /algorithm/token_bucket.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | "time" 7 | ) 8 | 9 | /** 10 | 令牌桶限流算法 11 | */ 12 | const ( 13 | /** 14 | 默认时间间隔 15 | */ 16 | INTERVAL = time.Second * 1 17 | /** 18 | 时间间隔内放入令牌的个数(比如时间间隔为1秒,那就是每隔一秒放入100 个令牌) 19 | */ 20 | INTERVAL_IN_TOKEN = 100 21 | /** 22 | 令牌桶初始时的令牌个数 23 | */ 24 | AVAIL_TOKEN = 100 25 | ) 26 | 27 | type TokenBucket struct { 28 | interval time.Duration //时间间隔 29 | ticker *time.Ticker //定时器 30 | cap int // 桶容量 31 | avail int //桶内一开始令牌数 32 | tokenArray []int //存储令牌的数组 33 | intervalInToken int //时间间隔内放入令牌的个数 34 | index int //数组放入令牌的下标处 35 | mutex sync.Mutex 36 | } 37 | 38 | /** 39 | 创建一个令牌通 40 | 入参为令牌桶的容量 41 | */ 42 | func NewTokenBucket(cap int) *TokenBucket { 43 | tokenBucket := &TokenBucket{ 44 | interval: INTERVAL, 45 | cap: cap, 46 | avail: AVAIL_TOKEN, 47 | tokenArray: make([]int, cap, cap), 48 | intervalInToken: INTERVAL_IN_TOKEN, 49 | index: 0, 50 | mutex: sync.Mutex{}, 51 | } 52 | go adjustTokenDaemon(tokenBucket) 53 | return tokenBucket 54 | } 55 | 56 | /** 57 | 调整令牌桶令牌的协程 58 | */ 59 | func adjustTokenDaemon(tokenBucket *TokenBucket) { 60 | //如果桶内一开始的令牌小于初始令牌,开始放入初始令牌 61 | for tokenBucket.index < tokenBucket.avail { 62 | tokenBucket.tokenArray[tokenBucket.index] = 1 63 | tokenBucket.index++ 64 | } 65 | tokenBucket.ticker = time.NewTicker(tokenBucket.interval) 66 | go func(t *time.Ticker) { 67 | for { 68 | <-t.C 69 | putToken(tokenBucket) 70 | } 71 | }(tokenBucket.ticker) 72 | } 73 | func putToken(tokenBucket *TokenBucket) { 74 | tokenBucket.mutex.Lock() 75 | for i := 0; i < tokenBucket.intervalInToken; i++ { 76 | if tokenBucket.index > tokenBucket.cap-1 { 77 | fmt.Println("令牌通已满") 78 | break 79 | } 80 | tokenBucket.tokenArray[tokenBucket.index] = 1 81 | tokenBucket.index++ 82 | fmt.Println("放入令牌成功") 83 | } 84 | defer tokenBucket.mutex.Unlock() 85 | } 86 | 87 | /** 88 | 从令牌桶弹出一个令牌,如果令牌通有令牌,返回true,否则返回false 89 | */ 90 | func (tokenBucket *TokenBucket) PopToken() bool { 91 | defer tokenBucket.mutex.Unlock() 92 | tokenBucket.mutex.Lock() 93 | if tokenBucket.index <= 0 { 94 | return false 95 | } 96 | tokenBucket.tokenArray[tokenBucket.index-1] = 0 97 | tokenBucket.index-- 98 | return true 99 | } 100 | -------------------------------------------------------------------------------- /algorithm/one_link_list_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestAdd(t *testing.T) { 9 | linkList := AddTail(nil, 1) 10 | linkList = AddTail(linkList, 2) 11 | linkList = AddTail(linkList, 3) 12 | linkList = AddTail(linkList, 4) 13 | linkList = AddTail(linkList, 5) 14 | 15 | } 16 | 17 | func TestRevers(t *testing.T) { 18 | linkList := AddTail(nil, 3) 19 | linkList = AddTail(linkList, 4) 20 | linkList = AddTail(linkList, 5) 21 | linkList = Revers(linkList) 22 | Print(linkList) 23 | } 24 | 25 | func TestDeleteCurrentNode(t *testing.T) { 26 | linkList := AddTail(nil, 3) 27 | linkList = AddTail(linkList, 4) 28 | linkList = DeleteCurrentNode(linkList) 29 | Print(linkList) 30 | } 31 | 32 | func TestFindCenterNode(t *testing.T) { 33 | linkList := AddTail(nil, 3) 34 | linkList = AddTail(linkList, 4) 35 | linkList = AddTail(linkList, 5) 36 | temp := FindCenterNode(linkList) 37 | fmt.Println(temp.Value) 38 | } 39 | 40 | func TestFindReciprocalNode(t *testing.T) { 41 | linkList := AddTail(nil, 3) 42 | linkList = AddTail(linkList, 4) 43 | linkList = AddTail(linkList, 5) 44 | temp := FindReciprocalNode(linkList, 1) 45 | if temp != nil { 46 | fmt.Println(temp.Value) 47 | } 48 | Print(linkList) 49 | } 50 | 51 | func TestDeleteNthFromEnd(t *testing.T) { 52 | linkList := AddTail(nil, 3) 53 | linkList = AddTail(linkList, 4) 54 | linkList = AddTail(linkList, 5) 55 | linkList = DeleteNthFromEnd(linkList, 3) 56 | Print(linkList) 57 | } 58 | 59 | func TestMergeSortLinkList(t *testing.T) { 60 | linklist1 := AddTail(nil, 1) 61 | linklist1 = AddTail(linklist1, 2) 62 | linklist1 = AddTail(linklist1, 4) 63 | linklist1 = AddTail(linklist1, 5) 64 | linklist2 := AddTail(nil, 0) 65 | 66 | three := MergeSortLinkList(nil, linklist2) 67 | Print(three) 68 | } 69 | 70 | func TestDeleteNode(t *testing.T) { 71 | linklist1 := AddTail(nil, 1) 72 | linklist1 = AddTail(linklist1, 2) 73 | linklist1 = AddTail(linklist1, 4) 74 | linklist1 = AddTail(linklist1, 1) 75 | linklist1 = DeleteAppointValueNode(linklist1, 1) 76 | Print(linklist1) 77 | } 78 | 79 | func TestSortOneLinkList(t *testing.T) { 80 | linklist1 := AddTail(nil, 1) 81 | linklist1 = AddTail(linklist1, 2) 82 | linklist1 = AddTail(linklist1, 4) 83 | linklist1 = AddTail(linklist1, 5) 84 | linklist1 = AddTail(linklist1, 0) 85 | Print(MergerSortOneLinkList(linklist1)) 86 | } 87 | 88 | func TestInsertSortOneLinkList(t *testing.T) { 89 | linklist1 := AddTail(nil, 4) 90 | linklist1 = AddTail(linklist1, 2) 91 | linklist1 = AddTail(linklist1, 1) 92 | linklist1 = AddTail(linklist1, 3) 93 | Print(InsertSortOneLinkList(linklist1)) 94 | 95 | } 96 | -------------------------------------------------------------------------------- /serialize/serialize_study_test.go: -------------------------------------------------------------------------------- 1 | package serialize 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | "time" 7 | ) 8 | 9 | //987 10 | func TestJsonSerialize(t *testing.T) { 11 | start := time.Now().UnixNano() 12 | bs := JsonSerialize() 13 | end := time.Now().UnixNano() 14 | fmt.Println((end - start), "ns", len(bs)) 15 | fmt.Println(string(bs[1:7])) 16 | } 17 | 18 | func TestJsonDeSerialize(t *testing.T) { 19 | start := time.Now().UnixNano() 20 | JsonDeSerialize(jsonBs) 21 | end := time.Now().UnixNano() 22 | fmt.Println((end - start), "ns") 23 | 24 | } 25 | 26 | //396 27 | func TestProto3Serialize(t *testing.T) { 28 | start := time.Now().UnixNano() 29 | bs := Proto3Serialize() 30 | end := time.Now().UnixNano() 31 | fmt.Println((end - start), "ns", len(bs)) 32 | } 33 | 34 | //750 35 | func TestMsgPackSerialize(t *testing.T) { 36 | start := time.Now().UnixNano() 37 | bs := MsgPackSerialize() 38 | end := time.Now().UnixNano() 39 | fmt.Println((end - start), "ns", len(bs), bs) 40 | } 41 | 42 | //1287 43 | func TestXmlSerialize(t *testing.T) { 44 | start := time.Now().UnixNano() 45 | bs := XmlSerialize() 46 | end := time.Now().UnixNano() 47 | fmt.Println((end - start), "ns", len(bs)) 48 | fmt.Println(string(bs)) 49 | } 50 | 51 | func BenchmarkProto3Serialize(b *testing.B) { 52 | b.ResetTimer() 53 | for i := 0; i < b.N; i++ { 54 | Proto3Serialize() 55 | } 56 | } 57 | 58 | var protoBs = Proto3Serialize() 59 | 60 | func BenchmarkProto3DeSerialize(b *testing.B) { 61 | b.ResetTimer() 62 | for i := 0; i < b.N; i++ { 63 | Proto3DeSerialize(protoBs) 64 | } 65 | } 66 | 67 | func BenchmarkJsonSerialize(b *testing.B) { 68 | b.ResetTimer() 69 | for i := 0; i < b.N; i++ { 70 | JsonSerialize() 71 | } 72 | } 73 | 74 | var jsonBs = JsonSerialize() 75 | 76 | func BenchmarkJsonDeSerialize(b *testing.B) { 77 | b.ResetTimer() 78 | for i := 0; i < b.N; i++ { 79 | JsonDeSerialize(jsonBs) 80 | } 81 | } 82 | 83 | func BenchmarkMsgPackSerialize(b *testing.B) { 84 | b.ResetTimer() 85 | for i := 0; i < b.N; i++ { 86 | MsgPackSerialize() 87 | } 88 | } 89 | 90 | var msgPackJson = MsgPackSerialize() 91 | 92 | func BenchmarkMsgPackDeSerialize(b *testing.B) { 93 | b.ResetTimer() 94 | for i := 0; i < b.N; i++ { 95 | MsgPackDeSerialize(msgPackJson) 96 | } 97 | } 98 | 99 | func BenchmarkXmlSerialize(b *testing.B) { 100 | b.ResetTimer() 101 | for i := 0; i < b.N; i++ { 102 | XmlSerialize() 103 | } 104 | } 105 | 106 | var xmlBs = XmlSerialize() 107 | 108 | func BenchmarkXmlDeSerialize(b *testing.B) { 109 | b.ResetTimer() 110 | for i := 0; i < b.N; i++ { 111 | XmlDeSerialize(xmlBs) 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /algorithm/ahocorasick_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "testing" 7 | ) 8 | 9 | func Test1(t *testing.T) { 10 | ac := NewMatcher() 11 | 12 | dictionary := []string{"she", "he", "say", "shr", "her"} 13 | ac.Build(dictionary) 14 | 15 | ret := ac.Match("yasherhs") 16 | fmt.Println(ret) 17 | if len(ret) != 3 || ret[0] != 0 || ret[1] != 1 || ret[2] != 4 { 18 | t.Fatal() 19 | } 20 | 21 | ret = ac.Match("yasherhs") 22 | if len(ret) != 3 || ret[0] != 0 || ret[1] != 1 || ret[2] != 4 { 23 | t.Fatal() 24 | } 25 | 26 | if ac.GetMatchResultSize("yasherhs") != 3 { 27 | t.Fatal() 28 | } 29 | } 30 | 31 | func Test2(t *testing.T) { 32 | ac := NewMatcher() 33 | 34 | dictionary := []string{"hello", "世界", "hello世界", "hello"} 35 | ac.Build(dictionary) 36 | 37 | ret := ac.Match("hello世界") 38 | if len(ret) != 4 { 39 | t.Fatal() 40 | } 41 | 42 | ret = ac.Match("世界") 43 | if len(ret) != 1 { 44 | t.Fatal() 45 | } 46 | 47 | ret = ac.Match("hello") 48 | if len(ret) != 2 { 49 | t.Fatal() 50 | } 51 | } 52 | 53 | func Test3(t *testing.T) { 54 | ac := NewMatcher() 55 | 56 | dictionary := []string{"abc", "bc", "ac", "bc", "de", "efg", "fgh", "hi", "abcd", "ac"} 57 | ac.Build(dictionary) 58 | 59 | ret := ac.Match("abcdefghij") 60 | if len(ret) != ac.GetMatchResultSize("abcdefghij") || len(ret) != 8 { 61 | t.Fatal() 62 | } 63 | 64 | ret = ac.Match("abcdef") 65 | if len(ret) != 5 { 66 | t.Fatal() 67 | } 68 | 69 | ret = ac.Match("acdejefg") 70 | if len(ret) != 4 { 71 | t.Fatal() 72 | } 73 | 74 | if len(ac.Match("abcd")) != 4 { 75 | t.Fatal() 76 | } 77 | 78 | if len(ac.Match("adefacde")) != 3 { 79 | t.Fatal() 80 | } 81 | 82 | ret = ac.Match("agbdfgiadafgha") 83 | if len(ret) != 1 || dictionary[ret[0]] != "fgh" { 84 | t.Fatal() 85 | } 86 | } 87 | 88 | func Benchmark1(b *testing.B) { 89 | ac := NewMatcher() 90 | 91 | dictionary := make([]string, 0) 92 | for i := 0; i < 200000; i++ { 93 | dictionary = append(dictionary, randWord(2, 6)) 94 | } 95 | ac.Build(dictionary) 96 | 97 | for i := 0; i < b.N; i++ { 98 | ret := ac.Match(randWord(5000, 10000)) 99 | if len(ret) > 0 { 100 | } 101 | } 102 | } 103 | 104 | func Benchmark2(b *testing.B) { 105 | ac := NewMatcher() 106 | 107 | dictionary := make([]string, 0) 108 | for i := 0; i < 200000; i++ { 109 | dictionary = append(dictionary, randWord(2, 6)) 110 | } 111 | ac.Build(dictionary) 112 | 113 | for i := 0; i < b.N; i++ { 114 | if ac.GetMatchResultSize(randWord(5000, 10000)) > 0 { 115 | } 116 | } 117 | } 118 | 119 | func randWord(m, n int) string { 120 | num := rand.Intn(n-m) + m 121 | var s string 122 | var a rune = 'a' 123 | 124 | for i := 0; i < num; i++ { 125 | c := a + rune(rand.Intn(26)) 126 | s = s + string(c) 127 | } 128 | 129 | return s 130 | } 131 | -------------------------------------------------------------------------------- /basic/context_study.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "sync" 7 | "time" 8 | ) 9 | 10 | func ContextWithTimeOutOne() { 11 | ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) 12 | //开启新的协程 13 | go func(ctx context.Context) { 14 | //模拟处理任务 15 | time.Sleep(10 * time.Second) 16 | fmt.Println("任务处理完成") 17 | cancel() 18 | }(ctx) 19 | select { 20 | case <-ctx.Done(): 21 | fmt.Println("context timeout") 22 | } 23 | } 24 | 25 | /** 26 | 超时控制,如果父context超时结束,子context超时也结束 ,哪怕父context超时设置1秒,子context超时设置3秒 27 | */ 28 | func ContextWithTimeOut() { 29 | wg := &sync.WaitGroup{} 30 | wg.Add(2) 31 | ctx, _ := context.WithTimeout(context.Background(), 2*time.Second) 32 | //开启新的协程 33 | go func(ctx context.Context, wg *sync.WaitGroup) { 34 | ctxA, _ := context.WithTimeout(ctx, 5*time.Second) 35 | ch := make(chan int) 36 | //开起新的协程 37 | go func(ctx context.Context, ch chan int, wg *sync.WaitGroup) { 38 | //模拟读取数据 39 | sumCh := make(chan int) 40 | go func(sumCh chan int) { 41 | sum := 10 42 | time.Sleep(3 * time.Second) 43 | sumCh <- sum 44 | }(sumCh) 45 | 46 | select { 47 | case <-ctx.Done(): 48 | wg.Done() 49 | fmt.Println("two done") 50 | case <-sumCh: 51 | wg.Done() 52 | } 53 | }(ctxA, ch, wg) 54 | 55 | select { 56 | case <-ctx.Done(): 57 | wg.Done() 58 | fmt.Println("one done") 59 | case <-ch: 60 | wg.Done() 61 | } 62 | }(ctx, wg) 63 | wg.Wait() 64 | } 65 | 66 | /** 67 | 手动编码取消,研发人员可控制的取消 68 | */ 69 | func ContextWithCancel() { 70 | wg := sync.WaitGroup{} 71 | wg.Add(1) 72 | ctx, cancel := context.WithCancel(context.Background()) 73 | go func(ctx context.Context) { 74 | select { 75 | case c := <-ctx.Done(): 76 | { 77 | fmt.Println(c) 78 | wg.Done() 79 | } 80 | } 81 | }(ctx) 82 | time.Sleep(1 * time.Second) 83 | cancel() 84 | wg.Wait() 85 | } 86 | 87 | /** 88 | 可延迟一定的时间取消,也可以手动编码取消 89 | */ 90 | func ContextWithDeadLine() { 91 | wg := &sync.WaitGroup{} 92 | wg.Add(1) 93 | ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(3*time.Second)) 94 | 95 | go func(wg *sync.WaitGroup, ctx context.Context) { 96 | select { 97 | case <-ctx.Done(): 98 | fmt.Println("ctx deadline done") 99 | wg.Done() 100 | } 101 | }(wg, ctx) 102 | time.Sleep(10 * time.Second) 103 | cancel() 104 | wg.Wait() 105 | } 106 | 107 | /** 108 | 上下文key value,根据key获取,当子context 获取不到对应key时,就取父的context获取 109 | */ 110 | func ContextWithValue() { 111 | wg := sync.WaitGroup{} 112 | wg.Add(1) 113 | ctx := context.WithValue(nil, "key", "value") 114 | go func(ctx context.Context) { 115 | ctxB := context.WithValue(ctx, "key1", "value1") 116 | v := ctx.Value("key") 117 | v1 := ctxB.Value("key1") 118 | v2 := ctxB.Value("key") 119 | fmt.Println(v, v1, v2) 120 | wg.Done() 121 | }(ctx) 122 | wg.Wait() 123 | } 124 | -------------------------------------------------------------------------------- /gotask/gotask.go: -------------------------------------------------------------------------------- 1 | package gotask 2 | 3 | import ( 4 | "sync" 5 | "time" 6 | ) 7 | 8 | /* 9 | * GoTask is a high-performance concurrent goroutine manager written in golang. 10 | * For this case, GoTask reduce your cpu rate and memory and make your project more efficency. 11 | */ 12 | type GoTask struct { 13 | wg sync.WaitGroup //wait for all gorotines finished 14 | tasks []GoTaskDetail //tasks 15 | maxTaskNum int //max count of gorotine 16 | quickMode bool //if set to quick mode, jobs will be executed when added 17 | curTaskNum int 18 | } 19 | 20 | /* 21 | * GoTaskDetail defines methods 22 | */ 23 | type GoTaskDetail struct { 24 | fn func(...interface{}) 25 | params interface{} 26 | } 27 | 28 | /* 29 | * Generate GoTask manager 30 | */ 31 | func NewGoTask(maxTaskNum int, quickMode bool) *GoTask { 32 | ret := &GoTask{ 33 | wg: sync.WaitGroup{}, 34 | tasks: make([]GoTaskDetail, 0), 35 | maxTaskNum: maxTaskNum, 36 | quickMode: quickMode, 37 | curTaskNum: 0, 38 | } 39 | return ret 40 | } 41 | 42 | /* 43 | * Add tasks 44 | */ 45 | func (self *GoTask) Add(task func(...interface{}), params ...interface{}) { 46 | if !self.quickMode { 47 | self.tasks = append(self.tasks, GoTaskDetail{ 48 | fn: task, 49 | params: params, 50 | }) 51 | } else { 52 | go func(v GoTaskDetail) { 53 | for { 54 | if self.curTaskNum < self.maxTaskNum { 55 | break 56 | } 57 | // time.Sleep(time.Millisecond * 50) 58 | } 59 | self.wg.Add(1) 60 | self.curTaskNum++ 61 | defer func() { 62 | self.wg.Done() 63 | self.curTaskNum-- 64 | }() 65 | v.fn(v.params) 66 | }(GoTaskDetail{fn: task, params: params}) 67 | } 68 | } 69 | 70 | /* 71 | * Get paramters from context 72 | */ 73 | func (self *GoTask) GetParamter(index int, params interface{}) interface{} { 74 | if p, ok := params.([]interface{}); ok { 75 | if len(p) > 0 { 76 | if t, ok := p[0].([]interface{}); ok { 77 | if len(t) > index { 78 | return t[index] 79 | } 80 | } 81 | } 82 | } 83 | return nil 84 | } 85 | 86 | /* 87 | * Start concurrent tasks 88 | */ 89 | func (self *GoTask) Start() { 90 | if self.quickMode { 91 | self.wg.Wait() 92 | return 93 | } 94 | curTaskNum := 0 95 | for _, v := range self.tasks { 96 | self.wg.Add(1) 97 | curTaskNum++ 98 | go func(v GoTaskDetail) { 99 | defer func() { 100 | self.wg.Done() 101 | curTaskNum-- 102 | }() 103 | v.fn(v.params) 104 | }(v) 105 | for { 106 | if curTaskNum < self.maxTaskNum { 107 | break 108 | } 109 | time.Sleep(time.Millisecond * 50) 110 | } 111 | } 112 | self.wg.Wait() 113 | } 114 | 115 | /* 116 | * if set quickMode == true, you must invoke Done() to finish manually. Deprecated 117 | */ 118 | func (self *GoTask) Done() { 119 | if self.quickMode == false { 120 | return 121 | } 122 | self.wg.Done() 123 | return 124 | } 125 | -------------------------------------------------------------------------------- /event_bus/network_event_bus/network_bus_test.go: -------------------------------------------------------------------------------- 1 | package EventBus 2 | 3 | import ( 4 | "fmt" 5 | "go_common/event_bus" 6 | "testing" 7 | ) 8 | 9 | func TestNewServer(t *testing.T) { 10 | serverBus := NewServer(":2010", "/_server_bus_", EventBus.New()) 11 | serverBus.Start() 12 | if serverBus == nil || !serverBus.service.started { 13 | t.Log("New server EventBus not created!") 14 | t.Fail() 15 | } 16 | serverBus.Stop() 17 | } 18 | 19 | func TestNewClient(t *testing.T) { 20 | clientBus := NewClient(":2015", "/_client_bus_", EventBus.New()) 21 | clientBus.Start() 22 | if clientBus == nil || !clientBus.service.started { 23 | t.Log("New client EventBus not created!") 24 | t.Fail() 25 | } 26 | clientBus.Stop() 27 | } 28 | 29 | func TestRegister(t *testing.T) { 30 | serverPath := "/_server_bus_" 31 | serverBus := NewServer(":2010", serverPath, EventBus.New()) 32 | 33 | args := &SubscribeArg{serverBus.address, serverPath, PublishService, Subscribe, "topic"} 34 | reply := new(bool) 35 | 36 | serverBus.service.Register(args, reply) 37 | 38 | if serverBus.eventBus.HasCallback("topic_topic") { 39 | t.Fail() 40 | } 41 | if !serverBus.eventBus.HasCallback("topic") { 42 | t.Fail() 43 | } 44 | } 45 | 46 | func TestPushEvent(t *testing.T) { 47 | clientBus := NewClient("localhost:2015", "/_client_bus_", EventBus.New()) 48 | 49 | eventArgs := make([]interface{}, 1) 50 | eventArgs[0] = 10 51 | 52 | clientArg := &ClientArg{eventArgs, "topic"} 53 | reply := new(bool) 54 | 55 | fn := func(a int) { 56 | if a != 10 { 57 | t.Fail() 58 | } 59 | } 60 | 61 | clientBus.eventBus.Subscribe("topic", fn) 62 | clientBus.service.PushEvent(clientArg, reply) 63 | if !(*reply) { 64 | t.Fail() 65 | } 66 | } 67 | 68 | func TestServerPublish(t *testing.T) { 69 | serverBus := NewServer(":2020", "/_server_bus_b", EventBus.New()) 70 | serverBus.Start() 71 | 72 | fn := func(a int) { 73 | if a != 10 { 74 | t.Fail() 75 | } 76 | } 77 | 78 | clientBus := NewClient(":2025", "/_client_bus_b", EventBus.New()) 79 | clientBus.Start() 80 | 81 | clientBus.Subscribe("topic", fn, ":2010", "/_server_bus_b") 82 | 83 | serverBus.EventBus().Publish("topic", 10) 84 | 85 | clientBus.Stop() 86 | serverBus.Stop() 87 | } 88 | 89 | func TestNetworkBus(t *testing.T) { 90 | networkBusA := NewNetworkBus(":2035", "/_net_bus_A") 91 | networkBusA.Start() 92 | 93 | networkBusB := NewNetworkBus(":2030", "/_net_bus_B") 94 | networkBusB.Start() 95 | 96 | fnA := func(a int) { 97 | if a != 10 { 98 | t.Fail() 99 | } 100 | fmt.Println(a) 101 | } 102 | networkBusA.Subscribe("topic-A", fnA, ":2030", "/_net_bus_B") 103 | networkBusB.EventBus().Publish("topic-A", 10) 104 | 105 | fnB := func(a int) { 106 | if a != 20 { 107 | t.Fail() 108 | } 109 | fmt.Println(a) 110 | } 111 | networkBusB.Subscribe("topic-B", fnB, ":2035", "/_net_bus_A") 112 | networkBusA.EventBus().Publish("topic-B", 20) 113 | 114 | networkBusA.Stop() 115 | networkBusB.Stop() 116 | } 117 | -------------------------------------------------------------------------------- /hystrix/hystrix_study.go: -------------------------------------------------------------------------------- 1 | package hystrix 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "net" 7 | "net/http" 8 | "strconv" 9 | "sync" 10 | "time" 11 | 12 | "github.com/afex/hystrix-go/hystrix" 13 | ) 14 | 15 | func init() { 16 | hystrix.ConfigureCommand("my_command", hystrix.CommandConfig{ 17 | //超时实践 18 | Timeout: 5000, 19 | //最大并发数 20 | MaxConcurrentRequests: 1, 21 | //错误百分比,错误率达到这个数值开启熔断 22 | ErrorPercentThreshold: 25, 23 | //当熔断器被打开后,SleepWindow的时间就是控制过多久后去尝试服务是否可用了(毫秒) 24 | SleepWindow: 10, 25 | //最小请求数,只有到达这个数量后才判断是否开启熔断 26 | RequestVolumeThreshold: 10, 27 | }) 28 | } 29 | 30 | //异步调用 31 | func HystrixAsyStudy() { 32 | wg := sync.WaitGroup{} 33 | wg.Add(1) 34 | 35 | result := make(chan string, 1) 36 | //定义依赖外部系统的函数 37 | f1 := func() error { 38 | // 处理业务系统(调用外部服务) 39 | fmt.Println("处理业务逻辑") 40 | result <- "处理结果" 41 | return nil 42 | } 43 | //回调函数,只有 err不为空,才会执行回调函数(如果发生了超时,超时之后也会回调) 44 | fallBack1 := func(err error) error { 45 | fmt.Println("回调函数") 46 | return err 47 | } 48 | errors := hystrix.Go("my_command", f1, fallBack1) 49 | select { 50 | case r := <-result: 51 | fmt.Println(r) 52 | case e := <-errors: 53 | fmt.Println(e) 54 | } 55 | hystrixStreamHandler := hystrix.NewStreamHandler() 56 | hystrixStreamHandler.Start() 57 | go http.ListenAndServe(net.JoinHostPort("127.0.0.1", "81"), hystrixStreamHandler) 58 | 59 | wg.Wait() 60 | } 61 | 62 | //同步调用 63 | func HystrixSynStudy() { 64 | result := make(chan string, 1) 65 | //定义依赖外部系统的函数 66 | f1 := func() error { 67 | // 处理业务系统(调用外部服务) 68 | fmt.Println("处理业务逻辑") 69 | time.Sleep(3 * time.Second) 70 | result <- "处理结果" 71 | return nil 72 | } 73 | //回调函数,只有 err不为空,才会执行回调函数(如果发生了超时,超时之后也会回调) 74 | fallBack1 := func(err error) error { 75 | fmt.Println("回调函数") 76 | return err 77 | } 78 | errors := hystrix.Do("my_command", f1, fallBack1) 79 | 80 | select { 81 | case r := <-result: 82 | fmt.Println(r) 83 | fmt.Println(errors) 84 | 85 | } 86 | } 87 | 88 | func HystrixCurrentStudy() { 89 | for i := 0; i < 1000; i++ { 90 | out := make(chan string, 1) 91 | err := hystrix.Go("my_command", func() error { 92 | out <- "结果" + strconv.Itoa(i) 93 | return nil 94 | }, func(e error) error { 95 | fmt.Println("回调") 96 | return e 97 | }) 98 | select { 99 | case r := <-out: 100 | fmt.Println(r) 101 | case e := <-err: 102 | fmt.Println(e) 103 | } 104 | } 105 | time.Sleep(100 * time.Second) 106 | } 107 | 108 | func HystrixRongDuanStudy() { 109 | 110 | for i := 0; i < 1000; i++ { 111 | out := make(chan string, 1) 112 | err := hystrix.Go("my_command", func() error { 113 | time.Sleep(50 * time.Millisecond) 114 | if i%2 == 0 { 115 | return errors.New("错误了") 116 | } 117 | out <- "结果" + strconv.Itoa(i) 118 | return nil 119 | }, nil) 120 | select { 121 | case r := <-out: 122 | fmt.Println(r) 123 | case e := <-err: 124 | fmt.Println(e) 125 | } 126 | } 127 | time.Sleep(100 * time.Second) 128 | } 129 | -------------------------------------------------------------------------------- /basic/reflection.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | ) 7 | 8 | /** 9 | golang 反射学习 10 | */ 11 | 12 | type User struct { 13 | Id int 14 | Name string 15 | Age int 16 | } 17 | 18 | type UserServiceImpl struct { 19 | } 20 | 21 | type UserService interface { 22 | /** 23 | 查询 24 | */ 25 | FindUserById() User 26 | /** 27 | 添加 28 | */ 29 | InsertUser(user User) 30 | } 31 | 32 | func (userServiceImpl UserServiceImpl) FindUserById() User { 33 | return User{2, "spw", 25} 34 | } 35 | 36 | func (userService UserServiceImpl) InsertUser(u User) { 37 | 38 | } 39 | 40 | func ReflectionStudy() { 41 | var num float64 = 1.234 42 | // 获取num变量的类型 43 | fmt.Println("type", reflect.TypeOf(num)) 44 | //获取num变量的遏制 45 | fmt.Println("value", reflect.ValueOf(num)) 46 | //获取num变量的值转化为float64 类型 (转换的时候区分是指针还是类型) 47 | fmt.Println("value", reflect.ValueOf(num).Interface().(float64)) 48 | // fmt.Println("value",reflect.ValueOf(num).Interface().(*float64)) panic 直接报错,golang 对类型要求非常严格 49 | 50 | /** 51 | 当是未知类型的时候 52 | */ 53 | user := User{1, "spw", 25} 54 | doFiled(user) 55 | 56 | userService := new(UserServiceImpl) 57 | doMethod(userService) 58 | } 59 | 60 | /** 61 | 通过反射获取结构体字段类型和值 62 | */ 63 | func doFiled(input interface{}) { 64 | getType := reflect.TypeOf(input) 65 | fmt.Println("get Type is :", getType.Name()) 66 | 67 | getValue := reflect.ValueOf(input) 68 | fmt.Println("get all Fields is:", getValue) 69 | 70 | //获取value是那种类型,此处结果是 struct 71 | fmt.Println(getValue.Kind()) 72 | 73 | // 获取方法字段 74 | // 1. 先获取interface的reflect.Type,然后通过NumField进行遍历 75 | // 2. 再通过reflect.Type的Field获取其Field 76 | // 3. 最后通过Field的Interface()得到对应的value 77 | for i := 0; i < getType.NumField(); i++ { 78 | field := getType.Field(i) 79 | value := getValue.Field(i).Interface() 80 | fmt.Printf("%s: %v = %v\n", field.Name, field.Type, value) 81 | } 82 | 83 | // 获取方法 84 | // 1. 先获取interface的reflect.Type,然后通过.NumMethod进行遍历 85 | for i := 0; i < getType.NumMethod(); i++ { 86 | m := getType.Method(i) 87 | fmt.Printf("%s: %v\n", m.Name, m.Type) 88 | } 89 | } 90 | 91 | /** 92 | 通过反射获取接口的方法 93 | */ 94 | func doMethod(input interface{}) { 95 | getValue := reflect.ValueOf(input) 96 | methodValue := getValue.MethodByName("FindUserById") 97 | fmt.Println(methodValue.Call(nil)[0]) 98 | 99 | getType := reflect.TypeOf(input) 100 | methodType, flag := getType.MethodByName("FindUserById") 101 | fmt.Println(methodType, flag) 102 | fmt.Println(methodType.Name) 103 | 104 | } 105 | 106 | /** 107 | 通过反射调用传递的函数 108 | */ 109 | func FuncReflection(f func(s string), str string) { 110 | fun := reflect.ValueOf(f) 111 | fun.Call(append(make([]reflect.Value, 0), reflect.ValueOf(str))) 112 | } 113 | 114 | func Reflect01(b interface{}) { 115 | pointer := reflect.TypeOf(b) 116 | switch pointer.Kind() { 117 | //是指针类型 118 | case reflect.Ptr: 119 | fmt.Println(pointer.Kind()) 120 | //不是指针类型 121 | default: 122 | fmt.Println(pointer.Kind()) 123 | } 124 | } 125 | 126 | //反射变量对应的Kind方法的返回值是基类型,并不是静态类型 127 | -------------------------------------------------------------------------------- /excel/read_and_write_excel.go: -------------------------------------------------------------------------------- 1 | package excel 2 | 3 | import ( 4 | "archive/zip" 5 | "fmt" 6 | "io" 7 | "io/ioutil" 8 | "os" 9 | "path/filepath" 10 | "strconv" 11 | 12 | "github.com/360EntSecGroup-Skylar/excelize" 13 | ) 14 | 15 | /** 16 | 返回的数据三维切片,第一维的大小是 sheet 第二维的大小是rows,不包含表头,第三维的大小是cells,一行多少列 17 | */ 18 | func ReadExcel(filePath string) ([][][]string, error) { 19 | excel, err := excelize.OpenFile(filePath) 20 | if err != nil { 21 | return nil, err 22 | } 23 | sheetMap := excel.GetSheetMap() 24 | sheets := make([][][]string, len(sheetMap)) 25 | 26 | for index, value := range sheetMap { 27 | rows := excel.GetRows(value) 28 | if len(rows) == 0 { 29 | fmt.Println(index, "sheet行数为空") 30 | continue 31 | } 32 | rowsString := make([][]string, len(rows)-1) 33 | for key, row := range rows { 34 | if key == 0 { // 第一行是表头 35 | continue 36 | } 37 | //循环工作表行数的每一列 38 | cellsString := make([]string, len(row)) 39 | for k, cell := range row { 40 | cellsString[k] = cell 41 | } 42 | rowsString[key-1] = cellsString 43 | } 44 | sheets[index-1] = rowsString 45 | } 46 | return sheets, nil 47 | } 48 | 49 | /** 50 | 第一个参数的源目录 51 | 第二个参数是解压后存放解压文件的目录 52 | */ 53 | func UnZipFile(sourceDir string, targetDir string) { 54 | //获取这个目录下的所有压缩文件 55 | filePathArray := getAllFile(sourceDir) 56 | for m, fileName := range filePathArray { 57 | // m 是为了防止不同压缩文件中的文件名重复给文件名加编号 58 | _, err := unzip(fileName, targetDir, m+1) 59 | if err != nil { 60 | fmt.Println(fileName, "解压失败", err) 61 | continue 62 | } 63 | } 64 | } 65 | func getAllFile(pathname string) []string { 66 | filePath := make([]string, 0, 0) 67 | rd, _ := ioutil.ReadDir(pathname) 68 | for _, fi := range rd { 69 | if fi.IsDir() { 70 | getAllFile(pathname + fi.Name() + "\\") 71 | } else { 72 | filePath = append(filePath, pathname+fi.Name()) 73 | } 74 | } 75 | return filePath 76 | } 77 | func unzip(archive, target string, m int) (string, error) { 78 | reader, err := zip.OpenReader(archive) 79 | if err != nil { 80 | fmt.Println(archive, "解析失败") 81 | return "", err 82 | } 83 | if err := os.MkdirAll(target, 0755); err != nil { 84 | return "", err 85 | } 86 | for _, file := range reader.File { 87 | path := filepath.Join(target, strconv.Itoa(m)+"_"+file.Name) 88 | if file.FileInfo().IsDir() { 89 | os.MkdirAll(path, file.Mode()) 90 | continue 91 | } 92 | fileReader, err := file.Open() 93 | if err != nil { 94 | return "", err 95 | } 96 | defer fileReader.Close() 97 | targetFile, err := os.Create(path) 98 | if err != nil { 99 | return "", err 100 | } 101 | defer targetFile.Close() 102 | if _, err := io.Copy(targetFile, fileReader); err == nil { 103 | return targetFile.Name(), nil 104 | } 105 | } 106 | return "", err 107 | } 108 | 109 | func WriteExcel(values [][]string, fileName string) { 110 | file := excelize.NewFile() 111 | for k, rows := range values { 112 | for i, v := range rows { 113 | r := rune(i + 97) 114 | s := strconv.QuoteRune(r) + strconv.Itoa(k+1) 115 | file.SetCellStr("Sheet1", s, v) 116 | } 117 | } 118 | file.SaveAs(fileName) 119 | } 120 | -------------------------------------------------------------------------------- /basic/file_study.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "io/ioutil" 7 | "os" 8 | "path" 9 | "path/filepath" 10 | "strings" 11 | "unicode/utf8" 12 | ) 13 | 14 | func FileStudy() { 15 | file, _ := os.Open("E:\\test.txt") 16 | 17 | data := make([]byte, 1024) 18 | file.Read(data) 19 | // 验证data字节是否uft-8编码 20 | fmt.Println(utf8.Valid(data)) 21 | // 从指定位置开始读取多少个字节,以下是从1025 位置开始读取6个字节 22 | o2, _ := file.Seek(5, 1026) 23 | b2 := make([]byte, 30) 24 | file.Read(b2) 25 | // 字节数组转换string字符串 26 | fmt.Println(data) 27 | fmt.Println(b2) 28 | fmt.Println(o2) 29 | 30 | // 将文件一次性去全部读取到内存 31 | bs, _ := ioutil.ReadFile("E:\\test.txt") 32 | fmt.Println(len(bs)) 33 | 34 | //获取文件的详细信息 35 | fileInfo, err := os.Stat("E:\\test.txt") 36 | //判断文件是否存在 37 | fmt.Println(os.IsNotExist(err)) //true 不存在 false 存在 38 | fmt.Println(fileInfo.IsDir()) // 是否是目录 false 39 | fmt.Println(fileInfo.Mode()) // 文件的权限 -rw-rw-rw- 40 | fmt.Println(fileInfo.ModTime()) // 最后修改时间 41 | //fileSys := fileInfo.Sys().(*syscall.Win32FileAttributeData) 42 | //fmt.Println(fileSys.CreationTime) 43 | ////获取文件最后写入的时间 44 | //fmt.Println(fileSys.LastWriteTime.Nanoseconds() / 1000 / 1000) 45 | //fmt.Println(time.Unix(fileSys.LastWriteTime.Nanoseconds()/1000/1000/1000, 0).Format("2006-01-02 15:04:05")) 46 | ////获取这个文件的字节大小 47 | //fmt.Println(fileSys.FileSizeLow) 48 | //按行读取文件 49 | reader := bufio.NewReader(file) 50 | for { 51 | //按行读取文件 52 | line, err := reader.ReadString('\n') //以'\n'为结束符读入一行 53 | if err != nil { 54 | break 55 | } 56 | //验证字符串是否是utf-8编码的 57 | fmt.Println(utf8.ValidString(line)) 58 | fmt.Println(strings.Trim(line, " ")) 59 | } 60 | createFile, _ := os.Create("E://testgo.txt") 61 | createFileInfo, _ := createFile.Stat() 62 | fmt.Println(createFileInfo.IsDir()) 63 | write := bufio.NewWriter(createFile) 64 | write.WriteString("go 创建的文件\n") 65 | write.Flush() 66 | 67 | // 创建目录 这样只会创建 spw 目录,同是也创建了test.txt 文件 68 | os.MkdirAll(path.Dir("E://qwe/test.txt"), os.ModePerm) 69 | // 这样回把test.txt 创建成一个文件夹 70 | os.MkdirAll("E://spw/test.txt", os.ModePerm) 71 | // 创建文件 72 | spw, _ := os.Create("E://spw/test.txt") 73 | fmt.Println(spw) 74 | 75 | defer func() { 76 | file.Close() 77 | createFile.Close() 78 | //spw.Close() 79 | }() 80 | 81 | // 返回是否是绝对路径 82 | fmt.Println(filepath.IsAbs("E:\\")) 83 | // 获取绝对路径 84 | fmt.Println(filepath.Abs("./src")) 85 | // 返回最后一个路径前面的路径 86 | fmt.Println(filepath.Dir("E:\\CodeWorkspce\\goProject\\goZiying")) 87 | //VolumeName函数返回最前面的卷名。如Windows系统里提供参数"C:\foo\bar"会返回"C:"; 88 | // Unix/linux系统的"\\host\share\foo"会返回"\\host\share";其他平台会返回""。 89 | fmt.Println(filepath.VolumeName("E:\\")) 90 | // 返回文件名的扩展 91 | fmt.Println(filepath.Ext("E:\\ccjf_price.sql")) 92 | 93 | /** 94 | 遍历某个目录下的所有文件或者文件夹(包含自身)然后调用WalkFunc 函数 95 | */ 96 | filepath.Walk("E:\\图片", func(path string, info os.FileInfo, err error) error { 97 | fmt.Println(path, info, err) 98 | return nil 99 | }) 100 | // 将路径中的分隔符替换为 斜杠 比如 \\ 替换为 / 101 | fmt.Println(filepath.ToSlash("E:\\goProject")) 102 | //FromSlash函数将path中的斜杠('/')替换为路径分隔符并返回替换结果,多个斜杠会替换为多个路径分隔符。 103 | fmt.Println(filepath.FromSlash("E://")) 104 | } 105 | -------------------------------------------------------------------------------- /basic/slice_study.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | //Go 语言切片是对数组的抽象。 9 | 10 | //Go 数组的长度不可改变,在特定场景中这样的集合就不太适用, 11 | //Go中提供了一种灵活,功能强悍的内置类型切片("动态数组"),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。 12 | 13 | // 声明切片 (未指定大小的数组) 14 | var slice1 []int 15 | var ar [1]int 16 | 17 | func SliceStudy() { 18 | 19 | // 使用make 函数创建切片,第一个参数为类型,第二个参数为长度length,第三个参数为容量 capacity 20 | slice1 = make([]int, 0, 2) 21 | 22 | fmt.Println(len(slice1), cap(slice1)) 23 | slice1 = append(slice1, 1) 24 | slice1 = append(slice1, 1) 25 | slice1 = append(slice1, 1) 26 | slice1 = append(slice1, 1) 27 | slice1 = append(slice1, 1) 28 | slice1 = append(slice1, 1) 29 | slice1 = append(slice1, 1) 30 | slice1 = append(slice1, 1) 31 | 32 | fmt.Println(len(slice1), cap(slice1)) 33 | 34 | //切片初始化 35 | slice2 := []int{1, 2, 3} 36 | slice11 := slice1[3:5] 37 | // len函数获取切片的长度 cap 函数获取切片的容量 38 | fmt.Println(slice2, len(slice2), cap(slice2), len(slice11), cap(slice11)) 39 | 40 | var arraySliceInt = [...]int{1, 2, 3, 4, 5, 6} 41 | 42 | slice3 := arraySliceInt[:] // 将数组赋值给切片 43 | slice4 := arraySliceInt[0:2] //数组下标0到2的值赋值给切片 ,不包含末尾 44 | slice5 := arraySliceInt[0:] //数组下标0到结尾赋值给切片 45 | slice6 := arraySliceInt[:5] //数组下标0开始到5赋值给切片, 不包含末尾 46 | fmt.Println(slice3) 47 | fmt.Println(slice4) 48 | fmt.Println(slice5) 49 | fmt.Println(slice6) 50 | 51 | slice7 := slice3[:] // 通过切片slice3初始化切片slice7 52 | fmt.Println(slice7) 53 | 54 | //切面的操作 55 | fmt.Println(slice7[1:5]) //打印子切面 56 | 57 | slice8 := append(slice7, 10) // append 方法给切面增加元素 58 | fmt.Println(slice8) 59 | var slice9 = make([]int, 20, len(slice8)*3) // 创建切片slice9 是slice8切面容量的两倍 60 | l := copy(slice9, slice8) // copy 方法把slice8 复制到 slice9,返会slice9 切面的长度 61 | fmt.Println(l) 62 | 63 | var ss []string 64 | print("func print", ss) 65 | //切片尾部追加元素append elemnt 66 | for i := 0; i < 10; i++ { 67 | ss = append(ss, fmt.Sprintf("s%d", i)) 68 | } 69 | print("after append", ss) 70 | //删除切片元素remove element at index 71 | index := 5 72 | ss = append(ss[:index], ss[index+1:]...) 73 | print("after delete", ss) 74 | //在切片中间插入元素insert element at index; 75 | //注意:保存后部剩余元素,必须新建一个临时切片 76 | rear := append([]string{}, ss[index:]...) 77 | ss = append(ss[0:index], "inserted") 78 | ss = append(ss, rear...) 79 | print("after insert", ss) 80 | 81 | t := []int{0} 82 | printPoint(t) // 0xc4200140a8 cap(s)= 1 83 | t = append(t, 1) 84 | printPoint(t) // 0xc4200140c0 0xc4200140c8 cap(s)= 2 85 | t = append(t, 2) 86 | printPoint(t) // 0xc4200160e0 0xc4200160e8 0xc4200160f0 cap(s)= 4 87 | t = append(t, 3) 88 | printPoint(t) // 0xc4200160e0 0xc4200160e8 0xc4200160f0 0xc4200160f8 cap(s)= 4 89 | 90 | s := make([]int, 2, 6) 91 | s[0] = 1 92 | s[1] = 2 93 | method1(s) 94 | fmt.Println(s) 95 | 96 | } 97 | 98 | func method1(s []int) { 99 | 100 | s[0] = 10 101 | fmt.Println(s, len(s), cap(s)) 102 | } 103 | 104 | func printPoint(s []int) { 105 | var temp []int 106 | 107 | fmt.Println(temp) 108 | for i := 0; i < len(s); i++ { 109 | fmt.Print(unsafe.Pointer(&s[i]), " ") 110 | 111 | } 112 | fmt.Println("cap(s)=", cap(s)) 113 | } 114 | 115 | func S() (int, int) { 116 | return 1, 1 117 | } 118 | -------------------------------------------------------------------------------- /algorithm/hashmap.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "hash/crc32" 5 | ) 6 | 7 | type HashMap struct { 8 | loadFactor float64 9 | rehashFactor int 10 | size int 11 | data []*Entry 12 | } 13 | 14 | type Entry struct { 15 | key string 16 | value string 17 | next *Entry 18 | } 19 | 20 | func NewHashMap() *HashMap { 21 | return &HashMap{ 22 | loadFactor: 0.75, 23 | rehashFactor: 2, 24 | size: 0, 25 | data: make([]*Entry, 16), 26 | } 27 | } 28 | 29 | /** 30 | key 相同的 value会覆盖 31 | */ 32 | func (hm *HashMap) Put(key, value string) { 33 | if float64(hm.size/len(hm.data)) > hm.loadFactor { 34 | rehash(hm) 35 | } 36 | hash := hashCode(key) 37 | index := getIndex(hash, len(hm.data)) 38 | entry := &Entry{ 39 | key: key, 40 | value: value, 41 | } 42 | oldEntry := hm.data[index] 43 | if oldEntry == nil { 44 | hm.data[index] = entry 45 | } else { 46 | for oldEntry != nil { 47 | if oldEntry.key == key { 48 | oldEntry.value = value 49 | return 50 | } 51 | if oldEntry.next == nil { 52 | oldEntry.next = entry 53 | break 54 | } 55 | oldEntry = oldEntry.next 56 | } 57 | } 58 | hm.size++ 59 | } 60 | 61 | /** 62 | 如果第二个参数返回 true,代表key存在,并第一个参数返回value 63 | 如果第二个参数返回false 代表key不存在,并第一个参数返回空串 64 | */ 65 | func (hm *HashMap) Get(key string) (string, bool) { 66 | hash := hashCode(key) 67 | index := getIndex(hash, len(hm.data)) 68 | en := hm.data[index] 69 | for en.next != nil { 70 | if en.key == key { 71 | return en.value, true 72 | } 73 | en = en.next 74 | } 75 | if en.key == key { 76 | return en.value, true 77 | } 78 | return "", false 79 | } 80 | 81 | func (hm *HashMap) Remove(key string) bool { 82 | 83 | return false 84 | } 85 | 86 | /** 87 | hash 扩容 88 | */ 89 | func rehash(hm *HashMap) { 90 | newData := make([]*Entry, hm.rehashFactor*len(hm.data)) 91 | for _, v := range hm.data { 92 | if v == nil { 93 | continue 94 | } 95 | if v != nil && v.next == nil { 96 | hash := hashCode(v.key) 97 | index := getIndex(hash, len(newData)) 98 | newData[index] = v 99 | continue 100 | } 101 | for v != nil { 102 | hash := hashCode(v.key) 103 | index := getIndex(hash, len(newData)) 104 | oldEntry := newData[index] 105 | if oldEntry == nil { 106 | en := &Entry{ 107 | key: v.key, 108 | value: v.value, 109 | } 110 | newData[index] = en 111 | } else { 112 | for oldEntry.next != nil { 113 | oldEntry = oldEntry.next 114 | } 115 | en := &Entry{ 116 | key: v.key, 117 | value: v.value, 118 | } 119 | oldEntry.next = en 120 | } 121 | v = v.next 122 | } 123 | } 124 | hm.data = newData 125 | } 126 | 127 | func getIndex(hash, dataLength int) int { 128 | return hash % dataLength 129 | } 130 | 131 | func hashCode(key interface{}) int { 132 | bs := make([]byte, 0) 133 | switch key.(type) { 134 | case string: 135 | bs = []byte(key.(string)) 136 | break 137 | default: 138 | panic("key type is error") 139 | } 140 | c := int(crc32.ChecksumIEEE(bs)) 141 | if c > 0 { 142 | return c 143 | } 144 | if -c > 0 { 145 | return -c 146 | } 147 | return 0 148 | } 149 | func (hm *HashMap) Size() int { 150 | return hm.size 151 | } 152 | -------------------------------------------------------------------------------- /basic/email.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "crypto/tls" 5 | "encoding/base64" 6 | "errors" 7 | "fmt" 8 | "log" 9 | "net" 10 | "net/smtp" 11 | "strings" 12 | ) 13 | 14 | // 邮件配置信息 15 | const ( 16 | ADDR = "" 17 | USER = "sunpengwei" //发送邮件的邮箱 18 | PASSWORD = "" //发送邮件邮箱的密码 19 | FROM = "" 20 | ) 21 | 22 | /** 23 | 发送邮件实体, to 发给谁, subject 邮件主题 message 邮件内容 24 | */ 25 | type Email struct { 26 | To string 27 | Subject string 28 | Message string 29 | } 30 | 31 | type LoginAuth struct { 32 | username, password string 33 | } 34 | 35 | /** 36 | 验证 37 | 38 | */ 39 | func NewLoginAuth(username, password string) smtp.Auth { 40 | 41 | return &LoginAuth{username, password} 42 | } 43 | 44 | func (a *LoginAuth) Start(server *smtp.ServerInfo) (string, []byte, error) { 45 | return "LOGIN", []byte{}, nil 46 | } 47 | 48 | func (a *LoginAuth) Next(fromServer []byte, more bool) ([]byte, error) { 49 | if more { 50 | fmt.Println(string(fromServer)) 51 | switch string(fromServer) { 52 | case "Username:": 53 | return []byte(a.username), nil 54 | case "Password:": 55 | return []byte(a.password), nil 56 | default: 57 | return nil, errors.New("Unknown fromServer") 58 | } 59 | } 60 | return nil, nil 61 | } 62 | 63 | func send(addr, subject string, a smtp.Auth, from string, to []string, msg []byte) error { 64 | c, err := smtp.Dial(addr) 65 | host, _, _ := net.SplitHostPort(addr) 66 | if err != nil { 67 | log.Println("call dial") 68 | return err 69 | } 70 | defer c.Close() 71 | 72 | if ok, _ := c.Extension("STARTTLS"); ok { 73 | config := &tls.Config{ServerName: host, InsecureSkipVerify: true} 74 | if err = c.StartTLS(config); err != nil { 75 | fmt.Println("call start tls") 76 | return err 77 | } 78 | } 79 | 80 | if a != nil { 81 | if ok, _ := c.Extension("AUTH"); ok { 82 | if err = c.Auth(a); err != nil { 83 | fmt.Println("check auth with err:", err) 84 | return err 85 | } 86 | } 87 | } 88 | 89 | if err = c.Mail(from); err != nil { 90 | return err 91 | } 92 | 93 | for _, addr := range to { 94 | if err = c.Rcpt(addr); err != nil { 95 | return err 96 | } 97 | } 98 | w, err := c.Data() 99 | if err != nil { 100 | return err 101 | } 102 | 103 | header := make(map[string]string) 104 | header["Subject"] = subject 105 | header["MIME-Version"] = "1.0" 106 | header["Content-Type"] = "text/plain; charset=\"utf-8\"" 107 | header["Content-Transfer-Encoding"] = "base64" 108 | message := "" 109 | for k, v := range header { 110 | message += fmt.Sprintf("%s: %s\r\n", k, v) 111 | } 112 | message += "\r\n" + base64.StdEncoding.EncodeToString(msg) 113 | _, err = w.Write([]byte(message)) 114 | if err != nil { 115 | return err 116 | } 117 | err = w.Close() 118 | if err != nil { 119 | return err 120 | } 121 | return c.Quit() 122 | } 123 | 124 | /** 125 | 发送邮件 126 | */ 127 | func SendMail(email *Email) { 128 | auth := NewLoginAuth(USER, PASSWORD) 129 | //auth := smtp.PlainAuth("", USER, PASSWORD, "mail.gomeplus.com") 130 | fmt.Println(auth) 131 | err := send(ADDR, email.Subject, auth, FROM, strings.Split(email.To, ","), []byte(email.Message)) 132 | if err != nil { 133 | log.Println("发送邮件失败", err) 134 | } else { 135 | log.Println("发送邮件成功") 136 | } 137 | 138 | } 139 | -------------------------------------------------------------------------------- /basic/string_study.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "strings" 7 | ) 8 | 9 | //Go语言支持以下2种形式的字符串: 10 | //1. 解释性字符串:带引号的字节序列。该类字符串使用双引号括起来,其中的相关的转义字符将被替换。例如: 11 | //str := "laoYu" 12 | //2. 原生字符串: 该类字符串使用反引号(注意:不是单引号)括起来,支持换行。例如: 13 | //str:=`This is a raw string \n` 14 | //上面原生字符串中的 \n 会被原样输出。 15 | 16 | func StringStudy() { 17 | 18 | str1 := "hello\ngo" 19 | 20 | fmt.Println(str1) // 会换行 21 | str2 := `hello \t go \n` 22 | 23 | fmt.Println(str2) //会原样输出 24 | 25 | str3 := "sunpengwei" 26 | //字符串函数包 27 | fmt.Println(len(str3)) //打印字符串长度 28 | 29 | fmt.Println(strings.HasPrefix(str3, "s")) // 判断是否以 s 开头 30 | fmt.Println(strings.HasSuffix(str3, "i")) // 判断是否以 i 结尾 31 | fmt.Println(strings.Contains(str3, "peng")) // 判断是否包含"peng"字符串 32 | fmt.Println(strings.ContainsAny(str3, "hy")) // 只要原始字符串中包含子字符串中的任意一个字符,都返回true,否则返回false 33 | // 比较两个字符串的大小,一模一样 返回0,str3 小于"www" 返回 -1,大于的话返回 1 34 | fmt.Println(strings.Compare(str3, "www")) 35 | fmt.Println(strings.Count(str3, "n")) // 统计字符串出现的次数 36 | fmt.Println(strings.EqualFold(str3, "sunpengwei")) // 比较两个字符串是否相等 37 | fmt.Println(strings.Fields(str3)) //将字符串转换为一个切片 38 | fmt.Println(strings.Split("s,p,w", ",")) // 根据子字符串切割,返回一个切片 39 | fmt.Println(strings.Repeat(str3, 5)) // 把字符串连接n次拼成一个新的字符串 40 | // 把字符串wei 替换成 yyy 0代表替换0次,-1 代表所有的wei都替换,1,2,3 分别代表替换几次 41 | fmt.Println(strings.Replace(str3, "wei", "yyy", -1)) 42 | // 根据子字符串切割,每个字符串保留分隔符(除了最后一个),返回一个切片 43 | fmt.Println(strings.SplitAfter("s,pp,w", ",")) 44 | fmt.Println(strings.Index(str3, "n")) // 返回字符串第一次出现的索引 45 | fmt.Println(strings.IndexAny(str3, "hnw")) // 返回字符串第一个被原始字符串包含的字符第一次出现的索引 46 | //使用空格连接字符串 47 | var s = make([]string, 0, 0) 48 | s = append(s, "sun", "peng") 49 | fmt.Println("Join", strings.Join(s, "")) 50 | 51 | fmt.Printf("[%q]", strings.Trim(" !!! Achtung !!! ", "! ")) // ["Achtung"] 52 | fmt.Printf("[%q]", strings.TrimLeft(" !!! Achtung !!! ", "! ")) // ["Achtung !!! "] 53 | fmt.Println(strings.TrimSpace(" a lone gopher ")) // a lone gopher 54 | 55 | // 拼接字符串比 + 速度快 56 | var buffer bytes.Buffer //Buffer是一个实现了读写方法的可变大小的字节缓冲 57 | for i := 0; i < 1000000; i++ { 58 | /* 59 | func (b *Buffer) WriteString(s string) (n int, err error) 60 | Write将s的内容写入缓冲中,如必要会增加缓冲容量。返回值n为len(p),err总是nil。如果缓冲变得太大,Write会采用错误值ErrTooLarge引发panic。 61 | */ 62 | buffer.WriteString("s") 63 | } 64 | 65 | fmt.Println("拼接后的结果为-->", buffer.String()) 66 | 67 | fmt.Println(string([]rune("2018-08-10")[:7])) 68 | } 69 | 70 | var hm = make(map[string]string, 8) 71 | var result = make([]string, 0) 72 | 73 | func LetterCombinations(digits string) []string { 74 | if len(digits) == 0 { 75 | return nil 76 | } 77 | hm["2"] = "abc" 78 | hm["3"] = "def" 79 | hm["4"] = "ghi" 80 | hm["5"] = "jkl" 81 | hm["6"] = "mno" 82 | hm["7"] = "pqrs" 83 | hm["8"] = "tuv" 84 | hm["9"] = "wxyz" 85 | 86 | backtrack("", digits) 87 | 88 | fmt.Println(result) 89 | return result 90 | } 91 | 92 | func backtrack(str, next_digits string) { 93 | if len(next_digits) == 0 { 94 | result = append(result, str) 95 | } else { 96 | v := next_digits[:1] 97 | temp := hm[v] 98 | for _, j := range temp { 99 | leter := j 100 | backtrack(str+string(leter), next_digits[1:]) 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /basic/pprof_study.go: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "math/rand" 7 | "net/http" 8 | _ "net/http/pprof" 9 | "os" 10 | "runtime/pprof" 11 | "time" 12 | ) 13 | 14 | // 针对web性能监测 ,引入 _ "net/http/pprof" 就可以了 15 | // 浏览器访问: http://localhost:8080/debug/pprof 16 | 17 | //debug/pprof/profile:访问这个链接会自动进行 CPU profiling,持续 30s,并生成一个文件供下载 18 | //debug/pprof/block:Goroutine阻塞事件的记录。默认每发生一次阻塞事件时取样一次。 19 | //debug/pprof/goroutines:活跃Goroutine的信息的记录。仅在获取时取样一次。 20 | //debug/pprof/heap: 堆内存分配情况的记录。默认每分配512K字节时取样一次。 21 | //debug/pprof/mutex: 查看争用互斥锁的持有者。 22 | //debug/pprof/threadcreate: 系统线程创建情况的记录。 仅在获取时取样一次 23 | 24 | var Count int64 = 0 25 | 26 | // go tool pprof http://127.0.0.1:9909/debug/pprof/profile 27 | func PprofWeb() { 28 | go func() { 29 | for { 30 | time.Sleep(3 * time.Millisecond) 31 | log.Println(Add("sunpengwei")) 32 | } 33 | }() 34 | err := http.ListenAndServe(":9999", nil) 35 | if err != nil { 36 | panic(err) 37 | } 38 | } 39 | 40 | var datas []string 41 | 42 | func Add(str string) string { 43 | data := []byte(str) 44 | sData := string(data) 45 | datas = append(datas, sData) 46 | 47 | return sData 48 | } 49 | 50 | func handlerData(w http.ResponseWriter, r *http.Request) { 51 | qUrl := r.URL 52 | fmt.Println(qUrl) 53 | fibRev := Fib() 54 | var fib uint64 55 | for i := 0; i < 1; i++ { 56 | fib = fibRev() 57 | fmt.Println("fib = ", fib) 58 | } 59 | str := RandomStr(RandomInt(100, 500)) 60 | str = fmt.Sprintf("Fib = %d; String = %s", fib, str) 61 | w.Write([]byte(str)) 62 | } 63 | 64 | func test(w http.ResponseWriter, r *http.Request) { 65 | fibRev := Fib() 66 | var fib uint64 67 | index := Count 68 | arr := make([]uint64, index) 69 | var i int64 70 | for ; i < index; i++ { 71 | fib = fibRev() 72 | arr[i] = fib 73 | fmt.Println("fib = ", fib) 74 | } 75 | time.Sleep(time.Millisecond * 500) 76 | str := fmt.Sprintf("Fib = %v", arr) 77 | w.Write([]byte(str)) 78 | } 79 | 80 | func Fib() func() uint64 { 81 | var x, y uint64 = 0, 1 82 | return func() uint64 { 83 | x, y = y, x+y 84 | return x 85 | } 86 | } 87 | 88 | var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890") 89 | 90 | func RandomStr(num int) string { 91 | seed := time.Now().UnixNano() 92 | if seed <= 0 { 93 | seed = time.Now().UnixNano() 94 | } 95 | rand.Seed(seed) 96 | b := make([]rune, num) 97 | for i := range b { 98 | b[i] = letterRunes[rand.Intn(len(letterRunes))] 99 | } 100 | return string(b) 101 | } 102 | 103 | func RandomInt(min, max int) int { 104 | rand.Seed(time.Now().UnixNano()) 105 | return rand.Intn(max-min+1) + min 106 | } 107 | 108 | func calCount() { 109 | timeInterval := time.Tick(time.Second) 110 | for { 111 | select { 112 | case i := <-timeInterval: 113 | Count = int64(i.Second()) 114 | } 115 | } 116 | } 117 | 118 | func PProfCPUApplication() { 119 | f, _ := os.Create("./cpu.prof") 120 | pprof.StartCPUProfile(f) 121 | 122 | for i := 1; i < 3000; i++ { 123 | time.Sleep(3 * time.Millisecond) 124 | RandomInt(10, 50) 125 | } 126 | pprof.StopCPUProfile() 127 | f.Close() 128 | } 129 | 130 | func PProfMemApplication() { 131 | f, _ := os.Create("./mem.prof") 132 | for i := 1; i < 3000; i++ { 133 | time.Sleep(3 * time.Millisecond) 134 | RandomInt(10, 50) 135 | } 136 | pprof.WriteHeapProfile(f) 137 | f.Close() 138 | } 139 | -------------------------------------------------------------------------------- /string_utils/string_utils_test.go: -------------------------------------------------------------------------------- 1 | package string_utils 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | // 字符串拼接的集中方法 9 | 10 | func BenchmarkAddStringWithOperator(b *testing.B) { 11 | for i := 0; i < b.N; i++ { 12 | AddStringWithOperator("时间复杂度和空间复杂度", "s") 13 | } 14 | } 15 | func BenchmarkAddStringWidthJoin(b *testing.B) { 16 | for i := 0; i < b.N; i++ { 17 | AddStringWidthJoin([]string{"时间复杂度和空间复杂度", "2"}) 18 | } 19 | } 20 | func BenchmarkAddStringWidthBuffer(b *testing.B) { 21 | for i := 0; i < b.N; i++ { 22 | AddStringWidthBuffer([]string{"时间复杂度和空间复杂度", "2"}) 23 | } 24 | } 25 | 26 | func TestReversString(t *testing.T) { 27 | t.Log(ReversString("spw")) 28 | } 29 | 30 | func TestFindMaxLenNoRepeatSubStr(t *testing.T) { 31 | t.Log(FindMaxLenNoRepeatSubStr("abcabcbb")) 32 | } 33 | func TestFindMaxLenNoRepeatSubStr2(t *testing.T) { 34 | t.Log(FindMaxLenNoRepeatSubStr2("abcabcbb")) 35 | } 36 | func TestFindMaxLenNoRepeatSubStr3(t *testing.T) { 37 | t.Log(FindMaxLenNoRepeatSubStr3("abcad")) 38 | } 39 | func TestFindMaxLenCommonSubStr(t *testing.T) { 40 | t.Log(FindMaxLenCommonSubStr("gfdef", "abcdef")) 41 | } 42 | func TestFindMaxLenCommonSubStr2(t *testing.T) { 43 | t.Log(FindMaxLenCommonSubStr2("abc", "abcd")) 44 | } 45 | 46 | func TestFindMaxLenCommonSubSeq(t *testing.T) { 47 | t.Log(FindMaxLenCommonSubSeq("abcd", "anbvcfgd")) 48 | } 49 | 50 | func TestFindAndReplacePattern(t *testing.T) { 51 | t.Log(FindAndReplacePattern([]string{"abb", "dee", "lkj"}, "abb")) 52 | } 53 | 54 | func TestRemoveRepeatStr(t *testing.T) { 55 | t.Log(RemoveRepeatStr("bbaacd")) 56 | } 57 | 58 | func TestRepeatedSubstringPattern(t *testing.T) { 59 | 60 | t.Log(RepeatedSubstringPattern("abab")) 61 | } 62 | func TestRepeatedSubstringPattern2(t *testing.T) { 63 | 64 | t.Log(RepeatedSubstringPattern2("ababa")) 65 | } 66 | 67 | func TestGetNext(t *testing.T) { 68 | t.Log(GetNext("ABCDABD")) 69 | } 70 | 71 | func TestStrMatch(t *testing.T) { 72 | t.Log(StrMatch("adabeabccbc", "ccbc")) 73 | } 74 | func TestIsValid(t *testing.T) { 75 | t.Log(IsValid("[]}")) 76 | } 77 | 78 | func TestLongestPalindrome(t *testing.T) { 79 | t.Log(LongestPalindrome("cbcdcbedcbc")) 80 | } 81 | 82 | func TestLengthOfLongestSubstring(t *testing.T) { 83 | t.Log(LengthOfLongestSubstring("accdan")) 84 | } 85 | 86 | func TestDeduplicate2(t *testing.T) { 87 | t.Log(Deduplicate2("aabcdeer")) 88 | } 89 | 90 | func TestLongestCommonPrefix(t *testing.T) { 91 | t.Log(LongestCommonPrefix([]string{"flower", "flow", "flight"})) 92 | } 93 | 94 | func TestRecursionPermutation(t *testing.T) { 95 | t.Log(RecursionPermutation("acety")) 96 | } 97 | 98 | func TestCheckInclusion(t *testing.T) { 99 | t.Log(CheckInclusion("ab", "mnab")) 100 | } 101 | 102 | func TestMultiply(t *testing.T) { 103 | fmt.Println("1584586728493525893642541066405904799198536104293994395887321573366110169031498781815747478010725266431858021835056717082517535189123595786349457873248" == "1584586728493525893642541066405904799198536104293994395887321573366110169031498781815747478010725266431858021835056717082517535189123595786349457873248") 104 | t.Log(Multiply("581852037460725882246068583352420736139988952640866685633288423526139", "2723349969536684936041476639043426870967112972397011150925040382981287990380531232")) 105 | } 106 | 107 | func Test_LetterCasePermutation(t *testing.T) { 108 | t.Log(LetterCasePermutation("a1b2")) 109 | } 110 | -------------------------------------------------------------------------------- /algorithm/arraystack.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "strconv" 5 | ) 6 | 7 | /** 8 | 数组实现栈 9 | */ 10 | 11 | type ArrayStack struct { 12 | Size int 13 | Data []interface{} 14 | } 15 | 16 | func Push(stack *ArrayStack, value interface{}) *ArrayStack { 17 | if stack == nil { 18 | stack = &ArrayStack{ 19 | Size: 0, 20 | Data: make([]interface{}, 10, 10), 21 | } 22 | stack.Data[stack.Size] = value 23 | } else { 24 | if stack.Size == len(stack.Data) { 25 | stack.Data = append(stack.Data, value) 26 | } else { 27 | stack.Data[stack.Size] = value 28 | } 29 | } 30 | stack.Size++ 31 | return stack 32 | } 33 | 34 | func Pop(stack *ArrayStack) interface{} { 35 | if stack == nil || stack.Size == 0 { 36 | return nil 37 | } 38 | value := stack.Data[stack.Size-1] 39 | stack.Data[stack.Size-1] = nil 40 | stack.Size-- 41 | return value 42 | } 43 | 44 | func Peek(stack *ArrayStack) interface{} { 45 | if stack == nil { 46 | return nil 47 | } 48 | value := stack.Data[stack.Size-1] 49 | return value 50 | } 51 | 52 | func IsEmpty(stack *ArrayStack) bool { 53 | if stack == nil || stack.Data == nil { 54 | return true 55 | } 56 | if stack.Size == 0 { 57 | return true 58 | } 59 | return false 60 | } 61 | 62 | /** 63 | 给定两个没有重复元素的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。找到 nums1 中每个元素在 nums2 中的下一个比其大的值。 64 | nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出-1。 65 | 示例 1: 66 | 输入: nums1 = [4,1,2], nums2 = [1,3,4,2]. 67 | 输出: [-1,3,-1] 68 | 解释: 69 | 对于num1中的数字4,你无法在第二个数组中找到下一个更大的数字,因此输出 -1。 70 | 对于num1中的数字1,第二个数组中数字1右边的下一个较大数字是 3。 71 | 对于num1中的数字2,第二个数组中没有下一个更大的数字,因此输出 -1。 72 | 73 | 示例 2: 74 | 输入: nums1 = [2,4], nums2 = [1,2,3,4]. 75 | 输出: [3,-1] 76 | 解释: 77 | 对于num1中的数字2,第二个数组中的下一个较大数字是3。 78 | 对于num1中的数字4,第二个数组中没有下一个更大的数字, 79 | 80 | */ 81 | func NextGreaterElement(findNums []int, nums []int) []int { 82 | var stack *ArrayStack 83 | m := make(map[int]int) 84 | for _, v := range nums { 85 | if !IsEmpty(stack) && Peek(stack).(int) < v { 86 | for !IsEmpty(stack) { 87 | flag := true 88 | if Peek(stack).(int) < v { 89 | m[Pop(stack).(int)] = v 90 | flag = false 91 | } 92 | if flag { 93 | break 94 | } 95 | } 96 | } 97 | stack = Push(stack, v) 98 | } 99 | for index, v := range findNums { 100 | if _, ok := m[v]; ok { 101 | findNums[index] = m[v] 102 | } else { 103 | findNums[index] = -1 104 | } 105 | } 106 | return findNums 107 | } 108 | 109 | func CalPoints(ops []string) int { 110 | if len(ops) == 0 { 111 | return 0 112 | } 113 | var stack *ArrayStack 114 | for _, v := range ops { 115 | i := 0 116 | if v == "+" { 117 | if stack == nil || stack.Size == 0 { 118 | i = 0 119 | } else if stack.Size == 1 { 120 | i = Peek(stack).(int) 121 | } else { 122 | m := Pop(stack).(int) 123 | n := Peek(stack).(int) 124 | i = m + n 125 | stack = Push(stack, m) 126 | } 127 | } else if v == "D" { 128 | if stack == nil || stack.Size == 0 { 129 | i = 0 130 | } else { 131 | m := Peek(stack).(int) 132 | i = m * 2 133 | } 134 | } else if v == "C" { 135 | Pop(stack) 136 | } else { 137 | i, _ = strconv.Atoi(v) 138 | } 139 | if i != 0 { 140 | stack = Push(stack, i) 141 | } 142 | } 143 | sum := 0 144 | for !IsEmpty(stack) { 145 | m := Pop(stack).(int) 146 | sum += m 147 | } 148 | return sum 149 | } 150 | -------------------------------------------------------------------------------- /algorithm/树笔记: -------------------------------------------------------------------------------- 1 | ## 树 2 | 树的基本概念 3 | 树: 4 | 树(Tree)是n(n>=0)个结点的有限集 5 | 树有且仅有一个根结点 6 | 树的结点包含一个数据元素一级若干指向子树的分支 7 | 8 | 度: 9 | 结点拥有的子树的个数被称为结点的度(比如,二叉树每个结点的度最大为2,最小为0(叶子结点)) 10 | 度为0的结点称为叶子结点(Leaf) 或终端结点 11 | 树的度是树内各结点的度的最大值(就是那个结点的度最大,那么这个结点的度就是这棵树的度) 12 | 13 | 结点: 14 | 结点的子树的根称为该节点的孩子,相应的,该结点称为孩子的双亲 15 | 同一个双亲的孩子叫做兄弟 16 | 其双亲在同一层的叫做堂兄弟 17 | 节点的祖先是从根结点到该结点所经分支上的所有结点 18 | 19 | 层次: 20 | 结点的层次,从根开始定义起,根称为第一层,根的孩子为第二层 21 | 树中结点的最大层次为树的深度或者高度 22 | 23 | 深度高度: 24 | 结点的深度是从根节点往下一直到该结点 25 | 结点的高度从最底的叶子节点一直到该结点 26 | 相同深度的节点,高度不一定相同 27 | 高度取决于该结点到终端节点的距离 28 | 深度取决于该结点到根节点距离 29 | 30 | ###二叉树 31 | 每个结点最多有两棵子树,二叉树中不存在度大于2的结点 32 | 左子树和右子树是有顺序的,不能颠倒 33 | 即使树中的某结点只有一棵子树,也要区分是左子树还是右子树 34 | 二叉树有五种形态,空树,只有根结点,根节点只有左子树,根节点只有右子树,根节点左右子树都有 35 | 36 | ###满二叉树 37 | 所有的分支结点都存在左右子树,所有的叶子结点都在同一层,则这个二叉树是满二叉树 38 | 叶子结点只能出现在最底层 39 | 非叶子结点的度一定为2 40 | 在同样深度的二叉树中,满二叉树的结点个数最多,叶子结点最多 41 | 42 | ###完全二叉树 43 | 如果编号为I的结点与同样高度的满二叉树中编号为I的结点在二叉树中位置完全相同,则这个二叉树称为完全二叉树(也就是叶子结点层差为1) 44 | 完全二叉树的叶子结点只能出现在最下两层 45 | 最底层的叶子结点一定集中在左边连续位置 46 | 如果结点度为1,则结点只有左孩子,没有右孩子 47 | 同样结点的二叉树,完全二叉树深度最小 48 | ###二叉树的性质 49 | 在二叉树上第I层上至多有2(i-1)次方个结点 50 | 深度为K的二叉树至多有2的k次方减1个结点 51 | 在二叉树T中,如果叶子结点的个数为n,度为2的结点的个数为m,则n = m+1 52 | 具有n个结点的完全二叉树的深度为log2n + 1 53 | 如果对一棵有n个结点的完全二叉树,结点编号从1到n(每层从左到右)对于任意一结点 1<= i <= n,则有 54 | 1、如果i等于1,则i为根结点,无双亲,如果i>1,则双亲结点为i/2 55 | 2、如果2*i大于n,则结点i无左孩子(结点i为叶子结点),否则,左孩子是结点2*i 56 | 3、如果2*i大于n+1,则结点i无右孩子,否则右孩子结点是2*i+1 57 | 58 | ###二叉查找树 59 | 称为二叉排序树,或二叉搜索树, 60 | 若左子树不为空,则左子树所有结点的值小于根结点的值 61 | 若右子树不为空,则右子树所有结点的值大于根结点的值 62 | 左右子树也分别为二叉排序树 63 | 没有键值相等的结点 64 | 对二叉排序树进行中序遍历,可得到有序的序列 65 | 二叉排序树的插入和查找时间复杂度均为O(logn),最坏情况下可能为O(n),因为极端情况下,二叉查找树会退化成链 66 | 二叉查找树的高度决定了二叉查找树的效率,高度越高,效率越低。 67 | 二叉查找树的插入过程如下: 68 | 若当前二叉查找树为空,则插入的元素为根结点 69 | 若插入的元素值小于根结点值,则将元素插入到左子树 70 | 若插入的元素的值大于根结点,则将元素插入到右子树 71 | 二叉查找树的删除(https://blog.csdn.net/zxnsirius/article/details/52131433) 72 | 若删除的结点p是叶子结点,则,直接删除,并修改父结点的指针(区分根结点和非根结点) 73 | 若删除的结点p是单支结点,则让p的子树和p的父结点相连 74 | 若删除的结点p 左子树和右子树均不为空,则需要找到一个结点的值在左右子树的中间 75 | 76 | ###AVL树(自平衡而查找树) 77 | AVL树是最先发明的自平衡二叉查找树,在AVL中任何节点的两个儿子子树的高度最大差别为1,所以它也被称为高度平衡树 78 | http://lib.csdn.net/article/datastructure/10654 (主要理解旋转) 79 | 80 | 81 | ###字典树(Tire) 82 | Tire树被称为字典树,又称单词查找树,Tire树,是一种树形结构,是一种哈希树的变种。 83 | 典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。 84 | 它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高 85 | Tire树的三个基本性质: 86 |   1) 根节点不包含字符,除根节点外每一个节点都只包含一个字符; 87 |   2) 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串; 88 |   3) 每个节点的所有子节点包含的字符都不相同。 89 | Tire树的应用: 90 |   1) 串的快速检索 91 |    给出N个单词组成的熟词表,以及一篇全用小写英文书写的文章,请你按最早出现的顺序写出所有不在熟词表中的生词。 92 | 在这道题中,我们可以用数组枚举,用哈希,用字典树,先把熟词建一棵树,然后读入文章进行比较,这种方法效率是比较高的。 93 |   2) “串”排序 94 |    给定N个互不相同的仅由一个单词构成的英文名,让你将他们按字典序从小到大输出。用字典树进行排序,采用数组的方式创建字典树,这棵树的每个结点的所有儿子很显然地按照其字母大小排序。对这棵树进行先序遍历即可。 95 |   3) 最长公共前缀 96 |    对所有串建立字典树,对于两个串的最长公共前缀的长度即他们所在的结点的公共祖先个数,于是,问题就转化为求公共祖先的问题。 97 | -------------------------------------------------------------------------------- /algorithm/ahocorasick.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | // ac自动机 4 | import ( 5 | "container/list" 6 | ) 7 | 8 | type trieNode struct { 9 | count int //当前模式串单词的数量 10 | fail *trieNode //失败指针 11 | child map[rune]*trieNode //字典树的孩子节点 12 | index int //模式串的下标 13 | } 14 | 15 | func newTrieNode() *trieNode { 16 | return &trieNode{ 17 | count: 0, 18 | fail: nil, 19 | child: make(map[rune]*trieNode), 20 | index: -1, 21 | } 22 | } 23 | 24 | type Matcher struct { 25 | root *trieNode 26 | size int // 模式串大小 27 | mark []bool 28 | } 29 | 30 | func NewMatcher() *Matcher { 31 | return &Matcher{ 32 | root: newTrieNode(), 33 | size: 0, 34 | mark: make([]bool, 0), 35 | } 36 | } 37 | 38 | // initialize the ahocorasick 39 | func (this *Matcher) Build(dictionary []string) { 40 | for i, _ := range dictionary { 41 | this.insert(dictionary[i]) 42 | } 43 | this.build() 44 | this.mark = make([]bool, this.size) 45 | } 46 | 47 | // string match search 48 | // return all strings matched as indexes into the original dictionary 49 | func (this *Matcher) Match(s string) []int { 50 | curNode := this.root 51 | this.resetMark() 52 | var p *trieNode = nil 53 | 54 | ret := make([]int, 0) 55 | 56 | for _, v := range s { 57 | for curNode.child[v] == nil && curNode != this.root { 58 | curNode = curNode.fail 59 | } 60 | curNode = curNode.child[v] 61 | if curNode == nil { 62 | curNode = this.root 63 | } 64 | 65 | p = curNode 66 | for p != this.root && p.count > 0 && !this.mark[p.index] { 67 | this.mark[p.index] = true 68 | for i := 0; i < p.count; i++ { 69 | ret = append(ret, p.index) 70 | } 71 | p = p.fail 72 | } 73 | } 74 | 75 | return ret 76 | } 77 | 78 | // just return the number of len(Match(s)) 79 | func (this *Matcher) GetMatchResultSize(s string) int { 80 | curNode := this.root 81 | this.resetMark() 82 | var p *trieNode = nil 83 | 84 | num := 0 85 | 86 | for _, v := range s { 87 | for curNode.child[v] == nil && curNode != this.root { 88 | curNode = curNode.fail 89 | } 90 | curNode = curNode.child[v] 91 | if curNode == nil { 92 | curNode = this.root 93 | } 94 | 95 | p = curNode 96 | for p != this.root && p.count > 0 && !this.mark[p.index] { 97 | this.mark[p.index] = true 98 | num += p.count 99 | p = p.fail 100 | } 101 | } 102 | 103 | return num 104 | } 105 | 106 | func (this *Matcher) build() { 107 | ll := list.New() 108 | ll.PushBack(this.root) 109 | for ll.Len() > 0 { 110 | temp := ll.Remove(ll.Front()).(*trieNode) 111 | var p *trieNode = nil 112 | 113 | for i, v := range temp.child { 114 | if temp == this.root { 115 | v.fail = this.root 116 | } else { 117 | p = temp.fail 118 | for p != nil { 119 | if p.child[i] != nil { 120 | v.fail = p.child[i] 121 | break 122 | } 123 | p = p.fail 124 | } 125 | if p == nil { 126 | v.fail = this.root 127 | } 128 | } 129 | ll.PushBack(v) 130 | } 131 | } 132 | } 133 | 134 | func (this *Matcher) insert(s string) { 135 | curNode := this.root 136 | for _, v := range s { 137 | if curNode.child[v] == nil { 138 | curNode.child[v] = newTrieNode() 139 | } 140 | curNode = curNode.child[v] 141 | } 142 | curNode.count++ 143 | curNode.index = this.size 144 | this.size++ 145 | } 146 | 147 | func (this *Matcher) resetMark() { 148 | for i := 0; i < this.size; i++ { 149 | this.mark[i] = false 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /algorithm/bfs.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "container/list" 5 | ) 6 | 7 | type TreeNodeBfs struct { 8 | Val int 9 | Left *TreeNode 10 | Right *TreeNode 11 | } 12 | 13 | func isCousins(root *TreeNodeBfs, x int, y int) bool { 14 | 15 | queue := list.New() 16 | queue.PushFront(root) 17 | 18 | for queue.Len() > 0 { 19 | tempQueue := list.New() 20 | f1, f2 := false, false 21 | var p1, p2 *TreeNodeBfs 22 | for queue.Len() > 0 { 23 | element := queue.Front() 24 | e := element.Value.(*TreeNodeBfs) 25 | if e.Left != nil { 26 | if e.Left.Val == x { 27 | f1 = true 28 | p1 = e 29 | } 30 | if e.Left.Val == y { 31 | f2 = true 32 | p2 = e 33 | } 34 | tempQueue.PushFront(e.Left) 35 | } 36 | if e.Right != nil { 37 | if e.Left.Val == x { 38 | f1 = true 39 | p1 = e 40 | } 41 | if e.Right.Val == y { 42 | f2 = true 43 | p2 = e 44 | } 45 | tempQueue.PushFront(e.Right) 46 | } 47 | if f1 && f2 && p1 != p2 { 48 | return true 49 | } 50 | queue.Remove(element) 51 | } 52 | queue.PushFrontList(tempQueue) 53 | } 54 | return false 55 | } 56 | 57 | func orangesRotting(grid [][]int) int { 58 | 59 | result := 0 60 | falg := make([][]bool, len(grid)) 61 | for i := 0; i < len(grid); i++ { 62 | temp := make([]bool, len(grid[i])) 63 | falg[i] = temp 64 | } 65 | queue := list.New() 66 | queue.PushFront(&RowCol{0, 0}) 67 | 68 | for queue.Len() > 0 { 69 | tempQueue := list.New() 70 | for queue.Len() > 0 { 71 | ele := queue.Front() 72 | v := ele.Value.(RowCol) 73 | if v.Row < len(grid)-1 && grid[v.Row+1][v.Col] != 0 { 74 | tempQueue.PushFront(&RowCol{v.Row + 1, v.Col}) 75 | result++ 76 | } 77 | 78 | if v.Col < len(grid[v.Row])-1 && grid[v.Row][v.Col+1] != 0 { 79 | tempQueue.PushFront(&RowCol{v.Row, v.Col + 1}) 80 | result++ 81 | } 82 | queue.Remove(ele) 83 | } 84 | 85 | queue.PushFrontList(tempQueue) 86 | } 87 | return result / 2 88 | } 89 | 90 | type RowCol struct { 91 | Row int 92 | Col int 93 | } 94 | 95 | func zigzagLevelOrder(root *TreeNode) [][]int { 96 | if root == nil { 97 | return nil 98 | } 99 | result := make([][]int, 0) 100 | DFS(root, &result, 0) 101 | return result 102 | } 103 | 104 | func DFS(root *TreeNode, result *[][]int, deep int) { 105 | if root == nil { 106 | return 107 | } 108 | if len(*result) <= deep { 109 | *result = append(*result, make([]int, 0)) 110 | } 111 | if deep%2 == 0 { 112 | t := (*result)[deep] 113 | t = append(t, root.Val) 114 | (*result)[deep] = t 115 | } else { 116 | t := (*result)[deep] 117 | temp := make([]int, 0) 118 | temp = append(temp, root.Val) 119 | temp = append(temp, t[:]...) 120 | (*result)[deep] = temp 121 | } 122 | DFS(root.Left, result, deep+1) 123 | DFS(root.Right, result, deep+1) 124 | 125 | } 126 | 127 | func findMinHeightTrees(n int, edges [][]int) []int { 128 | 129 | count := make([]int, n) 130 | 131 | m := make(map[int]*[]int, 0) 132 | for i := 0; i < n; i++ { 133 | temp := make([]int, 0) 134 | m[i] = &temp 135 | } 136 | for i := 0; i < len(edges); i++ { 137 | count[edges[i][0]]++ 138 | count[edges[i][1]]++ 139 | if _, ok := m[edges[i][0]]; ok { 140 | t := m[edges[i][0]] 141 | *t = append(*t, edges[i][1]) 142 | } else { 143 | t := make([]int, 0) 144 | t = append(t, edges[i][1]) 145 | m[edges[i][0]] = &t 146 | } 147 | 148 | } 149 | 150 | return nil 151 | } 152 | -------------------------------------------------------------------------------- /algorithm/avltree1.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import "fmt" 4 | 5 | // avl树 自平衡的二叉查找树 6 | 7 | type AVLTree *AVLTreeNode 8 | 9 | type AVLTreeNode struct { 10 | key int 11 | high int 12 | left *AVLTreeNode 13 | right *AVLTreeNode 14 | } 15 | 16 | func AvlInsert(avl AVLTree, key int) AVLTree { 17 | if avl == nil { 18 | avl = new(AVLTreeNode) 19 | if avl == nil { 20 | fmt.Println("avl tree create error!") 21 | return nil 22 | } else { 23 | avl.key = key 24 | avl.high = 0 25 | avl.left = nil 26 | avl.right = nil 27 | } 28 | } else if key < avl.key { 29 | avl.left = AvlInsert(avl.left, key) 30 | if highTree(avl.left)-highTree(avl.right) == 2 { 31 | if key < avl.left.key { //LL 32 | avl = leftLeftRotation(avl) 33 | } else { // LR 34 | avl = leftRighRotation(avl) 35 | } 36 | } 37 | } else if key > avl.key { 38 | avl.right = AvlInsert(avl.right, key) 39 | if (highTree(avl.right) - highTree(avl.left)) == 2 { 40 | if key < avl.right.key { // RL 41 | avl = rightRightRotation(avl) 42 | } else { 43 | fmt.Println("right right", key) 44 | avl = rightLeftRotation(avl) 45 | } 46 | } 47 | } else if key == avl.key { 48 | fmt.Println("the key", key, "has existed!") 49 | } 50 | avl.high = max(highTree(avl.left), highTree(avl.right)) + 1 51 | return avl 52 | } 53 | func highTree(p AVLTree) int { 54 | if p == nil { 55 | return -1 56 | } else { 57 | return p.high 58 | } 59 | } 60 | 61 | func max(a, b int) int { 62 | if a > b { 63 | return a 64 | } else { 65 | return b 66 | } 67 | } 68 | 69 | func leftLeftRotation(k AVLTree) AVLTree { 70 | var kl AVLTree 71 | kl = k.left 72 | k.left = kl.right 73 | kl.right = k 74 | k.high = max(highTree(k.left), highTree(k.right)) + 1 75 | kl.high = max(highTree(kl.left), k.high) + 1 76 | return kl 77 | } 78 | 79 | func rightRightRotation(k AVLTree) AVLTree { 80 | var kr AVLTree 81 | kr = k.right 82 | k.right = kr.left 83 | kr.left = k 84 | k.high = max(highTree(k.left), highTree(k.right)) + 1 85 | kr.high = max(k.high, highTree(kr.right)) + 1 86 | return kr 87 | } 88 | 89 | func leftRighRotation(k AVLTree) AVLTree { 90 | k.left = rightRightRotation(k.left) 91 | return leftLeftRotation(k) 92 | } 93 | 94 | func rightLeftRotation(k AVLTree) AVLTree { 95 | k.right = leftLeftRotation(k.right) 96 | return rightRightRotation(k) 97 | } 98 | 99 | func PreOrder(avl AVLTree) { 100 | if avl != nil { 101 | fmt.Print(avl.key, "\t") 102 | PreOrder(avl.left) 103 | PreOrder(avl.right) 104 | } 105 | 106 | } 107 | 108 | /** 109 | 前序非递归遍历 110 | */ 111 | func PreNotRecursionOrder(root AVLTree) []int { 112 | if root == nil { 113 | return nil 114 | } 115 | var stack *ArrayStack 116 | array := make([]int, 0, 0) 117 | for root != nil || !IsEmpty(stack) { 118 | if root != nil { 119 | array = append(array, root.key) 120 | stack = Push(stack, root) 121 | root = root.left 122 | } else { 123 | root = Pop(stack).(*AVLTreeNode) 124 | root = root.right 125 | } 126 | } 127 | return array 128 | } 129 | 130 | /** 131 | 中序遍历递归 132 | */ 133 | func MidOrder(avl AVLTree) { 134 | if avl != nil { 135 | MidOrder(avl.left) 136 | fmt.Print(avl.key, "\t") 137 | MidOrder(avl.right) 138 | } 139 | } 140 | 141 | /** 142 | 后续遍历递归 143 | */ 144 | func PoOrder(avl AVLTree) { 145 | if avl == nil { 146 | return 147 | } 148 | PoOrder(avl.left) 149 | PoOrder(avl.right) 150 | fmt.Println(avl.key) 151 | } 152 | 153 | func getAvlHeight(avl AVLTree) int { 154 | if avl == nil { 155 | return 0 156 | } 157 | l := getAvlHeight(avl.left) + 1 158 | r := getAvlHeight(avl.right) + 1 159 | if l > r { 160 | return l 161 | } 162 | return r 163 | } 164 | -------------------------------------------------------------------------------- /event_bus/network_event_bus/client.go: -------------------------------------------------------------------------------- 1 | package EventBus 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "go_common/event_bus" 7 | "net" 8 | "net/http" 9 | "net/rpc" 10 | "sync" 11 | ) 12 | 13 | const ( 14 | // PublishService - Client service method 15 | PublishService = "ClientService.PushEvent" 16 | ) 17 | 18 | // ClientArg - object containing event for client to publish locally 19 | type ClientArg struct { 20 | Args []interface{} 21 | Topic string 22 | } 23 | 24 | // Client - object capable of subscribing to a remote event bus 25 | type Client struct { 26 | eventBus EventBus.Bus 27 | address string 28 | path string 29 | service *ClientService 30 | } 31 | 32 | // NewClient - create a client object with the address and server path 33 | func NewClient(address, path string, eventBus EventBus.Bus) *Client { 34 | client := new(Client) 35 | client.eventBus = eventBus 36 | client.address = address 37 | client.path = path 38 | client.service = &ClientService{client, &sync.WaitGroup{}, false} 39 | return client 40 | } 41 | 42 | // EventBus - returns the underlying event bus 43 | func (client *Client) EventBus() EventBus.Bus { 44 | return client.eventBus 45 | } 46 | 47 | func (client *Client) doSubscribe(topic string, fn interface{}, serverAddr, serverPath string, subscribeType SubscribeType) { 48 | defer func() { 49 | if r := recover(); r != nil { 50 | fmt.Println("Server not found -", r) 51 | } 52 | }() 53 | 54 | rpcClient, err := rpc.DialHTTPPath("tcp", serverAddr, serverPath) 55 | defer rpcClient.Close() 56 | if err != nil { 57 | fmt.Errorf("dialing: %v", err) 58 | } 59 | args := &SubscribeArg{client.address, client.path, PublishService, subscribeType, topic} 60 | reply := new(bool) 61 | err = rpcClient.Call(RegisterService, args, reply) 62 | if err != nil { 63 | fmt.Errorf("Register error: %v", err) 64 | } 65 | if *reply { 66 | client.eventBus.Subscribe(topic, fn) 67 | } 68 | } 69 | 70 | //Subscribe subscribes to a topic in a remote event bus 71 | func (client *Client) Subscribe(topic string, fn interface{}, serverAddr, serverPath string) { 72 | client.doSubscribe(topic, fn, serverAddr, serverPath, Subscribe) 73 | } 74 | 75 | //SubscribeOnce subscribes once to a topic in a remote event bus 76 | func (client *Client) SubscribeOnce(topic string, fn interface{}, serverAddr, serverPath string) { 77 | client.doSubscribe(topic, fn, serverAddr, serverPath, SubscribeOnce) 78 | } 79 | 80 | // Start - starts the client service to listen to remote events 81 | func (client *Client) Start() error { 82 | var err error 83 | service := client.service 84 | if !service.started { 85 | server := rpc.NewServer() 86 | server.Register(service) 87 | server.HandleHTTP(client.path, "/debug"+client.path) 88 | l, err := net.Listen("tcp", client.address) 89 | if err == nil { 90 | service.wg.Add(1) 91 | service.started = true 92 | go http.Serve(l, nil) 93 | } 94 | } else { 95 | err = errors.New("Client service already started") 96 | } 97 | return err 98 | } 99 | 100 | // Stop - signal for the service to stop serving 101 | func (client *Client) Stop() { 102 | service := client.service 103 | if service.started { 104 | service.wg.Done() 105 | service.started = false 106 | } 107 | } 108 | 109 | // ClientService - service object listening to events published in a remote event bus 110 | type ClientService struct { 111 | client *Client 112 | wg *sync.WaitGroup 113 | started bool 114 | } 115 | 116 | // PushEvent - exported service to listening to remote events 117 | func (service *ClientService) PushEvent(arg *ClientArg, reply *bool) error { 118 | service.client.eventBus.Publish(arg.Topic, arg.Args...) 119 | *reply = true 120 | return nil 121 | } 122 | --------------------------------------------------------------------------------