├── .DS_Store ├── .gitignore ├── LICENSE ├── README.md ├── algorithm ├── bst │ ├── bst.go │ ├── bst_test.go │ ├── go.mod │ └── go.sum ├── quicksort │ └── quicksort.go └── search │ ├── go.mod │ ├── go.sum │ ├── tree.go │ └── tree_test.go ├── basic-example ├── .DS_Store ├── 01-hello_world │ └── hello_world.go ├── 02-values │ └── values.go ├── 03-variables │ └── variables.go ├── 04-constants │ └── constants.go ├── 05-for │ └── for.go ├── 06-if_else │ └── if_else.go ├── 07-switch │ └── switch.go ├── 08-array │ └── array.go ├── 09-slice │ ├── slice-layout.go │ └── slice.go ├── 10-map │ ├── map.go │ ├── rwlockmap.go │ ├── shardmap.go │ ├── sortedmap.go │ ├── syncmap.go │ └── unsafemap.go ├── 11-range │ └── range.go ├── 12-function │ └── function.go ├── 13-muti_return_values │ └── multi_return_values.go ├── 14-variadic_functions │ └── variadic_functions.go ├── 15-closures.go │ └── closures.go ├── 16-recursion │ └── recursion.go ├── 17-pointers │ └── pointers.go ├── 18-struct │ └── struct.go ├── 19-methods │ └── methods.go ├── 20-interfaces │ └── interfaces.go ├── 21-errors │ └── errors.go ├── 22-goroutines │ └── goroutines.go ├── 23-channels │ └── channels.go ├── 24-channel_buffering │ └── channel_buffering.go ├── 25-channel_sync │ └── channel_sync.go ├── 26-channel_directions │ └── channel_directions.go ├── 27-select │ └── select.go ├── 28-timeouts │ └── timeouts.go ├── 29-non_block_channel │ └── non_block_channel.go ├── 30-close_channels │ └── close_channels.go ├── 31-range_over_channels │ └── range_over_channels.go ├── 32-timers │ └── timers.go ├── 33-tickers │ └── tickers.go ├── 34-worker_pool │ └── worker_pool.go ├── 35-wait_groups │ └── wait_groups.go ├── 36-rate_limiting │ └── rate_limiting.go ├── 37-atomic_counters │ └── atomic_counters.go ├── 38-mutexes │ └── mutexes.go ├── 39-stateful_goroutines │ └── stateful_goroutines.go ├── 40-sorting │ └── sorting.go ├── 41-sorting_by_func │ └── sorting_by_func.go ├── 42-panic │ └── panic.go ├── 43-defer │ └── defer.go ├── 44-collections_funcs │ └── collections_funcs.go ├── 45-string_funcs │ └── string_funcs.go ├── 46-string_format │ └── 46_string_format.go ├── 47-regular │ └── regular.go ├── 48-type_assertion │ └── type_assertion.go ├── 49-hmac │ └── hmac.go └── 50-context │ ├── withcancel.go │ ├── withdeadline.go │ ├── withtimeout.go │ └── withvalue.go ├── engine └── main.go ├── gin-example ├── go.mod ├── go.sum └── main.go ├── grpc-example ├── deadline │ ├── client │ │ ├── go.mod │ │ ├── go.sum │ │ ├── main.go │ │ └── proto │ │ │ └── helloworld.pb.go │ └── server │ │ ├── go.mod │ │ ├── go.sum │ │ ├── main.go │ │ └── proto │ │ ├── gen_proto.sh │ │ ├── helloworld.pb.go │ │ └── helloworld.proto ├── grpc-client │ ├── cert │ │ ├── ca.key │ │ ├── ca.pem │ │ ├── ca.srl │ │ ├── client.csr │ │ ├── client.key │ │ └── client.pem │ ├── go.mod │ ├── go.sum │ ├── keys │ │ └── server.crt │ ├── main.go │ └── proto │ │ └── helloworld.pb.go ├── grpc-server │ ├── cert │ │ ├── ca.key │ │ ├── ca.pem │ │ ├── ca.srl │ │ ├── server.csr │ │ ├── server.key │ │ └── server.pem │ ├── go.mod │ ├── go.sum │ ├── keys │ │ ├── server.crt │ │ ├── server.csr │ │ ├── server.key │ │ └── server.pass.key │ ├── main.go │ └── proto │ │ ├── gen_proto.sh │ │ ├── helloworld.pb.go │ │ ├── helloworld.proto │ │ └── helloworld.validator.pb.go ├── pubsub │ ├── client │ │ ├── go.mod │ │ ├── go.sum │ │ ├── proto │ │ │ └── helloworld.pb.go │ │ ├── pub_client.go │ │ └── sub_client.go │ └── server │ │ ├── go.mod │ │ ├── go.sum │ │ ├── main.go │ │ ├── proto │ │ ├── gen_proto.sh │ │ ├── helloworld.pb.go │ │ └── helloworld.proto │ │ └── pubsub.go ├── py-client │ ├── helloworld.proto │ ├── helloworld_pb2.py │ ├── helloworld_pb2_grpc.py │ └── main.py ├── rest │ ├── go.mod │ ├── go.sum │ ├── grpc_service.go │ ├── proto │ │ ├── gen_proto.sh │ │ ├── helloworld.pb.go │ │ ├── helloworld.pb.gw.go │ │ ├── helloworld.proto │ │ └── helloworld.swagger.json │ └── rest_service.go └── simple │ ├── client │ ├── go.mod │ ├── go.sum │ ├── main.go │ └── proto │ │ └── helloworld.pb.go │ └── server │ ├── go.mod │ ├── go.sum │ ├── main.go │ └── proto │ ├── gen_proto.sh │ ├── helloworld.pb.go │ └── helloworld.proto ├── leetcode └── 206-reverse-linked-list.go └── openai-example ├── go.mod ├── go.sum └── main.go /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yongxinz/go-example/1f1a2374b166d05374a17982bab238eb04ba4476/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ 16 | 17 | __pycache__ 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 yongxinz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # go-example 2 | 3 | Go 语言编程的一些代码示例,开箱即用。 4 | 5 | ## 基础学习 6 | 7 | - [代码示例](basic-example/) 8 | 9 | ## 算法与数据结构 10 | 11 | - [代码示例](algorithm/) 12 | - [Go 语言实现快速排序算法](https://mp.weixin.qq.com/s/OaHrvRGyVEWEC4gyONan1Q) 13 | - [使用 Go 语言实现二叉搜索树](https://mp.weixin.qq.com/s/2wYRmG_AiiHYjLDEXg94Ag) 14 | 15 | ## gRPC 16 | 17 | 增加 gRPC 相关代码,内容包括简单的 gRPC 服务,流处理模式,验证器,Token 认证和证书认证。 18 | 19 | - [代码示例](grpc-example/) 20 | - [使用 grpcurl 通过命令行访问 gRPC 服务](https://mp.weixin.qq.com/s/GShwcGCopXVmxCKnYf5FhA) 21 | - [测试小姐姐问我 gRPC 怎么用,我直接把这篇文章甩给了她](https://mp.weixin.qq.com/s/qdI2JqpMq6t2KN1byHaNCQ) 22 | - [gRPC,爆赞](https://mp.weixin.qq.com/s/1Xbca4Dv0akonAZerrChgA) 23 | -------------------------------------------------------------------------------- /algorithm/bst/bst.go: -------------------------------------------------------------------------------- 1 | // Package binarysearchtree creates a ItemBinarySearchTree data structure for the Item type 2 | package binarysearchtree 3 | 4 | import ( 5 | "fmt" 6 | "sync" 7 | 8 | "github.com/cheekybits/genny/generic" 9 | ) 10 | 11 | // Item the type of the binary search tree 12 | type Item generic.Type 13 | 14 | // Node a single node that composes the tree 15 | type Node struct { 16 | key int 17 | value Item 18 | left *Node //left 19 | right *Node //right 20 | } 21 | 22 | // ItemBinarySearchTree the binary search tree of Items 23 | type ItemBinarySearchTree struct { 24 | root *Node 25 | lock sync.RWMutex 26 | } 27 | 28 | // Insert inserts the Item t in the tree 29 | func (bst *ItemBinarySearchTree) Insert(key int, value Item) { 30 | bst.lock.Lock() 31 | defer bst.lock.Unlock() 32 | n := &Node{key, value, nil, nil} 33 | if bst.root == nil { 34 | bst.root = n 35 | } else { 36 | insertNode(bst.root, n) 37 | } 38 | } 39 | 40 | // internal function to find the correct place for a node in a tree 41 | func insertNode(node, newNode *Node) { 42 | if newNode.key < node.key { 43 | if node.left == nil { 44 | node.left = newNode 45 | } else { 46 | insertNode(node.left, newNode) 47 | } 48 | } else { 49 | if node.right == nil { 50 | node.right = newNode 51 | } else { 52 | insertNode(node.right, newNode) 53 | } 54 | } 55 | } 56 | 57 | // InOrderTraverse visits all nodes with in-order traversing 58 | func (bst *ItemBinarySearchTree) InOrderTraverse(f func(Item)) { 59 | bst.lock.RLock() 60 | defer bst.lock.RUnlock() 61 | inOrderTraverse(bst.root, f) 62 | } 63 | 64 | // internal recursive function to traverse in order 65 | func inOrderTraverse(n *Node, f func(Item)) { 66 | if n != nil { 67 | inOrderTraverse(n.left, f) 68 | f(n.value) 69 | inOrderTraverse(n.right, f) 70 | } 71 | } 72 | 73 | // PreOrderTraverse visits all nodes with pre-order traversing 74 | func (bst *ItemBinarySearchTree) PreOrderTraverse(f func(Item)) { 75 | bst.lock.Lock() 76 | defer bst.lock.Unlock() 77 | preOrderTraverse(bst.root, f) 78 | } 79 | 80 | // internal recursive function to traverse pre order 81 | func preOrderTraverse(n *Node, f func(Item)) { 82 | if n != nil { 83 | f(n.value) 84 | preOrderTraverse(n.left, f) 85 | preOrderTraverse(n.right, f) 86 | } 87 | } 88 | 89 | // PostOrderTraverse visits all nodes with post-order traversing 90 | func (bst *ItemBinarySearchTree) PostOrderTraverse(f func(Item)) { 91 | bst.lock.Lock() 92 | defer bst.lock.Unlock() 93 | postOrderTraverse(bst.root, f) 94 | } 95 | 96 | // internal recursive function to traverse post order 97 | func postOrderTraverse(n *Node, f func(Item)) { 98 | if n != nil { 99 | postOrderTraverse(n.left, f) 100 | postOrderTraverse(n.right, f) 101 | f(n.value) 102 | } 103 | } 104 | 105 | // Min returns the Item with min value stored in the tree 106 | func (bst *ItemBinarySearchTree) Min() *Item { 107 | bst.lock.RLock() 108 | defer bst.lock.RUnlock() 109 | n := bst.root 110 | if n == nil { 111 | return nil 112 | } 113 | for { 114 | if n.left == nil { 115 | return &n.value 116 | } 117 | n = n.left 118 | } 119 | } 120 | 121 | // Max returns the Item with max value stored in the tree 122 | func (bst *ItemBinarySearchTree) Max() *Item { 123 | bst.lock.RLock() 124 | defer bst.lock.RUnlock() 125 | n := bst.root 126 | if n == nil { 127 | return nil 128 | } 129 | for { 130 | if n.right == nil { 131 | return &n.value 132 | } 133 | n = n.right 134 | } 135 | } 136 | 137 | // Search returns true if the Item t exists in the tree 138 | func (bst *ItemBinarySearchTree) Search(key int) bool { 139 | bst.lock.RLock() 140 | defer bst.lock.RUnlock() 141 | return search(bst.root, key) 142 | } 143 | 144 | // internal recursive function to search an item in the tree 145 | func search(n *Node, key int) bool { 146 | if n == nil { 147 | return false 148 | } 149 | if key < n.key { 150 | return search(n.left, key) 151 | } 152 | if key > n.key { 153 | return search(n.right, key) 154 | } 155 | return true 156 | } 157 | 158 | // Remove removes the Item with key `key` from the tree 159 | func (bst *ItemBinarySearchTree) Remove(key int) { 160 | bst.lock.Lock() 161 | defer bst.lock.Unlock() 162 | remove(bst.root, key) 163 | } 164 | 165 | // internal recursive function to remove an item 166 | func remove(node *Node, key int) *Node { 167 | if node == nil { 168 | return nil 169 | } 170 | if key < node.key { 171 | node.left = remove(node.left, key) 172 | return node 173 | } 174 | if key > node.key { 175 | node.right = remove(node.right, key) 176 | return node 177 | } 178 | // key == node.key 179 | if node.left == nil && node.right == nil { 180 | node = nil 181 | return nil 182 | } 183 | if node.left == nil { 184 | node = node.right 185 | return node 186 | } 187 | if node.right == nil { 188 | node = node.left 189 | return node 190 | } 191 | leftmostrightside := node.right 192 | for { 193 | //find smallest value on the right side 194 | if leftmostrightside != nil && leftmostrightside.left != nil { 195 | leftmostrightside = leftmostrightside.left 196 | } else { 197 | break 198 | } 199 | } 200 | node.key, node.value = leftmostrightside.key, leftmostrightside.value 201 | node.right = remove(node.right, node.key) 202 | return node 203 | } 204 | 205 | // String prints a visual representation of the tree 206 | func (bst *ItemBinarySearchTree) String() { 207 | bst.lock.Lock() 208 | defer bst.lock.Unlock() 209 | fmt.Println("------------------------------------------------") 210 | stringify(bst.root, 0) 211 | fmt.Println("------------------------------------------------") 212 | } 213 | 214 | // internal recursive function to print a tree 215 | func stringify(n *Node, level int) { 216 | if n != nil { 217 | format := "" 218 | for i := 0; i < level; i++ { 219 | format += " " 220 | } 221 | format += "---[ " 222 | level++ 223 | stringify(n.left, level) 224 | fmt.Printf(format+"%d\n", n.key) 225 | stringify(n.right, level) 226 | } 227 | } 228 | -------------------------------------------------------------------------------- /algorithm/bst/bst_test.go: -------------------------------------------------------------------------------- 1 | package binarysearchtree 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | var bst ItemBinarySearchTree 9 | 10 | func fillTree(bst *ItemBinarySearchTree) { 11 | bst.Insert(8, "8") 12 | bst.Insert(4, "4") 13 | bst.Insert(10, "10") 14 | bst.Insert(2, "2") 15 | bst.Insert(6, "6") 16 | bst.Insert(1, "1") 17 | bst.Insert(3, "3") 18 | bst.Insert(5, "5") 19 | bst.Insert(7, "7") 20 | bst.Insert(9, "9") 21 | } 22 | 23 | func TestInsert(t *testing.T) { 24 | fillTree(&bst) 25 | bst.String() 26 | 27 | bst.Insert(11, "11") 28 | bst.String() 29 | } 30 | 31 | // isSameSlice returns true if the 2 slices are identical 32 | func isSameSlice(a, b []string) bool { 33 | if a == nil && b == nil { 34 | return true 35 | } 36 | if a == nil || b == nil { 37 | return false 38 | } 39 | if len(a) != len(b) { 40 | return false 41 | } 42 | for i := range a { 43 | if a[i] != b[i] { 44 | return false 45 | } 46 | } 47 | return true 48 | } 49 | 50 | func TestInOrderTraverse(t *testing.T) { 51 | var result []string 52 | bst.InOrderTraverse(func(i Item) { 53 | result = append(result, fmt.Sprintf("%s", i)) 54 | }) 55 | if !isSameSlice(result, []string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"}) { 56 | t.Errorf("Traversal order incorrect, got %v", result) 57 | } 58 | } 59 | 60 | func TestPreOrderTraverse(t *testing.T) { 61 | var result []string 62 | bst.PreOrderTraverse(func(i Item) { 63 | result = append(result, fmt.Sprintf("%s", i)) 64 | }) 65 | if !isSameSlice(result, []string{"8", "4", "2", "1", "3", "6", "5", "7", "10", "9", "11"}) { 66 | t.Errorf("Traversal order incorrect, got %v instead of %v", result, []string{"8", "4", "2", "1", "3", "6", "5", "7", "10", "9", "11"}) 67 | } 68 | } 69 | 70 | func TestPostOrderTraverse(t *testing.T) { 71 | var result []string 72 | bst.PostOrderTraverse(func(i Item) { 73 | result = append(result, fmt.Sprintf("%s", i)) 74 | }) 75 | if !isSameSlice(result, []string{"1", "3", "2", "5", "7", "6", "4", "9", "11", "10", "8"}) { 76 | t.Errorf("Traversal order incorrect, got %v instead of %v", result, []string{"1", "3", "2", "5", "7", "6", "4", "9", "11", "10", "8"}) 77 | } 78 | } 79 | 80 | func TestMin(t *testing.T) { 81 | if fmt.Sprintf("%s", *bst.Min()) != "1" { 82 | t.Errorf("min should be 1") 83 | } 84 | } 85 | 86 | func TestMax(t *testing.T) { 87 | if fmt.Sprintf("%s", *bst.Max()) != "11" { 88 | t.Errorf("max should be 11") 89 | } 90 | } 91 | 92 | func TestSearch(t *testing.T) { 93 | if !bst.Search(1) || !bst.Search(8) || !bst.Search(11) { 94 | t.Errorf("search not working") 95 | } 96 | } 97 | 98 | func TestRemove(t *testing.T) { 99 | bst.Remove(1) 100 | if fmt.Sprintf("%s", *bst.Min()) != "2" { 101 | t.Errorf("min should be 2") 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /algorithm/bst/go.mod: -------------------------------------------------------------------------------- 1 | module bst 2 | 3 | go 1.17 4 | 5 | require github.com/cheekybits/genny v1.0.0 6 | -------------------------------------------------------------------------------- /algorithm/bst/go.sum: -------------------------------------------------------------------------------- 1 | github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= 2 | github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= 3 | -------------------------------------------------------------------------------- /algorithm/quicksort/quicksort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func partition(list []int, low, high int) int { 6 | // 选择基准值 7 | pivot := list[high] 8 | for low < high { 9 | // low 指针值 <= pivot low 指针右移 10 | for low < high && pivot >= list[low] { 11 | low++ 12 | } 13 | // low 指针值 > pivot low 值移到 high 位置 14 | list[high] = list[low] 15 | 16 | // high 指针值 >= pivot high 指针左移 17 | for low < high && pivot <= list[high] { 18 | high-- 19 | } 20 | // high 指针值 < pivot high 值移到 low 位置 21 | list[low] = list[high] 22 | } 23 | // pivot 替换 high 值 24 | list[high] = pivot 25 | return high 26 | } 27 | 28 | func QuickSort(list []int, low, high int) { 29 | if high > low { 30 | // 分区 31 | pivot := partition(list, low, high) 32 | // 左边部分排序 33 | QuickSort(list, low, pivot-1) 34 | // 右边部分排序 35 | QuickSort(list, pivot+1, high) 36 | } 37 | } 38 | 39 | func main() { 40 | list := []int{2, 44, 4, 8, 33, 1, 22, -11, 6, 34, 55, 54, 9} 41 | QuickSort(list, 0, len(list)-1) 42 | fmt.Println(list) 43 | } 44 | -------------------------------------------------------------------------------- /algorithm/search/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/yongxin/go-example/algorithm/search 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/stretchr/testify v1.8.4 7 | github.com/zeromicro/go-zero v1.5.4 8 | ) 9 | 10 | require ( 11 | github.com/davecgh/go-spew v1.1.1 // indirect 12 | github.com/pmezard/go-difflib v1.0.0 // indirect 13 | gopkg.in/yaml.v3 v3.0.1 // indirect 14 | ) 15 | -------------------------------------------------------------------------------- /algorithm/search/go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 2 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 4 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 5 | github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= 6 | github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 7 | github.com/zeromicro/go-zero v1.5.4 h1:kRvcYuxcHOkUZvg7887KQl77Qv4klGL7MqGkTBgkpS8= 8 | github.com/zeromicro/go-zero v1.5.4/go.mod h1:x/aUyLmSwRECvOyjOf+lhwThBOilJIY+s3slmPAeboA= 9 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 10 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 11 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 12 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 13 | -------------------------------------------------------------------------------- /algorithm/search/tree.go: -------------------------------------------------------------------------------- 1 | package search 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | ) 7 | 8 | const ( 9 | colon = ':' 10 | slash = '/' 11 | ) 12 | 13 | var ( 14 | // errDupItem means adding duplicated item. 15 | errDupItem = errors.New("duplicated item") 16 | // errDupSlash means item is started with more than one slash. 17 | errDupSlash = errors.New("duplicated slash") 18 | // errEmptyItem means adding empty item. 19 | errEmptyItem = errors.New("empty item") 20 | // errInvalidState means search tree is in an invalid state. 21 | errInvalidState = errors.New("search tree is in an invalid state") 22 | // errNotFromRoot means path is not starting with slash. 23 | errNotFromRoot = errors.New("path should start with /") 24 | 25 | // NotFound is used to hold the not found result. 26 | NotFound Result 27 | ) 28 | 29 | type ( 30 | innerResult struct { 31 | key string 32 | value string 33 | named bool 34 | found bool 35 | } 36 | 37 | node struct { 38 | item interface{} 39 | children [2]map[string]*node 40 | } 41 | 42 | // A Tree is a search tree. 43 | Tree struct { 44 | root *node 45 | } 46 | 47 | // A Result is a search result from tree. 48 | Result struct { 49 | Item interface{} 50 | Params map[string]string 51 | } 52 | ) 53 | 54 | // NewTree returns a Tree. 55 | func NewTree() *Tree { 56 | return &Tree{ 57 | root: newNode(nil), 58 | } 59 | } 60 | 61 | // Add adds item to associate with route. 62 | func (t *Tree) Add(route string, item interface{}) error { 63 | if len(route) == 0 || route[0] != slash { 64 | return errNotFromRoot 65 | } 66 | 67 | if item == nil { 68 | return errEmptyItem 69 | } 70 | 71 | err := add(t.root, route[1:], item) 72 | switch err { 73 | case errDupItem: 74 | return duplicatedItem(route) 75 | case errDupSlash: 76 | return duplicatedSlash(route) 77 | default: 78 | return err 79 | } 80 | } 81 | 82 | // Search searches item that associates with given route. 83 | func (t *Tree) Search(route string) (Result, bool) { 84 | if len(route) == 0 || route[0] != slash { 85 | return NotFound, false 86 | } 87 | 88 | var result Result 89 | ok := t.next(t.root, route[1:], &result) 90 | return result, ok 91 | } 92 | 93 | func (t *Tree) next(n *node, route string, result *Result) bool { 94 | if len(route) == 0 && n.item != nil { 95 | result.Item = n.item 96 | return true 97 | } 98 | 99 | for i := range route { 100 | if route[i] != slash { 101 | continue 102 | } 103 | 104 | token := route[:i] 105 | return n.forEach(func(k string, v *node) bool { 106 | r := match(k, token) 107 | if !r.found || !t.next(v, route[i+1:], result) { 108 | return false 109 | } 110 | if r.named { 111 | addParam(result, r.key, r.value) 112 | } 113 | 114 | return true 115 | }) 116 | } 117 | 118 | return n.forEach(func(k string, v *node) bool { 119 | if r := match(k, route); r.found && v.item != nil { 120 | result.Item = v.item 121 | if r.named { 122 | addParam(result, r.key, r.value) 123 | } 124 | 125 | return true 126 | } 127 | 128 | return false 129 | }) 130 | } 131 | 132 | func (nd *node) forEach(fn func(string, *node) bool) bool { 133 | for _, children := range nd.children { 134 | for k, v := range children { 135 | if fn(k, v) { 136 | return true 137 | } 138 | } 139 | } 140 | 141 | return false 142 | } 143 | 144 | func (nd *node) getChildren(route string) map[string]*node { 145 | if len(route) > 0 && route[0] == colon { 146 | return nd.children[1] 147 | } 148 | 149 | return nd.children[0] 150 | } 151 | 152 | func add(nd *node, route string, item interface{}) error { 153 | if len(route) == 0 { 154 | if nd.item != nil { 155 | return errDupItem 156 | } 157 | 158 | nd.item = item 159 | return nil 160 | } 161 | 162 | if route[0] == slash { 163 | return errDupSlash 164 | } 165 | 166 | for i := range route { 167 | if route[i] != slash { 168 | continue 169 | } 170 | 171 | token := route[:i] 172 | children := nd.getChildren(token) 173 | if child, ok := children[token]; ok { 174 | if child != nil { 175 | return add(child, route[i+1:], item) 176 | } 177 | 178 | return errInvalidState 179 | } 180 | 181 | child := newNode(nil) 182 | children[token] = child 183 | return add(child, route[i+1:], item) 184 | } 185 | 186 | children := nd.getChildren(route) 187 | if child, ok := children[route]; ok { 188 | if child.item != nil { 189 | return errDupItem 190 | } 191 | 192 | child.item = item 193 | } else { 194 | children[route] = newNode(item) 195 | } 196 | 197 | return nil 198 | } 199 | 200 | func addParam(result *Result, k, v string) { 201 | if result.Params == nil { 202 | result.Params = make(map[string]string) 203 | } 204 | 205 | result.Params[k] = v 206 | } 207 | 208 | func duplicatedItem(item string) error { 209 | return fmt.Errorf("duplicated item for %s", item) 210 | } 211 | 212 | func duplicatedSlash(item string) error { 213 | return fmt.Errorf("duplicated slash for %s", item) 214 | } 215 | 216 | func match(pat, token string) innerResult { 217 | if pat[0] == colon { 218 | return innerResult{ 219 | key: pat[1:], 220 | value: token, 221 | named: true, 222 | found: true, 223 | } 224 | } 225 | 226 | return innerResult{ 227 | found: pat == token, 228 | } 229 | } 230 | 231 | func newNode(item interface{}) *node { 232 | return &node{ 233 | item: item, 234 | children: [2]map[string]*node{ 235 | make(map[string]*node), 236 | make(map[string]*node), 237 | }, 238 | } 239 | } 240 | -------------------------------------------------------------------------------- /algorithm/search/tree_test.go: -------------------------------------------------------------------------------- 1 | package search 2 | 3 | import ( 4 | "math/rand" 5 | "strings" 6 | "testing" 7 | 8 | "github.com/stretchr/testify/assert" 9 | "github.com/zeromicro/go-zero/core/stringx" 10 | ) 11 | 12 | type mockedRoute struct { 13 | route string 14 | value int 15 | } 16 | 17 | func TestSearch(t *testing.T) { 18 | routes := []mockedRoute{ 19 | {"/", 1}, 20 | {"/api", 2}, 21 | {"/img", 3}, 22 | {"/:layer1", 4}, 23 | {"/api/users", 5}, 24 | {"/img/jpgs", 6}, 25 | {"/img/jpgs", 7}, 26 | {"/api/:layer2", 8}, 27 | {"/:layer1/:layer2", 9}, 28 | {"/:layer1/:layer2/users", 10}, 29 | } 30 | 31 | tests := []struct { 32 | query string 33 | expect int 34 | params map[string]string 35 | contains bool 36 | }{ 37 | { 38 | query: "", 39 | contains: false, 40 | }, 41 | { 42 | query: "/", 43 | expect: 1, 44 | contains: true, 45 | }, 46 | { 47 | query: "/wildcard", 48 | expect: 4, 49 | params: map[string]string{ 50 | "layer1": "wildcard", 51 | }, 52 | contains: true, 53 | }, 54 | { 55 | query: "/wildcard/", 56 | expect: 4, 57 | params: map[string]string{ 58 | "layer1": "wildcard", 59 | }, 60 | contains: true, 61 | }, 62 | { 63 | query: "/a/b/c", 64 | contains: false, 65 | }, 66 | { 67 | query: "/a/b", 68 | expect: 9, 69 | params: map[string]string{ 70 | "layer1": "a", 71 | "layer2": "b", 72 | }, 73 | contains: true, 74 | }, 75 | { 76 | query: "/a/b/", 77 | expect: 9, 78 | params: map[string]string{ 79 | "layer1": "a", 80 | "layer2": "b", 81 | }, 82 | contains: true, 83 | }, 84 | { 85 | query: "/a/b/users", 86 | expect: 10, 87 | params: map[string]string{ 88 | "layer1": "a", 89 | "layer2": "b", 90 | }, 91 | contains: true, 92 | }, 93 | } 94 | 95 | for _, test := range tests { 96 | t.Run(test.query, func(t *testing.T) { 97 | tree := NewTree() 98 | for _, r := range routes { 99 | tree.Add(r.route, r.value) 100 | } 101 | result, ok := tree.Search(test.query) 102 | assert.Equal(t, test.contains, ok) 103 | if ok { 104 | actual := result.Item.(int) 105 | assert.EqualValues(t, test.params, result.Params) 106 | assert.Equal(t, test.expect, actual) 107 | } 108 | }) 109 | } 110 | } 111 | 112 | func TestStrictSearch(t *testing.T) { 113 | routes := []mockedRoute{ 114 | {"/api/users", 1}, 115 | {"/api/:layer", 2}, 116 | } 117 | query := "/api/users" 118 | 119 | tree := NewTree() 120 | for _, r := range routes { 121 | tree.Add(r.route, r.value) 122 | } 123 | 124 | for i := 0; i < 1000; i++ { 125 | result, ok := tree.Search(query) 126 | assert.True(t, ok) 127 | assert.Equal(t, 1, result.Item.(int)) 128 | } 129 | } 130 | 131 | func TestStrictSearchSibling(t *testing.T) { 132 | routes := []mockedRoute{ 133 | {"/api/:user/profile/name", 1}, 134 | {"/api/:user/profile", 2}, 135 | {"/api/:user/name", 3}, 136 | {"/api/:layer", 4}, 137 | } 138 | query := "/api/123/name" 139 | 140 | tree := NewTree() 141 | for _, r := range routes { 142 | tree.Add(r.route, r.value) 143 | } 144 | 145 | result, ok := tree.Search(query) 146 | assert.True(t, ok) 147 | assert.Equal(t, 3, result.Item.(int)) 148 | } 149 | 150 | func TestAddDuplicate(t *testing.T) { 151 | tree := NewTree() 152 | err := tree.Add("/a/b", 1) 153 | assert.Nil(t, err) 154 | err = tree.Add("/a/b", 2) 155 | assert.Error(t, errDupItem, err) 156 | err = tree.Add("/a/b/", 2) 157 | assert.Error(t, errDupItem, err) 158 | } 159 | 160 | func TestPlain(t *testing.T) { 161 | tree := NewTree() 162 | err := tree.Add("/a/b", 1) 163 | assert.Nil(t, err) 164 | err = tree.Add("/a/c", 2) 165 | assert.Nil(t, err) 166 | _, ok := tree.Search("/a/d") 167 | assert.False(t, ok) 168 | } 169 | 170 | func TestSearchWithDoubleSlashes(t *testing.T) { 171 | tree := NewTree() 172 | err := tree.Add("//a", 1) 173 | assert.Error(t, errDupSlash, err) 174 | } 175 | 176 | func TestSearchInvalidRoute(t *testing.T) { 177 | tree := NewTree() 178 | err := tree.Add("", 1) 179 | assert.Equal(t, errNotFromRoot, err) 180 | err = tree.Add("bad", 1) 181 | assert.Equal(t, errNotFromRoot, err) 182 | } 183 | 184 | func TestSearchInvalidItem(t *testing.T) { 185 | tree := NewTree() 186 | err := tree.Add("/", nil) 187 | assert.Equal(t, errEmptyItem, err) 188 | } 189 | 190 | func BenchmarkSearchTree(b *testing.B) { 191 | const ( 192 | avgLen = 1000 193 | entries = 10000 194 | ) 195 | 196 | tree := NewTree() 197 | generate := func() string { 198 | var buf strings.Builder 199 | size := rand.Intn(avgLen) + avgLen/2 200 | val := stringx.Randn(size) 201 | prev := 0 202 | for j := rand.Intn(9) + 1; j < size; j += rand.Intn(9) + 1 { 203 | buf.WriteRune('/') 204 | buf.WriteString(val[prev:j]) 205 | prev = j 206 | } 207 | if prev < size { 208 | buf.WriteRune('/') 209 | buf.WriteString(val[prev:]) 210 | } 211 | return buf.String() 212 | } 213 | index := rand.Intn(entries) 214 | var query string 215 | for i := 0; i < entries; i++ { 216 | val := generate() 217 | if i == index { 218 | query = val 219 | } 220 | tree.Add(val, i) 221 | } 222 | 223 | for i := 0; i < b.N; i++ { 224 | tree.Search(query) 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /basic-example/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yongxinz/go-example/1f1a2374b166d05374a17982bab238eb04ba4476/basic-example/.DS_Store -------------------------------------------------------------------------------- /basic-example/01-hello_world/hello_world.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println("hello world") 7 | } 8 | -------------------------------------------------------------------------------- /basic-example/02-values/values.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | ) 7 | 8 | func main() { 9 | fmt.Println("go" + "lang") 10 | 11 | fmt.Println("1 + 1 = ", 1+1) 12 | fmt.Println("7.0 / 3.0 = ", 7.0/3.0) 13 | 14 | // 向上取整 15 | fmt.Println("7.0 / 3.0 = ", math.Ceil(7.0/3.0)) 16 | // 向下取整 17 | fmt.Println("7.0 / 3.0 = ", math.Floor(7.0/3.0)) 18 | // 四舍五入 19 | fmt.Println("7.0 / 3.0 = ", math.Floor(7.0/3.0+0.5)) 20 | 21 | fmt.Println(true && false) 22 | fmt.Println(true || false) 23 | fmt.Println(!true) 24 | } 25 | -------------------------------------------------------------------------------- /basic-example/03-variables/variables.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func main() { 8 | var a int 9 | a = 1 10 | fmt.Println(a) 11 | 12 | var b, c int = 2, 3 13 | fmt.Println(b, c) 14 | 15 | var d int 16 | fmt.Println(d) 17 | 18 | var e = true 19 | fmt.Println(e) 20 | 21 | f := 12 22 | fmt.Println(f) 23 | } 24 | -------------------------------------------------------------------------------- /basic-example/04-constants/constants.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | const s string = "hello world" 6 | 7 | func main() { 8 | fmt.Println(s) 9 | 10 | const a = 300 11 | fmt.Println(a) 12 | } 13 | -------------------------------------------------------------------------------- /basic-example/05-for/for.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | i := 1 7 | for i <= 3 { 8 | fmt.Println(i) 9 | i += 1 10 | } 11 | 12 | for j := 0; j <= 5; j++ { 13 | fmt.Println(j) 14 | } 15 | 16 | for { 17 | fmt.Println("loop") 18 | break 19 | } 20 | 21 | for m := 0; m <= 10; m++ { 22 | if m%2 == 0 { 23 | continue 24 | } 25 | 26 | fmt.Println(m) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /basic-example/06-if_else/if_else.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | 7 | if 7%2 == 0 { 8 | fmt.Println("7 is even") 9 | } else { 10 | fmt.Println("7 is odd") 11 | } 12 | 13 | if 8%4 == 0 { 14 | fmt.Println("8 is divisible by 4") 15 | } 16 | 17 | if num := 9; num < 0 { 18 | fmt.Println(num, "is negative") 19 | } else if num < 10 { 20 | fmt.Println(num, "has 1 digit") 21 | } else { 22 | fmt.Println(num, "has multiple digits") 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /basic-example/07-switch/switch.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func main() { 9 | i := 2 10 | 11 | fmt.Print("Write ", i, " as ") 12 | switch i { 13 | case 1: 14 | fmt.Println("one") 15 | case 2: 16 | fmt.Println("two") 17 | case 3: 18 | fmt.Println("three") 19 | } 20 | 21 | switch time.Now().Weekday() { 22 | case time.Saturday, time.Sunday: 23 | fmt.Println("it is weekend") 24 | default: 25 | fmt.Println("it is workday") 26 | } 27 | 28 | t := time.Now() 29 | switch { 30 | case t.Hour() < 12: 31 | fmt.Println("it is before none") 32 | default: 33 | fmt.Println("it is after none") 34 | } 35 | 36 | whatAmI := func(i interface{}) { 37 | switch t := i.(type) { 38 | case bool: 39 | fmt.Println("it is bool") 40 | case int: 41 | fmt.Println("it is int") 42 | default: 43 | fmt.Printf("it is unknown type %T\n", t) 44 | } 45 | } 46 | 47 | whatAmI(true) 48 | whatAmI(1) 49 | whatAmI("hello") 50 | } 51 | -------------------------------------------------------------------------------- /basic-example/08-array/array.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var a [5]int 7 | 8 | fmt.Println("emp: ", a) 9 | 10 | a[4] = 100 11 | fmt.Println("set: ", a) 12 | fmt.Println("get: ", a[4]) 13 | 14 | b := []int{1, 2, 3, 4, 5} 15 | fmt.Println("dcl: ", b) 16 | 17 | var c [2][3]int 18 | for i := 0; i < 2; i++ { 19 | for j := 0; j < 3; j++ { 20 | c[i][j] = i + j 21 | } 22 | } 23 | fmt.Println("2d: ", c) 24 | } 25 | -------------------------------------------------------------------------------- /basic-example/09-slice/slice-layout.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "reflect" 4 | 5 | var sum int64 6 | 7 | func addUpDirect(s []int64) { 8 | for i := 0; i < len(s); i++ { 9 | sum += s[i] 10 | } 11 | } 12 | 13 | func addUpViaInterface(s []interface{}) { 14 | for i := 0; i < len(s); i++ { 15 | sum += s[i].(int64) 16 | } 17 | } 18 | 19 | func InterfaceSlice(slice interface{}) []interface{} { 20 | s := reflect.ValueOf(slice) 21 | if s.Kind() != reflect.Slice { 22 | panic("InterfaceSlice() given a non-slice type") 23 | } 24 | 25 | // Keep the distinction between nil and empty slice input 26 | if s.IsNil() { 27 | return nil 28 | } 29 | 30 | ret := make([]interface{}, s.Len()) 31 | 32 | for i := 0; i < s.Len(); i++ { 33 | ret[i] = s.Index(i).Interface() 34 | } 35 | 36 | return ret 37 | } 38 | 39 | func main() { 40 | is := []int64{0x55, 0x22, 0xab, 0x9} 41 | 42 | addUpDirect(is) 43 | 44 | iis := make([]interface{}, len(is)) 45 | for i := 0; i < len(is); i++ { 46 | iis[i] = is[i] 47 | } 48 | 49 | addUpViaInterface(iis) 50 | } 51 | -------------------------------------------------------------------------------- /basic-example/09-slice/slice.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | i := make([]int, 3) 7 | fmt.Println("i: ", i) 8 | 9 | s := make([]string, 3) 10 | fmt.Println("s: ", s) 11 | 12 | s[0] = "a" 13 | s[1] = "b" 14 | s[2] = "c" 15 | fmt.Println("set: ", s) 16 | fmt.Println("get: ", s[2]) 17 | 18 | fmt.Println("len: ", len(s)) 19 | 20 | s = append(s, "d") 21 | s = append(s, "e", "f") 22 | fmt.Println("append: ", s) 23 | fmt.Println("len: ", len(s)) 24 | 25 | c := make([]string, len(s)) 26 | copy(c, s) 27 | fmt.Println("c: ", c) 28 | 29 | fmt.Println("c[2:5]: ", c[2:5]) 30 | 31 | d := make([][]int, 3) 32 | for m := 0; m < 3; m++ { 33 | innerLen := m + 1 34 | d[m] = make([]int, innerLen) 35 | for n := 0; n < innerLen; n++ { 36 | d[m][n] = m + n 37 | } 38 | } 39 | fmt.Println("d: ", d) 40 | } 41 | -------------------------------------------------------------------------------- /basic-example/10-map/map.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | m := make(map[string]int) 7 | 8 | m["k1"] = 2 9 | m["k2"] = 300 10 | 11 | fmt.Println("m: ", m) 12 | 13 | v1 := m["k1"] 14 | fmt.Println("v1: ", v1) 15 | 16 | fmt.Println("map len: ", len(m)) 17 | 18 | m["k1"] = 3 19 | fmt.Println("m: ", m) 20 | 21 | delete(m, "k1") 22 | v1 = m["k1"] 23 | fmt.Println("v1: ", v1) 24 | 25 | _, prs := m["k1"] 26 | fmt.Println("prs: ", prs) 27 | 28 | n := map[string]int{"foo": 1, "bar": 2, "baz": 3} 29 | fmt.Println("n: ", n) 30 | } 31 | -------------------------------------------------------------------------------- /basic-example/10-map/rwlockmap.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | ) 7 | 8 | type SafeMap struct { 9 | sync.RWMutex 10 | Map map[string]string 11 | } 12 | 13 | func NewSafeMap() *SafeMap { 14 | sm := new(SafeMap) 15 | sm.Map = make(map[string]string) 16 | return sm 17 | } 18 | 19 | func (sm *SafeMap) ReadMap(key string) string { 20 | sm.RLock() 21 | value := sm.Map[key] 22 | sm.RUnlock() 23 | return value 24 | } 25 | 26 | func (sm *SafeMap) WriteMap(key string, value string) { 27 | sm.Lock() 28 | sm.Map[key] = value 29 | sm.Unlock() 30 | } 31 | 32 | func main() { 33 | safeMap := NewSafeMap() 34 | 35 | var wg sync.WaitGroup 36 | 37 | // 启动多个goroutine进行写操作 38 | for i := 0; i < 10; i++ { 39 | wg.Add(1) 40 | go func(i int) { 41 | defer wg.Done() 42 | safeMap.WriteMap(fmt.Sprintf("name%d", i), fmt.Sprintf("John%d", i)) 43 | }(i) 44 | } 45 | 46 | wg.Wait() 47 | 48 | // 启动多个goroutine进行读操作 49 | for i := 0; i < 10; i++ { 50 | wg.Add(1) 51 | go func(i int) { 52 | defer wg.Done() 53 | fmt.Println(safeMap.ReadMap(fmt.Sprintf("name%d", i))) 54 | }(i) 55 | } 56 | 57 | wg.Wait() 58 | } 59 | -------------------------------------------------------------------------------- /basic-example/10-map/shardmap.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | ) 7 | 8 | const N = 16 9 | 10 | type SafeMap struct { 11 | maps [N]map[string]string 12 | locks [N]sync.RWMutex 13 | } 14 | 15 | func NewSafeMap() *SafeMap { 16 | sm := new(SafeMap) 17 | for i := 0; i < N; i++ { 18 | sm.maps[i] = make(map[string]string) 19 | } 20 | return sm 21 | } 22 | 23 | func (sm *SafeMap) ReadMap(key string) string { 24 | index := hash(key) % N 25 | sm.locks[index].RLock() 26 | value := sm.maps[index][key] 27 | sm.locks[index].RUnlock() 28 | return value 29 | } 30 | 31 | func (sm *SafeMap) WriteMap(key string, value string) { 32 | index := hash(key) % N 33 | sm.locks[index].Lock() 34 | sm.maps[index][key] = value 35 | sm.locks[index].Unlock() 36 | } 37 | 38 | func hash(s string) int { 39 | h := 0 40 | for i := 0; i < len(s); i++ { 41 | h = 31*h + int(s[i]) 42 | } 43 | return h 44 | } 45 | 46 | func main() { 47 | safeMap := NewSafeMap() 48 | 49 | var wg sync.WaitGroup 50 | 51 | // 启动多个goroutine进行写操作 52 | for i := 0; i < 10; i++ { 53 | wg.Add(1) 54 | go func(i int) { 55 | defer wg.Done() 56 | safeMap.WriteMap(fmt.Sprintf("name%d", i), fmt.Sprintf("John%d", i)) 57 | }(i) 58 | } 59 | 60 | wg.Wait() 61 | 62 | // 启动多个goroutine进行读操作 63 | for i := 0; i < 10; i++ { 64 | wg.Add(1) 65 | go func(i int) { 66 | defer wg.Done() 67 | fmt.Println(safeMap.ReadMap(fmt.Sprintf("name%d", i))) 68 | }(i) 69 | } 70 | 71 | wg.Wait() 72 | } 73 | -------------------------------------------------------------------------------- /basic-example/10-map/sortedmap.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | ) 7 | 8 | func main() { 9 | m := map[string]int{ 10 | "apple": 1, 11 | "banana": 2, 12 | "orange": 3, 13 | } 14 | 15 | // 将 map 中的键存储到切片中 16 | keys := make([]string, 0, len(m)) 17 | for k := range m { 18 | keys = append(keys, k) 19 | } 20 | 21 | // 对切片进行排序 22 | sort.Strings(keys) 23 | 24 | // 按照排序后的顺序遍历 map 25 | for _, k := range keys { 26 | fmt.Printf("key=%s, value=%d\n", k, m[k]) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /basic-example/10-map/syncmap.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | ) 7 | 8 | func main() { 9 | var m sync.Map 10 | var wg sync.WaitGroup 11 | 12 | // 启动多个goroutine进行写操作 13 | for i := 0; i < 10; i++ { 14 | wg.Add(1) 15 | go func(i int) { 16 | defer wg.Done() 17 | m.Store(fmt.Sprintf("name%d", i), fmt.Sprintf("John%d", i)) 18 | }(i) 19 | } 20 | 21 | wg.Wait() 22 | 23 | // 启动多个goroutine进行读操作 24 | for i := 0; i < 10; i++ { 25 | wg.Add(1) 26 | go func(i int) { 27 | defer wg.Done() 28 | v, _ := m.Load(fmt.Sprintf("name%d", i)) 29 | fmt.Println(v.(string)) 30 | }(i) 31 | } 32 | 33 | wg.Wait() 34 | } 35 | -------------------------------------------------------------------------------- /basic-example/10-map/unsafemap.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "sync" 4 | 5 | func main() { 6 | m := make(map[string]int) 7 | m["foo"] = 1 8 | 9 | var wg sync.WaitGroup 10 | wg.Add(2) 11 | 12 | go func() { 13 | for i := 0; i < 1000; i++ { 14 | m["foo"]++ 15 | } 16 | wg.Done() 17 | }() 18 | 19 | go func() { 20 | for i := 0; i < 1000; i++ { 21 | m["foo"]++ 22 | } 23 | wg.Done() 24 | }() 25 | 26 | wg.Wait() 27 | } 28 | -------------------------------------------------------------------------------- /basic-example/11-range/range.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | num := []int{1, 2, 3, 4, 5} 7 | 8 | sum := 0 9 | for _, i := range num { 10 | sum += i 11 | } 12 | fmt.Println("sum = ", sum) 13 | 14 | for i, n := range num { 15 | if n == 3 { 16 | fmt.Println("i = ", i) 17 | } 18 | } 19 | 20 | kvs := map[string]string{"a": "apple", "b": "banana"} 21 | for k, v := range kvs { 22 | fmt.Println("k -> v: ", k, v) 23 | } 24 | 25 | for k := range kvs { 26 | fmt.Println("key: ", k) 27 | } 28 | 29 | for k, v := range "abc" { 30 | fmt.Println("k, v: ", k, v) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /basic-example/12-function/function.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func add(a int, b int) int { 6 | return a + b 7 | } 8 | 9 | func addAdd(a, b, c int) int { 10 | return a + b + c 11 | } 12 | 13 | func main() { 14 | r := add(1, 2) 15 | fmt.Println("a + b = ", r) 16 | 17 | r = addAdd(1, 2, 3) 18 | fmt.Println("a + b + c = ", r) 19 | } 20 | -------------------------------------------------------------------------------- /basic-example/13-muti_return_values/multi_return_values.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func vals() (int, int) { 6 | return 3, 5 7 | } 8 | 9 | func main() { 10 | a, b := vals() 11 | fmt.Println(a, b) 12 | 13 | _, c := vals() 14 | fmt.Println(c) 15 | } 16 | -------------------------------------------------------------------------------- /basic-example/14-variadic_functions/variadic_functions.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func sum(nums ...int) { 6 | fmt.Print(nums, " ") 7 | total := 0 8 | for _, n := range nums { 9 | total += n 10 | } 11 | fmt.Println(total) 12 | } 13 | 14 | func main() { 15 | sum(1, 2) 16 | sum(1, 2, 3) 17 | 18 | nums := []int{1, 2, 3, 4} 19 | sum(nums...) 20 | } 21 | -------------------------------------------------------------------------------- /basic-example/15-closures.go/closures.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func intSeq() func() int { 6 | i := 1 7 | return func() int { 8 | i++ 9 | return i 10 | } 11 | } 12 | 13 | func main() { 14 | nxtInt := intSeq() 15 | 16 | fmt.Println(nxtInt()) 17 | fmt.Println(nxtInt()) 18 | fmt.Println(nxtInt()) 19 | 20 | nxtInts := intSeq() 21 | fmt.Println(nxtInts()) 22 | } 23 | -------------------------------------------------------------------------------- /basic-example/16-recursion/recursion.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func fact(a int) int { 6 | if a == 0 { 7 | return 1 8 | } 9 | return a * fact(a-1) 10 | } 11 | 12 | func main() { 13 | n := fact(7) 14 | fmt.Println(n) 15 | } 16 | -------------------------------------------------------------------------------- /basic-example/17-pointers/pointers.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func zeroval(n int) { 6 | n = 0 7 | } 8 | 9 | func zeroptr(ptr *int) { 10 | *ptr = 0 11 | } 12 | 13 | func main() { 14 | i := 1 15 | fmt.Println("init: ", i) 16 | 17 | zeroval(i) 18 | fmt.Println("zeroval: ", i) 19 | 20 | zeroptr(&i) 21 | fmt.Println("zeroptr: ", i) 22 | 23 | fmt.Println("ptr: ", &i) 24 | } 25 | -------------------------------------------------------------------------------- /basic-example/18-struct/struct.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type person struct { 6 | name string 7 | age int 8 | } 9 | 10 | func newPerson(name string) *person { 11 | p := person{name: name} 12 | p.age = 41 13 | return &p 14 | } 15 | 16 | func main() { 17 | fmt.Println(person{"Bob", 20}) 18 | 19 | fmt.Println(person{name: "John", age: 30}) 20 | 21 | fmt.Println(person{name: "Tom"}) 22 | 23 | fmt.Println(&person{name: "Ann", age: 40}) 24 | 25 | fmt.Println(newPerson("Jack")) 26 | 27 | // s := person{"Pony", 50} 28 | // s.age = 51 29 | // fmt.Println(s) 30 | 31 | s := person{name: "Sean", age: 50} 32 | fmt.Println(s.name) 33 | 34 | sp := &s 35 | fmt.Println(sp.age) 36 | 37 | sp.age = 51 38 | fmt.Println(sp.age) 39 | fmt.Println(s) 40 | } 41 | -------------------------------------------------------------------------------- /basic-example/19-methods/methods.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type rect struct { 6 | width, height int 7 | } 8 | 9 | func (r rect) area() int { 10 | return r.width * r.height 11 | } 12 | 13 | func (r *rect) perim() int { 14 | return 2*r.width + 2*r.height 15 | } 16 | 17 | func main() { 18 | r := rect{width: 10, height: 5} 19 | fmt.Println("area: ", r.area()) 20 | fmt.Println("perim: ", r.perim()) 21 | 22 | rp := &r 23 | fmt.Println("area: ", rp.area()) 24 | fmt.Println("perim: ", rp.perim()) 25 | } 26 | -------------------------------------------------------------------------------- /basic-example/20-interfaces/interfaces.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | ) 7 | 8 | type geometry interface { 9 | area() float64 10 | perim() float64 11 | } 12 | 13 | type rect struct { 14 | width, height float64 15 | } 16 | 17 | type circle struct { 18 | radius float64 19 | } 20 | 21 | func (r rect) area() float64 { 22 | return r.width * r.height 23 | } 24 | 25 | func (r rect) perim() float64 { 26 | return 2*r.width + 2*r.height 27 | } 28 | 29 | func (c circle) area() float64 { 30 | return math.Pi * c.radius * c.radius 31 | } 32 | 33 | func (c circle) perim() float64 { 34 | return 2 * math.Pi * c.radius 35 | } 36 | 37 | func measure(g geometry) { 38 | fmt.Println("g: ", g) 39 | fmt.Println("area: ", g.area()) 40 | fmt.Println("perim: ", g.perim()) 41 | } 42 | 43 | func main() { 44 | r := rect{width: 10, height: 5} 45 | c := circle{radius: 5} 46 | 47 | measure(r) 48 | measure(c) 49 | } 50 | -------------------------------------------------------------------------------- /basic-example/21-errors/errors.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | ) 7 | 8 | func f1(arg int) (int, error) { 9 | if arg == 42 { 10 | return -1, errors.New("can not work with 42") 11 | } 12 | 13 | return arg + 3, nil 14 | } 15 | 16 | type argError struct { 17 | arg int 18 | prob string 19 | } 20 | 21 | func (e *argError) Error() string { 22 | return fmt.Sprintf("%d - %s", e.arg, e.prob) 23 | } 24 | 25 | func f2(arg int) (int, error) { 26 | if arg == 42 { 27 | return -1, &argError{arg, "cannot work with it"} 28 | } 29 | return arg + 3, nil 30 | } 31 | 32 | func main() { 33 | for _, i := range []int{4, 42} { 34 | if n, err := f1(i); err != nil { 35 | fmt.Println("f1 failed: ", err) 36 | } else { 37 | fmt.Println("f1 worked: ", n) 38 | } 39 | } 40 | 41 | for _, i := range []int{3, 42} { 42 | if r, e := f2(i); e != nil { 43 | fmt.Println("f2 failed: ", e) 44 | } else { 45 | fmt.Println("f2 worked: ", r) 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /basic-example/22-goroutines/goroutines.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func f1(msg string) { 9 | for i := 0; i < 3; i++ { 10 | fmt.Println(msg, " : ", i) 11 | } 12 | } 13 | 14 | func main() { 15 | f1("direct") 16 | 17 | go f1("goroutine") 18 | 19 | go func(msg string) { 20 | fmt.Println(msg) 21 | }("going") 22 | 23 | time.Sleep(time.Second) 24 | fmt.Println("Done") 25 | } 26 | -------------------------------------------------------------------------------- /basic-example/23-channels/channels.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | message := make(chan string) 7 | 8 | go func(msg string) { message <- msg }("hello channel") 9 | 10 | fmt.Println(<-message) 11 | } 12 | -------------------------------------------------------------------------------- /basic-example/24-channel_buffering/channel_buffering.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | message := make(chan string, 2) 7 | 8 | message <- "hello" 9 | message <- "channel" 10 | 11 | fmt.Println(<-message) 12 | fmt.Println(<-message) 13 | } 14 | -------------------------------------------------------------------------------- /basic-example/25-channel_sync/channel_sync.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func work(done chan bool) { 9 | fmt.Println("working ....") 10 | time.Sleep(time.Second) 11 | fmt.Println("done") 12 | 13 | done <- true 14 | } 15 | 16 | func main() { 17 | done := make(chan bool, 1) 18 | 19 | go work(done) 20 | 21 | <-done 22 | } 23 | -------------------------------------------------------------------------------- /basic-example/26-channel_directions/channel_directions.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func ping(pings chan<- string, msg string) { 6 | pings <- msg 7 | } 8 | 9 | func pong(pongs chan<- string, pings <-chan string) { 10 | msg := <-pings 11 | pongs <- msg 12 | } 13 | 14 | func main() { 15 | pings := make(chan string, 1) 16 | pongs := make(chan string, 1) 17 | 18 | ping(pings, "hello") 19 | pong(pongs, pings) 20 | 21 | fmt.Println(<-pongs) 22 | } 23 | -------------------------------------------------------------------------------- /basic-example/27-select/select.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func main() { 9 | c1 := make(chan string) 10 | c2 := make(chan string) 11 | 12 | go func() { 13 | time.Sleep(3 * time.Second) 14 | c1 <- "one" 15 | }() 16 | 17 | go func() { 18 | time.Sleep(3 * time.Second) 19 | c2 <- "tow" 20 | }() 21 | 22 | select { 23 | case msg := <-c1: 24 | fmt.Println(msg) 25 | case msg := <-c2: 26 | fmt.Println(msg) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /basic-example/28-timeouts/timeouts.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func main() { 9 | c1 := make(chan string, 1) 10 | go func() { 11 | time.Sleep(2 * time.Second) 12 | c1 <- "result 1" 13 | }() 14 | 15 | select { 16 | case msg := <-c1: 17 | fmt.Println(msg) 18 | case <-time.After(time.Second): 19 | fmt.Println("timeout 1") 20 | } 21 | 22 | c2 := make(chan string, 1) 23 | go func() { 24 | time.Sleep(2 * time.Second) 25 | c2 <- "result 2" 26 | }() 27 | 28 | select { 29 | case msg := <-c2: 30 | fmt.Println(msg) 31 | case <-time.After(3 * time.Second): 32 | fmt.Println("timeout 2") 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /basic-example/29-non_block_channel/non_block_channel.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func main() { 8 | message := make(chan string) 9 | // message := make(chan string, 1) 10 | signals := make(chan bool) 11 | 12 | select { 13 | case msg := <-message: 14 | fmt.Println("receive msg: ", msg) 15 | default: 16 | fmt.Println("no receive message") 17 | } 18 | 19 | msg := "hello" 20 | select { 21 | case message <- msg: 22 | fmt.Println("send msg: ", msg) 23 | default: 24 | fmt.Println("no send message") 25 | } 26 | 27 | select { 28 | case msg := <-message: 29 | fmt.Println("receive message: ", msg) 30 | case sig := <-signals: 31 | fmt.Println("receive sig: ", sig) 32 | default: 33 | fmt.Println("no active") 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /basic-example/30-close_channels/close_channels.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | jobs := make(chan int, 5) 7 | done := make(chan bool) 8 | 9 | go func() { 10 | for { 11 | j, more := <-jobs 12 | if more { 13 | fmt.Println("receive message: ", j) 14 | } else { 15 | fmt.Println("receive all message") 16 | done <- true 17 | return 18 | } 19 | } 20 | }() 21 | 22 | for i := 0; i < 3; i++ { 23 | jobs <- i 24 | fmt.Println("send message: ", i) 25 | } 26 | 27 | close(jobs) 28 | <-done 29 | } 30 | -------------------------------------------------------------------------------- /basic-example/31-range_over_channels/range_over_channels.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | ch := make(chan string, 2) 7 | 8 | ch <- "one" 9 | ch <- "two" 10 | close(ch) 11 | 12 | for i := range ch { 13 | fmt.Println(i) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /basic-example/32-timers/timers.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func main() { 9 | timer1 := time.NewTimer(2 * time.Second) 10 | 11 | <-timer1.C 12 | fmt.Println("timer1 fired") 13 | 14 | timer2 := time.NewTimer(time.Second) 15 | go func() { 16 | <-timer2.C 17 | fmt.Println("timer2 fired") 18 | }() 19 | 20 | stop2 := timer2.Stop() 21 | if stop2 { 22 | fmt.Println("timer2 stoped") 23 | } 24 | 25 | time.Sleep(2 * time.Second) 26 | } 27 | -------------------------------------------------------------------------------- /basic-example/33-tickers/tickers.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func main() { 9 | timer := time.NewTicker(2 * time.Second) 10 | ch := make(chan bool, 1) 11 | 12 | go func() { 13 | for { 14 | select { 15 | case <-ch: 16 | return 17 | case i := <-timer.C: 18 | fmt.Println("pro run at ", i) 19 | } 20 | } 21 | }() 22 | 23 | time.Sleep(5 * time.Second) 24 | timer.Stop() 25 | ch <- true 26 | } 27 | -------------------------------------------------------------------------------- /basic-example/34-worker_pool/worker_pool.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func worker(id int, jobs <-chan int, results chan<- int) { 9 | for job := range jobs { 10 | fmt.Println("worker ", id, "start job ", job) 11 | time.Sleep(time.Second) 12 | fmt.Println("worker ", id, "finish job ", job) 13 | results <- job * 2 14 | } 15 | } 16 | 17 | func main() { 18 | numJobs := 5 19 | jobs := make(chan int, numJobs) 20 | results := make(chan int, numJobs) 21 | 22 | for w := 1; w <= 3; w++ { 23 | go worker(w, jobs, results) 24 | } 25 | 26 | for i := 1; i <= numJobs; i++ { 27 | jobs <- i 28 | } 29 | close(jobs) 30 | 31 | for i := 1; i <= numJobs; i++ { 32 | <-results 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /basic-example/35-wait_groups/wait_groups.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | "time" 7 | ) 8 | 9 | func worker(id int, wg *sync.WaitGroup) { 10 | defer wg.Done() 11 | 12 | fmt.Println("worker", id, "start") 13 | time.Sleep(time.Second) 14 | fmt.Println("worker", id, "finish") 15 | } 16 | 17 | func main() { 18 | var wg sync.WaitGroup 19 | 20 | for i := 1; i <= 5; i++ { 21 | wg.Add(1) 22 | go worker(i, &wg) 23 | } 24 | 25 | wg.Wait() 26 | } 27 | -------------------------------------------------------------------------------- /basic-example/36-rate_limiting/rate_limiting.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func main() { 9 | nums := make(chan int, 5) 10 | 11 | for i := 1; i <= 5; i++ { 12 | nums <- i 13 | } 14 | close(nums) 15 | 16 | limiter := time.Tick(time.Second) 17 | for n := range nums { 18 | <-limiter 19 | fmt.Println("request ", n, time.Now()) 20 | } 21 | 22 | burstyLimiters := make(chan time.Time, 3) 23 | for i := 1; i <= 3; i++ { 24 | burstyLimiters <- time.Now() 25 | } 26 | 27 | go func() { 28 | for t := range time.Tick(time.Second) { 29 | burstyLimiters <- t 30 | } 31 | }() 32 | 33 | for i := 1; i <= 5; i++ { 34 | fmt.Println("request ", i, <-burstyLimiters) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /basic-example/37-atomic_counters/atomic_counters.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | "sync/atomic" 7 | ) 8 | 9 | func main() { 10 | var ops uint64 11 | 12 | var wg sync.WaitGroup 13 | 14 | for i := 0; i < 50; i++ { 15 | wg.Add(1) 16 | go func() { 17 | for j := 1; j <= 1000; j++ { 18 | atomic.AddUint64(&ops, 1) 19 | } 20 | wg.Done() 21 | }() 22 | } 23 | 24 | wg.Wait() 25 | fmt.Println(ops) 26 | } 27 | -------------------------------------------------------------------------------- /basic-example/38-mutexes/mutexes.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "sync" 7 | "sync/atomic" 8 | "time" 9 | ) 10 | 11 | func main() { 12 | 13 | var state = make(map[int]int) 14 | 15 | var mutex = &sync.Mutex{} 16 | 17 | var readOps uint64 18 | var writeOps uint64 19 | 20 | for r := 0; r < 100; r++ { 21 | go func() { 22 | total := 0 23 | for { 24 | 25 | key := rand.Intn(5) 26 | mutex.Lock() 27 | total += state[key] 28 | mutex.Unlock() 29 | atomic.AddUint64(&readOps, 1) 30 | 31 | time.Sleep(time.Millisecond) 32 | } 33 | }() 34 | } 35 | 36 | for w := 0; w < 10; w++ { 37 | go func() { 38 | for { 39 | key := rand.Intn(5) 40 | val := rand.Intn(100) 41 | mutex.Lock() 42 | state[key] = val 43 | mutex.Unlock() 44 | atomic.AddUint64(&writeOps, 1) 45 | time.Sleep(time.Millisecond) 46 | } 47 | }() 48 | } 49 | 50 | time.Sleep(time.Second) 51 | 52 | readOpsFinal := atomic.LoadUint64(&readOps) 53 | fmt.Println("readOps:", readOpsFinal) 54 | writeOpsFinal := atomic.LoadUint64(&writeOps) 55 | fmt.Println("writeOps:", writeOpsFinal) 56 | 57 | mutex.Lock() 58 | fmt.Println("state:", state) 59 | mutex.Unlock() 60 | } 61 | -------------------------------------------------------------------------------- /basic-example/39-stateful_goroutines/stateful_goroutines.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "sync/atomic" 7 | "time" 8 | ) 9 | 10 | type readOp struct { 11 | key int 12 | resp chan int 13 | } 14 | type writeOp struct { 15 | key int 16 | val int 17 | resp chan bool 18 | } 19 | 20 | func main() { 21 | 22 | var readOps uint64 23 | var writeOps uint64 24 | 25 | reads := make(chan readOp) 26 | writes := make(chan writeOp) 27 | 28 | go func() { 29 | var state = make(map[int]int) 30 | for { 31 | select { 32 | case read := <-reads: 33 | read.resp <- state[read.key] 34 | case write := <-writes: 35 | state[write.key] = write.val 36 | write.resp <- true 37 | } 38 | } 39 | }() 40 | 41 | for r := 0; r < 100; r++ { 42 | go func() { 43 | for { 44 | read := readOp{ 45 | key: rand.Intn(5), 46 | resp: make(chan int)} 47 | reads <- read 48 | <-read.resp 49 | atomic.AddUint64(&readOps, 1) 50 | time.Sleep(time.Millisecond) 51 | } 52 | }() 53 | } 54 | 55 | for w := 0; w < 10; w++ { 56 | go func() { 57 | for { 58 | write := writeOp{ 59 | key: rand.Intn(5), 60 | val: rand.Intn(100), 61 | resp: make(chan bool)} 62 | writes <- write 63 | <-write.resp 64 | atomic.AddUint64(&writeOps, 1) 65 | time.Sleep(time.Millisecond) 66 | } 67 | }() 68 | } 69 | 70 | time.Sleep(time.Second) 71 | 72 | readOpsFinal := atomic.LoadUint64(&readOps) 73 | fmt.Println("readOps:", readOpsFinal) 74 | writeOpsFinal := atomic.LoadUint64(&writeOps) 75 | fmt.Println("writeOps:", writeOpsFinal) 76 | } 77 | -------------------------------------------------------------------------------- /basic-example/40-sorting/sorting.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | ) 7 | 8 | func main() { 9 | strs := []string{"c", "a", "b"} 10 | sort.Strings(strs) 11 | fmt.Println(strs) 12 | 13 | nums := []int{22, 1, 4, 645, 3} 14 | sort.Ints(nums) 15 | fmt.Println(nums) 16 | 17 | fmt.Println(sort.IntsAreSorted(nums)) 18 | } 19 | -------------------------------------------------------------------------------- /basic-example/41-sorting_by_func/sorting_by_func.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | ) 7 | 8 | type byLength []string 9 | 10 | func (s byLength) Len() int { 11 | return len(s) 12 | } 13 | 14 | func (s byLength) Swap(i, j int) { 15 | s[i], s[j] = s[j], s[i] 16 | } 17 | 18 | func (s byLength) Less(i, j int) bool { 19 | return len(s[i]) < len(s[j]) 20 | } 21 | 22 | func main() { 23 | s := []string{"peach", "banana", "kiwi"} 24 | sort.Sort(byLength(s)) 25 | fmt.Println(s) 26 | } 27 | -------------------------------------------------------------------------------- /basic-example/42-panic/panic.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | panic("a problem") 5 | 6 | // _, err := os.Create("/tmp/file") 7 | // if err != nil { 8 | // panic(err) 9 | // } 10 | } 11 | -------------------------------------------------------------------------------- /basic-example/43-defer/defer.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | ) 7 | 8 | func createFile(file string) *os.File { 9 | fmt.Print("creating") 10 | f, err := os.Create(file) 11 | if err != nil { 12 | fmt.Print("create file error") 13 | os.Exit(0) 14 | } 15 | return f 16 | } 17 | 18 | func writeFile(f *os.File) { 19 | fmt.Print("writing") 20 | fmt.Fprintf(f, "data") 21 | } 22 | 23 | func closeFile(f *os.File) { 24 | fmt.Print("closing") 25 | f.Close() 26 | } 27 | 28 | func main() { 29 | file := "./tmp.txt" 30 | f := createFile(file) 31 | defer closeFile(f) 32 | writeFile(f) 33 | } 34 | -------------------------------------------------------------------------------- /basic-example/44-collections_funcs/collections_funcs.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | func Index(vs []string, t string) int { 9 | for i, v := range vs { 10 | if v == t { 11 | return i 12 | } 13 | } 14 | return -1 15 | } 16 | 17 | func Include(vs []string, t string) bool { 18 | return Index(vs, t) >= 0 19 | } 20 | 21 | func Any(vs []string, f func(string) bool) bool { 22 | for _, v := range vs { 23 | if f(v) { 24 | return true 25 | } 26 | } 27 | return false 28 | } 29 | 30 | func All(vs []string, f func(string) bool) bool { 31 | for _, v := range vs { 32 | if !f(v) { 33 | return false 34 | } 35 | } 36 | return true 37 | } 38 | 39 | func Filter(vs []string, f func(string) bool) []string { 40 | vsf := make([]string, 0) 41 | for _, v := range vs { 42 | if f(v) { 43 | vsf = append(vsf, v) 44 | } 45 | } 46 | return vsf 47 | } 48 | 49 | func Map(vs []string, f func(string) string) []string { 50 | vsm := make([]string, len(vs)) 51 | for i, v := range vs { 52 | vsm[i] = f(v) 53 | } 54 | return vsm 55 | } 56 | 57 | func main() { 58 | 59 | var strs = []string{"peach", "apple", "pear", "plum"} 60 | 61 | fmt.Println(Index(strs, "pear")) 62 | 63 | fmt.Println(Include(strs, "grape")) 64 | 65 | fmt.Println(Any(strs, func(v string) bool { 66 | return strings.HasPrefix(v, "p") 67 | })) 68 | 69 | fmt.Println(All(strs, func(v string) bool { 70 | return strings.HasPrefix(v, "p") 71 | })) 72 | 73 | fmt.Println(Filter(strs, func(v string) bool { 74 | return strings.Contains(v, "e") 75 | })) 76 | 77 | fmt.Println(Map(strs, strings.ToUpper)) 78 | 79 | } 80 | -------------------------------------------------------------------------------- /basic-example/45-string_funcs/string_funcs.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | s "strings" 6 | ) 7 | 8 | var p = fmt.Println 9 | 10 | func main() { 11 | 12 | p("Contains: ", s.Contains("test", "es")) 13 | p("Count: ", s.Count("test", "t")) 14 | p("HasPrefix: ", s.HasPrefix("test", "te")) 15 | p("HasSuffix: ", s.HasSuffix("test", "st")) 16 | p("Index: ", s.Index("test", "e")) 17 | p("Join: ", s.Join([]string{"a", "b"}, "-")) 18 | p("Repeat: ", s.Repeat("a", 5)) 19 | p("Replace: ", s.Replace("foo", "o", "0", -1)) 20 | p("Replace: ", s.Replace("foo", "o", "0", 1)) 21 | p("Split: ", s.Split("a-b-c-d-e", "-")) 22 | p("ToLower: ", s.ToLower("TEST")) 23 | p("ToUpper: ", s.ToUpper("test")) 24 | p() 25 | 26 | p("Len: ", len("hello")) 27 | p("Char:", "hello"[1]) 28 | } 29 | -------------------------------------------------------------------------------- /basic-example/46-string_format/46_string_format.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | ) 7 | 8 | type point struct { 9 | x, y int 10 | } 11 | 12 | func main() { 13 | 14 | p := point{1, 2} 15 | fmt.Printf("%v\n", p) 16 | 17 | fmt.Printf("%+v\n", p) 18 | 19 | fmt.Printf("%#v\n", p) 20 | 21 | fmt.Printf("%T\n", p) 22 | 23 | fmt.Printf("%t\n", true) 24 | 25 | fmt.Printf("%d\n", 123) 26 | 27 | fmt.Printf("%b\n", 14) 28 | 29 | fmt.Printf("%c\n", 33) 30 | 31 | fmt.Printf("%x\n", 456) 32 | 33 | fmt.Printf("%f\n", 78.9) 34 | 35 | fmt.Printf("%e\n", 123400000.0) 36 | fmt.Printf("%E\n", 123400000.0) 37 | 38 | fmt.Printf("%s\n", "\"string\"") 39 | 40 | fmt.Printf("%q\n", "\"string\"") 41 | 42 | fmt.Printf("%x\n", "hex this") 43 | 44 | fmt.Printf("%p\n", &p) 45 | 46 | fmt.Printf("|%6d|%6d|\n", 12, 345) 47 | 48 | fmt.Printf("|%6.2f|%6.2f|\n", 1.2, 3.45) 49 | 50 | fmt.Printf("|%-6.2f|%-6.2f|\n", 1.2, 3.45) 51 | 52 | fmt.Printf("|%6s|%6s|\n", "foo", "b") 53 | 54 | fmt.Printf("|%-6s|%-6s|\n", "foo", "b") 55 | 56 | s := fmt.Sprintf("a %s", "string") 57 | fmt.Println(s) 58 | 59 | fmt.Fprintf(os.Stderr, "an %s\n", "error") 60 | } 61 | -------------------------------------------------------------------------------- /basic-example/47-regular/regular.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "regexp" 7 | ) 8 | 9 | func main() { 10 | 11 | match, _ := regexp.MatchString("p([a-z]+)ch", "peach") 12 | fmt.Println(match) 13 | 14 | r, _ := regexp.Compile("p([a-z]+)ch") 15 | 16 | fmt.Println(r.MatchString("peach")) 17 | 18 | fmt.Println(r.FindString("peach punch")) 19 | 20 | fmt.Println(r.FindStringIndex("peach punch")) 21 | 22 | fmt.Println(r.FindStringSubmatch("peach punch")) 23 | 24 | fmt.Println(r.FindStringSubmatchIndex("peach punch")) 25 | 26 | fmt.Println(r.FindAllString("peach punch pinch", -1)) 27 | 28 | fmt.Println(r.FindAllStringSubmatchIndex( 29 | "peach punch pinch", -1)) 30 | 31 | fmt.Println(r.FindAllString("peach punch pinch", 2)) 32 | 33 | fmt.Println(r.Match([]byte("peach"))) 34 | 35 | r = regexp.MustCompile("p([a-z]+)ch") 36 | fmt.Println(r) 37 | 38 | fmt.Println(r.ReplaceAllString("a peach", "")) 39 | 40 | in := []byte("a peach") 41 | out := r.ReplaceAllFunc(in, bytes.ToUpper) 42 | fmt.Println(string(out)) 43 | } 44 | -------------------------------------------------------------------------------- /basic-example/48-type_assertion/type_assertion.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | foo(233) 7 | foo("666") 8 | } 9 | 10 | func foo(v interface{}) { 11 | if v1, ok1 := v.(string); ok1 { 12 | fmt.Println(v1) 13 | } else if v2, ok2 := v.(int); ok2 { 14 | fmt.Println(v2) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /basic-example/49-hmac/hmac.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/hmac" 5 | "crypto/sha256" 6 | "encoding/hex" 7 | "fmt" 8 | "time" 9 | ) 10 | 11 | func main() { 12 | timestamp := time.Now().Unix() 13 | secret := "this is secret" 14 | 15 | stringToSign := fmt.Sprintf("%v", timestamp) + "@" + secret 16 | 17 | h := hmac.New(sha256.New, []byte(secret)) 18 | h.Write([]byte(stringToSign)) 19 | signature := hex.EncodeToString(h.Sum(nil)) 20 | 21 | fmt.Println(signature) 22 | } 23 | -------------------------------------------------------------------------------- /basic-example/50-context/withcancel.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | ) 7 | 8 | func main() { 9 | // gen generates integers in a separate goroutine and 10 | // sends them to the returned channel. 11 | // The callers of gen need to cancel the context once 12 | // they are done consuming generated integers not to leak 13 | // the internal goroutine started by gen. 14 | gen := func(ctx context.Context) <-chan int { 15 | dst := make(chan int) 16 | n := 1 17 | go func() { 18 | for { 19 | select { 20 | case <-ctx.Done(): 21 | return // returning not to leak the goroutine 22 | case dst <- n: 23 | n++ 24 | } 25 | } 26 | }() 27 | return dst 28 | } 29 | 30 | ctx, cancel := context.WithCancel(context.Background()) 31 | defer cancel() // cancel when we are finished consuming integers 32 | 33 | for n := range gen(ctx) { 34 | fmt.Println(n) 35 | if n == 5 { 36 | break 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /basic-example/50-context/withdeadline.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "time" 7 | ) 8 | 9 | const shortDuration = 1 * time.Millisecond 10 | 11 | func main() { 12 | d := time.Now().Add(shortDuration) 13 | ctx, cancel := context.WithDeadline(context.Background(), d) 14 | 15 | // Even though ctx will be expired, it is good practice to call its 16 | // cancellation function in any case. Failure to do so may keep the 17 | // context and its parent alive longer than necessary. 18 | defer cancel() 19 | 20 | select { 21 | case <-time.After(1 * time.Second): 22 | fmt.Println("overslept") 23 | case <-ctx.Done(): 24 | fmt.Println(ctx.Err()) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /basic-example/50-context/withtimeout.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "time" 7 | ) 8 | 9 | const shortDuration = 1 * time.Millisecond 10 | 11 | func main() { 12 | // Pass a context with a timeout to tell a blocking function that it 13 | // should abandon its work after the timeout elapses. 14 | ctx, cancel := context.WithTimeout(context.Background(), shortDuration) 15 | defer cancel() 16 | 17 | select { 18 | case <-time.After(1 * time.Second): 19 | fmt.Println("overslept") 20 | case <-ctx.Done(): 21 | fmt.Println(ctx.Err()) // prints "context deadline exceeded" 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /basic-example/50-context/withvalue.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | ) 7 | 8 | func main() { 9 | type favContextKey string 10 | 11 | f := func(ctx context.Context, k favContextKey) { 12 | if v := ctx.Value(k); v != nil { 13 | fmt.Println("found value:", v) 14 | return 15 | } 16 | fmt.Println("key not found:", k) 17 | } 18 | 19 | k := favContextKey("language") 20 | ctx := context.WithValue(context.Background(), k, "Go") 21 | 22 | f(ctx, k) 23 | f(ctx, favContextKey("color")) 24 | 25 | } 26 | -------------------------------------------------------------------------------- /engine/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "reflect" 7 | "strings" 8 | "sync" 9 | ) 10 | 11 | type DataContext struct { 12 | lockVars sync.Mutex 13 | lockBase sync.Mutex 14 | base map[string]reflect.Value 15 | } 16 | 17 | func NewDataContext() *DataContext { 18 | dc := &DataContext{ 19 | base: make(map[string]reflect.Value), 20 | } 21 | return dc 22 | } 23 | 24 | func (dc *DataContext) Add(key string, obj interface{}) { 25 | dc.lockBase.Lock() 26 | defer dc.lockBase.Unlock() 27 | dc.base[key] = reflect.ValueOf(obj) 28 | } 29 | 30 | func (dc *DataContext) Del(keys ...string) { 31 | if len(keys) == 0 { 32 | return 33 | } 34 | dc.lockBase.Lock() 35 | defer dc.lockBase.Unlock() 36 | 37 | for _, key := range keys { 38 | delete(dc.base, key) 39 | } 40 | } 41 | 42 | func (dc *DataContext) Get(key string) (reflect.Value, error) { 43 | dc.lockBase.Lock() 44 | v, ok := dc.base[key] 45 | dc.lockBase.Unlock() 46 | if ok { 47 | return v, nil 48 | } else { 49 | return reflect.ValueOf(nil), errors.New(fmt.Sprintf("NOT FOUND key :%s ", key)) 50 | } 51 | } 52 | 53 | /** 54 | execute the injected functions: a(..) 55 | function execute supply multi return values, but simplify ,just return one value 56 | */ 57 | func (dc *DataContext) ExecFunc(funcName string, parameters []reflect.Value) (reflect.Value, error) { 58 | dc.lockBase.Lock() 59 | v, ok := dc.base[funcName] 60 | dc.lockBase.Unlock() 61 | 62 | if ok { 63 | args := ParamsTypeChange(v, parameters) 64 | res := v.Call(args) 65 | raw, e := GetRawTypeValue(res) 66 | if e != nil { 67 | return reflect.ValueOf(nil), e 68 | } 69 | return raw, nil 70 | } 71 | 72 | return reflect.ValueOf(nil), errors.New(fmt.Sprintf("NOT FOUND function \"%s(..)\"", funcName)) 73 | } 74 | 75 | const ( 76 | _int = 1 77 | _uint = 2 78 | _float = 3 79 | ) 80 | 81 | /* 82 | number type exchange 83 | */ 84 | func ParamsTypeChange(f reflect.Value, params []reflect.Value) []reflect.Value { 85 | tf := f.Type() 86 | if tf.Kind() == reflect.Ptr { 87 | tf = tf.Elem() 88 | } 89 | plen := tf.NumIn() 90 | for i := 0; i < plen; i++ { 91 | switch tf.In(i).Kind() { 92 | case reflect.Int: 93 | tag := getNumType(params[i]) 94 | if tag == _int { 95 | params[i] = reflect.ValueOf(int(params[i].Int())) 96 | } else if tag == _uint { 97 | params[i] = reflect.ValueOf(int(params[i].Uint())) 98 | } else { 99 | params[i] = reflect.ValueOf(int(params[i].Float())) 100 | } 101 | break 102 | case reflect.Int8: 103 | tag := getNumType(params[i]) 104 | if tag == _int { 105 | params[i] = reflect.ValueOf(int8(params[i].Int())) 106 | } else if tag == _uint { 107 | params[i] = reflect.ValueOf(int8(params[i].Uint())) 108 | } else { 109 | params[i] = reflect.ValueOf(int8(params[i].Float())) 110 | } 111 | break 112 | case reflect.Int16: 113 | tag := getNumType(params[i]) 114 | if tag == _int { 115 | params[i] = reflect.ValueOf(int16(params[i].Int())) 116 | } else if tag == _uint { 117 | params[i] = reflect.ValueOf(int16(params[i].Uint())) 118 | } else { 119 | params[i] = reflect.ValueOf(int16(params[i].Float())) 120 | } 121 | break 122 | case reflect.Int32: 123 | tag := getNumType(params[i]) 124 | if tag == _int { 125 | params[i] = reflect.ValueOf(int32(params[i].Int())) 126 | } else if tag == _uint { 127 | params[i] = reflect.ValueOf(int32(params[i].Uint())) 128 | } else { 129 | params[i] = reflect.ValueOf(int32(params[i].Float())) 130 | } 131 | break 132 | case reflect.Int64: 133 | tag := getNumType(params[i]) 134 | if tag == _int { 135 | params[i] = reflect.ValueOf(params[i].Int()) 136 | } else if tag == _uint { 137 | params[i] = reflect.ValueOf(int64(params[i].Uint())) 138 | } else { 139 | params[i] = reflect.ValueOf(int64(params[i].Float())) 140 | } 141 | break 142 | case reflect.Uint: 143 | tag := getNumType(params[i]) 144 | if tag == _int { 145 | params[i] = reflect.ValueOf(uint(params[i].Int())) 146 | } else if tag == _uint { 147 | params[i] = reflect.ValueOf(uint(params[i].Uint())) 148 | } else { 149 | params[i] = reflect.ValueOf(uint(params[i].Float())) 150 | } 151 | break 152 | case reflect.Uint8: 153 | tag := getNumType(params[i]) 154 | if tag == _int { 155 | params[i] = reflect.ValueOf(uint8(params[i].Int())) 156 | } else if tag == _uint { 157 | params[i] = reflect.ValueOf(uint8(params[i].Uint())) 158 | } else { 159 | params[i] = reflect.ValueOf(uint8(params[i].Float())) 160 | } 161 | break 162 | case reflect.Uint16: 163 | tag := getNumType(params[i]) 164 | if tag == _int { 165 | params[i] = reflect.ValueOf(uint16(params[i].Int())) 166 | } else if tag == _uint { 167 | params[i] = reflect.ValueOf(uint16(params[i].Uint())) 168 | } else { 169 | params[i] = reflect.ValueOf(uint16(params[i].Float())) 170 | } 171 | break 172 | case reflect.Uint32: 173 | tag := getNumType(params[i]) 174 | if tag == _int { 175 | params[i] = reflect.ValueOf(uint32(params[i].Int())) 176 | } else if tag == _uint { 177 | params[i] = reflect.ValueOf(uint32(params[i].Uint())) 178 | } else { 179 | params[i] = reflect.ValueOf(uint32(params[i].Float())) 180 | } 181 | break 182 | case reflect.Uint64: 183 | tag := getNumType(params[i]) 184 | if tag == _int { 185 | params[i] = reflect.ValueOf(uint64(params[i].Int())) 186 | } else if tag == _uint { 187 | params[i] = reflect.ValueOf(params[i].Uint()) 188 | } else { 189 | params[i] = reflect.ValueOf(uint64(params[i].Float())) 190 | } 191 | break 192 | case reflect.Float32: 193 | tag := getNumType(params[i]) 194 | if tag == _int { 195 | params[i] = reflect.ValueOf(float32(params[i].Int())) 196 | } else if tag == _uint { 197 | params[i] = reflect.ValueOf(float32(params[i].Uint())) 198 | } else { 199 | params[i] = reflect.ValueOf(float32(params[i].Float())) 200 | } 201 | break 202 | case reflect.Float64: 203 | tag := getNumType(params[i]) 204 | if tag == _int { 205 | params[i] = reflect.ValueOf(float64(params[i].Int())) 206 | } else if tag == _uint { 207 | params[i] = reflect.ValueOf(float64(params[i].Uint())) 208 | } else { 209 | params[i] = reflect.ValueOf(params[i].Float()) 210 | } 211 | break 212 | case reflect.Ptr: 213 | break 214 | case reflect.Interface: 215 | if !reflect.ValueOf(params[i]).IsValid() { 216 | params[i] = reflect.New(tf.In(i)) 217 | } 218 | default: 219 | continue 220 | } 221 | } 222 | return params 223 | } 224 | 225 | func getNumType(param reflect.Value) int { 226 | ts := param.Kind().String() 227 | if strings.HasPrefix(ts, "int") { 228 | return _int 229 | } 230 | 231 | if strings.HasPrefix(ts, "uint") { 232 | return _uint 233 | } 234 | 235 | if strings.HasPrefix(ts, "float") { 236 | return _float 237 | } 238 | 239 | panic(fmt.Sprintf("it is not number type, type is %s !", ts)) 240 | } 241 | 242 | /** 243 | if want to support multi return ,change this method implements 244 | */ 245 | func GetRawTypeValue(rs []reflect.Value) (reflect.Value, error) { 246 | if len(rs) == 0 { 247 | return reflect.ValueOf(nil), nil 248 | } else { 249 | return rs[0], nil 250 | } 251 | } 252 | 253 | type User struct { 254 | Name string `json:"name"` 255 | Age int `json:"age"` 256 | } 257 | 258 | func PrintHello(user User) { 259 | fmt.Println(user.Name) 260 | fmt.Println(user.Age) 261 | } 262 | 263 | func main() { 264 | // 假设从数据库中获取函数名 265 | functionName := "PrintHello" 266 | 267 | // 使用反射获取函数 268 | functionValue := reflect.ValueOf(nil).MethodByName(functionName) 269 | if !functionValue.IsValid() { 270 | fmt.Printf("Function '%s' not found\n", functionName) 271 | return 272 | } 273 | 274 | // 创建函数参数 275 | user := User{ 276 | Name: "John Doe", 277 | Age: 30, 278 | } 279 | args := []reflect.Value{reflect.ValueOf(user)} 280 | 281 | // 动态调用函数 282 | functionValue.Call(args) 283 | 284 | // dc := NewDataContext() 285 | // dc.Add("hello", PrintHello) 286 | 287 | // params := map[string]interface{}{ 288 | // "name": "zhangsan", 289 | // "age": 11, 290 | // } 291 | 292 | // funcName := "hello" 293 | 294 | // userType := reflect.TypeOf(User{}) 295 | // userValue := reflect.New(userType).Elem() 296 | // for i := 0; i < userType.NumField(); i++ { 297 | // field := userType.Field(i) 298 | // jsonTag := field.Tag.Get("json") 299 | // if val, ok := params[jsonTag]; ok { 300 | // fieldValue := userValue.Field(i) 301 | // fieldType := fieldValue.Type() 302 | // value := reflect.ValueOf(val) 303 | 304 | // if value.Type().ConvertibleTo(fieldType) { 305 | // fieldValue.Set(value.Convert(fieldType)) 306 | // } 307 | // } 308 | // } 309 | 310 | // dc.ExecFunc(funcName, []reflect.Value{userValue}) 311 | } 312 | -------------------------------------------------------------------------------- /gin-example/go.mod: -------------------------------------------------------------------------------- 1 | module gin-example 2 | 3 | go 1.16 4 | 5 | require github.com/gin-gonic/gin v1.7.4 6 | -------------------------------------------------------------------------------- /gin-example/go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 2 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 3 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 4 | github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= 5 | github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= 6 | github.com/gin-gonic/gin v1.7.4 h1:QmUZXrvJ9qZ3GfWvQ+2wnW/1ePrTEJqPKMYEU3lD/DM= 7 | github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= 8 | github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= 9 | github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= 10 | github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= 11 | github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= 12 | github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= 13 | github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= 14 | github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= 15 | github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= 16 | github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= 17 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 18 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 19 | github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= 20 | github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 21 | github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= 22 | github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= 23 | github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= 24 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= 25 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= 26 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 27 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= 28 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 29 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 30 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 31 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 32 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 33 | github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= 34 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 35 | github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= 36 | github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= 37 | github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= 38 | github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= 39 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 40 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= 41 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 42 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 43 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 44 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 45 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg= 46 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 47 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 48 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 49 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 50 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 51 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 52 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 53 | gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= 54 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 55 | -------------------------------------------------------------------------------- /gin-example/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | func main() { 8 | r := gin.Default() 9 | r.GET("/ping", func(c *gin.Context) { 10 | c.JSON(200, gin.H{ 11 | "message": "pong", 12 | }) 13 | }) 14 | r.Run() // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080") 15 | } 16 | -------------------------------------------------------------------------------- /grpc-example/deadline/client/go.mod: -------------------------------------------------------------------------------- 1 | module client 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/golang/protobuf v1.5.2 7 | google.golang.org/grpc v1.41.0 8 | ) 9 | -------------------------------------------------------------------------------- /grpc-example/deadline/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "client/proto" 5 | "context" 6 | "fmt" 7 | "log" 8 | "time" 9 | 10 | "google.golang.org/grpc" 11 | "google.golang.org/grpc/codes" 12 | "google.golang.org/grpc/status" 13 | ) 14 | 15 | func main() { 16 | // 简单调用 17 | conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure()) 18 | defer conn.Close() 19 | 20 | ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(time.Duration(3*time.Second))) 21 | defer cancel() 22 | 23 | client := proto.NewGreeterClient(conn) 24 | // 简单调用 25 | reply, err := client.SayHello(ctx, &proto.HelloRequest{Name: "zzz"}) 26 | if err != nil { 27 | statusErr, ok := status.FromError(err) 28 | if ok { 29 | if statusErr.Code() == codes.DeadlineExceeded { 30 | log.Fatalln("client.SayHello err: deadline") 31 | } 32 | } 33 | 34 | log.Fatalf("client.SayHello err: %v", err) 35 | } 36 | fmt.Println(reply.Message) 37 | } 38 | -------------------------------------------------------------------------------- /grpc-example/deadline/client/proto/helloworld.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // source: helloworld.proto 3 | 4 | package proto 5 | 6 | import ( 7 | context "context" 8 | fmt "fmt" 9 | proto "github.com/golang/protobuf/proto" 10 | grpc "google.golang.org/grpc" 11 | codes "google.golang.org/grpc/codes" 12 | status "google.golang.org/grpc/status" 13 | math "math" 14 | ) 15 | 16 | // Reference imports to suppress errors if they are not otherwise used. 17 | var _ = proto.Marshal 18 | var _ = fmt.Errorf 19 | var _ = math.Inf 20 | 21 | // This is a compile-time assertion to ensure that this generated file 22 | // is compatible with the proto package it is being compiled against. 23 | // A compilation error at this line likely means your copy of the 24 | // proto package needs to be updated. 25 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 26 | 27 | // The request message containing the user's name. 28 | type HelloRequest struct { 29 | Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` 30 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 31 | XXX_unrecognized []byte `json:"-"` 32 | XXX_sizecache int32 `json:"-"` 33 | } 34 | 35 | func (m *HelloRequest) Reset() { *m = HelloRequest{} } 36 | func (m *HelloRequest) String() string { return proto.CompactTextString(m) } 37 | func (*HelloRequest) ProtoMessage() {} 38 | func (*HelloRequest) Descriptor() ([]byte, []int) { 39 | return fileDescriptor_17b8c58d586b62f2, []int{0} 40 | } 41 | 42 | func (m *HelloRequest) XXX_Unmarshal(b []byte) error { 43 | return xxx_messageInfo_HelloRequest.Unmarshal(m, b) 44 | } 45 | func (m *HelloRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 46 | return xxx_messageInfo_HelloRequest.Marshal(b, m, deterministic) 47 | } 48 | func (m *HelloRequest) XXX_Merge(src proto.Message) { 49 | xxx_messageInfo_HelloRequest.Merge(m, src) 50 | } 51 | func (m *HelloRequest) XXX_Size() int { 52 | return xxx_messageInfo_HelloRequest.Size(m) 53 | } 54 | func (m *HelloRequest) XXX_DiscardUnknown() { 55 | xxx_messageInfo_HelloRequest.DiscardUnknown(m) 56 | } 57 | 58 | var xxx_messageInfo_HelloRequest proto.InternalMessageInfo 59 | 60 | func (m *HelloRequest) GetName() string { 61 | if m != nil { 62 | return m.Name 63 | } 64 | return "" 65 | } 66 | 67 | // The response message containing the greetings 68 | type HelloReply struct { 69 | Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` 70 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 71 | XXX_unrecognized []byte `json:"-"` 72 | XXX_sizecache int32 `json:"-"` 73 | } 74 | 75 | func (m *HelloReply) Reset() { *m = HelloReply{} } 76 | func (m *HelloReply) String() string { return proto.CompactTextString(m) } 77 | func (*HelloReply) ProtoMessage() {} 78 | func (*HelloReply) Descriptor() ([]byte, []int) { 79 | return fileDescriptor_17b8c58d586b62f2, []int{1} 80 | } 81 | 82 | func (m *HelloReply) XXX_Unmarshal(b []byte) error { 83 | return xxx_messageInfo_HelloReply.Unmarshal(m, b) 84 | } 85 | func (m *HelloReply) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 86 | return xxx_messageInfo_HelloReply.Marshal(b, m, deterministic) 87 | } 88 | func (m *HelloReply) XXX_Merge(src proto.Message) { 89 | xxx_messageInfo_HelloReply.Merge(m, src) 90 | } 91 | func (m *HelloReply) XXX_Size() int { 92 | return xxx_messageInfo_HelloReply.Size(m) 93 | } 94 | func (m *HelloReply) XXX_DiscardUnknown() { 95 | xxx_messageInfo_HelloReply.DiscardUnknown(m) 96 | } 97 | 98 | var xxx_messageInfo_HelloReply proto.InternalMessageInfo 99 | 100 | func (m *HelloReply) GetMessage() string { 101 | if m != nil { 102 | return m.Message 103 | } 104 | return "" 105 | } 106 | 107 | func init() { 108 | proto.RegisterType((*HelloRequest)(nil), "proto.HelloRequest") 109 | proto.RegisterType((*HelloReply)(nil), "proto.HelloReply") 110 | } 111 | 112 | func init() { proto.RegisterFile("helloworld.proto", fileDescriptor_17b8c58d586b62f2) } 113 | 114 | var fileDescriptor_17b8c58d586b62f2 = []byte{ 115 | // 140 bytes of a gzipped FileDescriptorProto 116 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xc8, 0x48, 0xcd, 0xc9, 117 | 0xc9, 0x2f, 0xcf, 0x2f, 0xca, 0x49, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x05, 0x53, 118 | 0x4a, 0x4a, 0x5c, 0x3c, 0x1e, 0x20, 0xa9, 0xa0, 0xd4, 0xc2, 0xd2, 0xd4, 0xe2, 0x12, 0x21, 0x21, 119 | 0x2e, 0x96, 0xbc, 0xc4, 0xdc, 0x54, 0x09, 0x46, 0x05, 0x46, 0x0d, 0xce, 0x20, 0x30, 0x5b, 0x49, 120 | 0x8d, 0x8b, 0x0b, 0xaa, 0xa6, 0x20, 0xa7, 0x52, 0x48, 0x82, 0x8b, 0x3d, 0x37, 0xb5, 0xb8, 0x38, 121 | 0x31, 0x1d, 0xa6, 0x08, 0xc6, 0x35, 0xb2, 0xe7, 0x62, 0x77, 0x2f, 0x4a, 0x4d, 0x2d, 0x49, 0x2d, 122 | 0x12, 0x32, 0xe1, 0xe2, 0x08, 0x4e, 0xac, 0x04, 0xeb, 0x12, 0x12, 0x86, 0xd8, 0xa8, 0x87, 0x6c, 123 | 0x8f, 0x94, 0x20, 0xaa, 0x60, 0x41, 0x4e, 0xa5, 0x12, 0x43, 0x12, 0x1b, 0x58, 0xcc, 0x18, 0x10, 124 | 0x00, 0x00, 0xff, 0xff, 0x28, 0x05, 0x7a, 0x0b, 0xae, 0x00, 0x00, 0x00, 125 | } 126 | 127 | // Reference imports to suppress errors if they are not otherwise used. 128 | var _ context.Context 129 | var _ grpc.ClientConn 130 | 131 | // This is a compile-time assertion to ensure that this generated file 132 | // is compatible with the grpc package it is being compiled against. 133 | const _ = grpc.SupportPackageIsVersion4 134 | 135 | // GreeterClient is the client API for Greeter service. 136 | // 137 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. 138 | type GreeterClient interface { 139 | // Sends a greeting 140 | SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) 141 | } 142 | 143 | type greeterClient struct { 144 | cc *grpc.ClientConn 145 | } 146 | 147 | func NewGreeterClient(cc *grpc.ClientConn) GreeterClient { 148 | return &greeterClient{cc} 149 | } 150 | 151 | func (c *greeterClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) { 152 | out := new(HelloReply) 153 | err := c.cc.Invoke(ctx, "/proto.Greeter/SayHello", in, out, opts...) 154 | if err != nil { 155 | return nil, err 156 | } 157 | return out, nil 158 | } 159 | 160 | // GreeterServer is the server API for Greeter service. 161 | type GreeterServer interface { 162 | // Sends a greeting 163 | SayHello(context.Context, *HelloRequest) (*HelloReply, error) 164 | } 165 | 166 | // UnimplementedGreeterServer can be embedded to have forward compatible implementations. 167 | type UnimplementedGreeterServer struct { 168 | } 169 | 170 | func (*UnimplementedGreeterServer) SayHello(ctx context.Context, req *HelloRequest) (*HelloReply, error) { 171 | return nil, status.Errorf(codes.Unimplemented, "method SayHello not implemented") 172 | } 173 | 174 | func RegisterGreeterServer(s *grpc.Server, srv GreeterServer) { 175 | s.RegisterService(&_Greeter_serviceDesc, srv) 176 | } 177 | 178 | func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 179 | in := new(HelloRequest) 180 | if err := dec(in); err != nil { 181 | return nil, err 182 | } 183 | if interceptor == nil { 184 | return srv.(GreeterServer).SayHello(ctx, in) 185 | } 186 | info := &grpc.UnaryServerInfo{ 187 | Server: srv, 188 | FullMethod: "/proto.Greeter/SayHello", 189 | } 190 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 191 | return srv.(GreeterServer).SayHello(ctx, req.(*HelloRequest)) 192 | } 193 | return interceptor(ctx, in, info, handler) 194 | } 195 | 196 | var _Greeter_serviceDesc = grpc.ServiceDesc{ 197 | ServiceName: "proto.Greeter", 198 | HandlerType: (*GreeterServer)(nil), 199 | Methods: []grpc.MethodDesc{ 200 | { 201 | MethodName: "SayHello", 202 | Handler: _Greeter_SayHello_Handler, 203 | }, 204 | }, 205 | Streams: []grpc.StreamDesc{}, 206 | Metadata: "helloworld.proto", 207 | } 208 | -------------------------------------------------------------------------------- /grpc-example/deadline/server/go.mod: -------------------------------------------------------------------------------- 1 | module server 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/golang/protobuf v1.5.2 7 | google.golang.org/grpc v1.41.0 8 | ) 9 | -------------------------------------------------------------------------------- /grpc-example/deadline/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "log" 7 | "net" 8 | "runtime" 9 | "server/proto" 10 | "time" 11 | 12 | "google.golang.org/grpc" 13 | "google.golang.org/grpc/codes" 14 | "google.golang.org/grpc/reflection" 15 | "google.golang.org/grpc/status" 16 | ) 17 | 18 | type greeter struct { 19 | } 20 | 21 | func (*greeter) SayHello(ctx context.Context, req *proto.HelloRequest) (*proto.HelloReply, error) { 22 | data := make(chan *proto.HelloReply, 1) 23 | go handle(ctx, req, data) 24 | select { 25 | case res := <-data: 26 | return res, nil 27 | case <-ctx.Done(): 28 | return nil, status.Errorf(codes.Canceled, "Client cancelled, abandoning.") 29 | } 30 | } 31 | 32 | func handle(ctx context.Context, req *proto.HelloRequest, data chan<- *proto.HelloReply) { 33 | select { 34 | case <-ctx.Done(): 35 | log.Println(ctx.Err()) 36 | runtime.Goexit() //超时后退出该Go协程 37 | case <-time.After(4 * time.Second): // 模拟耗时操作 38 | res := proto.HelloReply{ 39 | Message: "hello " + req.Name, 40 | } 41 | // //修改数据库前进行超时判断 42 | // if ctx.Err() == context.Canceled{ 43 | // ... 44 | // //如果已经超时,则退出 45 | // } 46 | data <- &res 47 | } 48 | } 49 | 50 | func main() { 51 | lis, err := net.Listen("tcp", ":50051") 52 | if err != nil { 53 | log.Fatalf("failed to listen: %v", err) 54 | } 55 | 56 | // 简单调用 57 | server := grpc.NewServer() 58 | // 注册 grpcurl 所需的 reflection 服务 59 | reflection.Register(server) 60 | // 注册业务服务 61 | proto.RegisterGreeterServer(server, &greeter{}) 62 | 63 | fmt.Println("grpc server start ...") 64 | if err := server.Serve(lis); err != nil { 65 | log.Fatalf("failed to serve: %v", err) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /grpc-example/deadline/server/proto/gen_proto.sh: -------------------------------------------------------------------------------- 1 | 2 | protoc --go_out=plugins=grpc:. *.proto 3 | -------------------------------------------------------------------------------- /grpc-example/deadline/server/proto/helloworld.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // source: helloworld.proto 3 | 4 | package proto 5 | 6 | import ( 7 | context "context" 8 | fmt "fmt" 9 | proto "github.com/golang/protobuf/proto" 10 | grpc "google.golang.org/grpc" 11 | codes "google.golang.org/grpc/codes" 12 | status "google.golang.org/grpc/status" 13 | math "math" 14 | ) 15 | 16 | // Reference imports to suppress errors if they are not otherwise used. 17 | var _ = proto.Marshal 18 | var _ = fmt.Errorf 19 | var _ = math.Inf 20 | 21 | // This is a compile-time assertion to ensure that this generated file 22 | // is compatible with the proto package it is being compiled against. 23 | // A compilation error at this line likely means your copy of the 24 | // proto package needs to be updated. 25 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 26 | 27 | // The request message containing the user's name. 28 | type HelloRequest struct { 29 | Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` 30 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 31 | XXX_unrecognized []byte `json:"-"` 32 | XXX_sizecache int32 `json:"-"` 33 | } 34 | 35 | func (m *HelloRequest) Reset() { *m = HelloRequest{} } 36 | func (m *HelloRequest) String() string { return proto.CompactTextString(m) } 37 | func (*HelloRequest) ProtoMessage() {} 38 | func (*HelloRequest) Descriptor() ([]byte, []int) { 39 | return fileDescriptor_17b8c58d586b62f2, []int{0} 40 | } 41 | 42 | func (m *HelloRequest) XXX_Unmarshal(b []byte) error { 43 | return xxx_messageInfo_HelloRequest.Unmarshal(m, b) 44 | } 45 | func (m *HelloRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 46 | return xxx_messageInfo_HelloRequest.Marshal(b, m, deterministic) 47 | } 48 | func (m *HelloRequest) XXX_Merge(src proto.Message) { 49 | xxx_messageInfo_HelloRequest.Merge(m, src) 50 | } 51 | func (m *HelloRequest) XXX_Size() int { 52 | return xxx_messageInfo_HelloRequest.Size(m) 53 | } 54 | func (m *HelloRequest) XXX_DiscardUnknown() { 55 | xxx_messageInfo_HelloRequest.DiscardUnknown(m) 56 | } 57 | 58 | var xxx_messageInfo_HelloRequest proto.InternalMessageInfo 59 | 60 | func (m *HelloRequest) GetName() string { 61 | if m != nil { 62 | return m.Name 63 | } 64 | return "" 65 | } 66 | 67 | // The response message containing the greetings 68 | type HelloReply struct { 69 | Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` 70 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 71 | XXX_unrecognized []byte `json:"-"` 72 | XXX_sizecache int32 `json:"-"` 73 | } 74 | 75 | func (m *HelloReply) Reset() { *m = HelloReply{} } 76 | func (m *HelloReply) String() string { return proto.CompactTextString(m) } 77 | func (*HelloReply) ProtoMessage() {} 78 | func (*HelloReply) Descriptor() ([]byte, []int) { 79 | return fileDescriptor_17b8c58d586b62f2, []int{1} 80 | } 81 | 82 | func (m *HelloReply) XXX_Unmarshal(b []byte) error { 83 | return xxx_messageInfo_HelloReply.Unmarshal(m, b) 84 | } 85 | func (m *HelloReply) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 86 | return xxx_messageInfo_HelloReply.Marshal(b, m, deterministic) 87 | } 88 | func (m *HelloReply) XXX_Merge(src proto.Message) { 89 | xxx_messageInfo_HelloReply.Merge(m, src) 90 | } 91 | func (m *HelloReply) XXX_Size() int { 92 | return xxx_messageInfo_HelloReply.Size(m) 93 | } 94 | func (m *HelloReply) XXX_DiscardUnknown() { 95 | xxx_messageInfo_HelloReply.DiscardUnknown(m) 96 | } 97 | 98 | var xxx_messageInfo_HelloReply proto.InternalMessageInfo 99 | 100 | func (m *HelloReply) GetMessage() string { 101 | if m != nil { 102 | return m.Message 103 | } 104 | return "" 105 | } 106 | 107 | func init() { 108 | proto.RegisterType((*HelloRequest)(nil), "proto.HelloRequest") 109 | proto.RegisterType((*HelloReply)(nil), "proto.HelloReply") 110 | } 111 | 112 | func init() { proto.RegisterFile("helloworld.proto", fileDescriptor_17b8c58d586b62f2) } 113 | 114 | var fileDescriptor_17b8c58d586b62f2 = []byte{ 115 | // 140 bytes of a gzipped FileDescriptorProto 116 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xc8, 0x48, 0xcd, 0xc9, 117 | 0xc9, 0x2f, 0xcf, 0x2f, 0xca, 0x49, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x05, 0x53, 118 | 0x4a, 0x4a, 0x5c, 0x3c, 0x1e, 0x20, 0xa9, 0xa0, 0xd4, 0xc2, 0xd2, 0xd4, 0xe2, 0x12, 0x21, 0x21, 119 | 0x2e, 0x96, 0xbc, 0xc4, 0xdc, 0x54, 0x09, 0x46, 0x05, 0x46, 0x0d, 0xce, 0x20, 0x30, 0x5b, 0x49, 120 | 0x8d, 0x8b, 0x0b, 0xaa, 0xa6, 0x20, 0xa7, 0x52, 0x48, 0x82, 0x8b, 0x3d, 0x37, 0xb5, 0xb8, 0x38, 121 | 0x31, 0x1d, 0xa6, 0x08, 0xc6, 0x35, 0xb2, 0xe7, 0x62, 0x77, 0x2f, 0x4a, 0x4d, 0x2d, 0x49, 0x2d, 122 | 0x12, 0x32, 0xe1, 0xe2, 0x08, 0x4e, 0xac, 0x04, 0xeb, 0x12, 0x12, 0x86, 0xd8, 0xa8, 0x87, 0x6c, 123 | 0x8f, 0x94, 0x20, 0xaa, 0x60, 0x41, 0x4e, 0xa5, 0x12, 0x43, 0x12, 0x1b, 0x58, 0xcc, 0x18, 0x10, 124 | 0x00, 0x00, 0xff, 0xff, 0x28, 0x05, 0x7a, 0x0b, 0xae, 0x00, 0x00, 0x00, 125 | } 126 | 127 | // Reference imports to suppress errors if they are not otherwise used. 128 | var _ context.Context 129 | var _ grpc.ClientConn 130 | 131 | // This is a compile-time assertion to ensure that this generated file 132 | // is compatible with the grpc package it is being compiled against. 133 | const _ = grpc.SupportPackageIsVersion4 134 | 135 | // GreeterClient is the client API for Greeter service. 136 | // 137 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. 138 | type GreeterClient interface { 139 | // Sends a greeting 140 | SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) 141 | } 142 | 143 | type greeterClient struct { 144 | cc *grpc.ClientConn 145 | } 146 | 147 | func NewGreeterClient(cc *grpc.ClientConn) GreeterClient { 148 | return &greeterClient{cc} 149 | } 150 | 151 | func (c *greeterClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) { 152 | out := new(HelloReply) 153 | err := c.cc.Invoke(ctx, "/proto.Greeter/SayHello", in, out, opts...) 154 | if err != nil { 155 | return nil, err 156 | } 157 | return out, nil 158 | } 159 | 160 | // GreeterServer is the server API for Greeter service. 161 | type GreeterServer interface { 162 | // Sends a greeting 163 | SayHello(context.Context, *HelloRequest) (*HelloReply, error) 164 | } 165 | 166 | // UnimplementedGreeterServer can be embedded to have forward compatible implementations. 167 | type UnimplementedGreeterServer struct { 168 | } 169 | 170 | func (*UnimplementedGreeterServer) SayHello(ctx context.Context, req *HelloRequest) (*HelloReply, error) { 171 | return nil, status.Errorf(codes.Unimplemented, "method SayHello not implemented") 172 | } 173 | 174 | func RegisterGreeterServer(s *grpc.Server, srv GreeterServer) { 175 | s.RegisterService(&_Greeter_serviceDesc, srv) 176 | } 177 | 178 | func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 179 | in := new(HelloRequest) 180 | if err := dec(in); err != nil { 181 | return nil, err 182 | } 183 | if interceptor == nil { 184 | return srv.(GreeterServer).SayHello(ctx, in) 185 | } 186 | info := &grpc.UnaryServerInfo{ 187 | Server: srv, 188 | FullMethod: "/proto.Greeter/SayHello", 189 | } 190 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 191 | return srv.(GreeterServer).SayHello(ctx, req.(*HelloRequest)) 192 | } 193 | return interceptor(ctx, in, info, handler) 194 | } 195 | 196 | var _Greeter_serviceDesc = grpc.ServiceDesc{ 197 | ServiceName: "proto.Greeter", 198 | HandlerType: (*GreeterServer)(nil), 199 | Methods: []grpc.MethodDesc{ 200 | { 201 | MethodName: "SayHello", 202 | Handler: _Greeter_SayHello_Handler, 203 | }, 204 | }, 205 | Streams: []grpc.StreamDesc{}, 206 | Metadata: "helloworld.proto", 207 | } 208 | -------------------------------------------------------------------------------- /grpc-example/deadline/server/proto/helloworld.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package proto; 4 | 5 | // The greeting service definition. 6 | service Greeter { 7 | // Sends a greeting 8 | rpc SayHello (HelloRequest) returns (HelloReply) {} 9 | } 10 | 11 | // The request message containing the user's name. 12 | message HelloRequest { 13 | string name = 1; 14 | } 15 | 16 | // The response message containing the greetings 17 | message HelloReply { 18 | string message = 1; 19 | } -------------------------------------------------------------------------------- /grpc-example/grpc-client/cert/ca.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEowIBAAKCAQEA7wI5159l+0An8PmATgPe0vgGEn48b8nkYo1pvN5QZ+PtxDQS 3 | zl5tM7TX03cHAfG86WUm6CA7mY3mrZnv6B5GMunzu8dwyFuW6yKSqAyV4vgaPHIm 4 | S4rsOGCp54Py3Xy5LSggonbuHxFd37mlEcCxMDkrwSK+GDNmS04DGFJQaoaHqym7 5 | 5mq32CEfsc8GiQgLyW/Xgt+domaO6YG4h9RfgbgHi/JifiCSi+rN5BPKerBPjVkb 6 | 5idtjXlWYayPFeTlQ2Xf4/oBq5+rReG0OQ2890Dz8aKnWFtxG7wSBX19E206yJ4d 7 | kmJf4KDktDujWNU0sYloy3Af40guZgcidDnPXQIDAQABAoIBAFsgMyOFz6Eizdev 8 | mP6ltSAkllQYszw/8oasugLblDZ4DaA/5meuUt5i9eLXP+G65DbsbRAVsgOSub+4 9 | sGKEoGkrD9WpbdPGL91ImjfeTItz4rTnJLiqp/O6zyzI/yD5O7T+1qp6w8Euoub4 10 | 5fnFyQjE02zYrTeW6UqO3Nk6ERT7pzhVl978IZOqbBSdjCizzWkO7T5B2P8jbE4D 11 | x3cVmuXbTT1an7hgLFVHrXvJdbf23gP8cdN8BLMzRbPBGzQFv3pJzAB2OgPXQJiX 12 | 5PxxW11DrZLMXRXTfLLLJ/cd96XIPJ5dGqHvZZ1ZUCK2jrEcqD64OPmGhy4+N533 13 | iuKJHXUCgYEA/CkgAwveuPkCFR0VGl491U9KPU5Ke093WMKwbl9UY+07RtX0u4RB 14 | dv1JvJg1SguWY+r5kFMsX+190g/Nn7XwNgHoMdqT/SrlqGLp4CWi+za9ZYB03O8s 15 | IMZxMQMmCjWJUiL7Tf2xVpe2t9FPp8WH/oauyBKjQkSri5vC5Hl3YlcCgYEA8qXW 16 | SdbzYrwfi8OPvA1ympXtwyIzlfFQCRvSzRMLpbBPw7n/hsEni4tPQDR4KosGJazx 17 | El9lpMrhRPPCXHx6stdglINQyM14u9t5Ra7N7GBfDdE//NDh1VCM5v1Xsm5sGyZ7 18 | 621eo0ET64qcN/w4bi9bb2nn9RVu3xebXrEq02sCgYEAyPfd04+6SqHqzvkGwKUr 19 | kr5G5OVo5y5GaC+CffTsRVflTmdnTavyoOrtwaltjz389lVn4Wbojuuww6Jkt01B 20 | zUlnzZPvLm7p6nIrA8H7S0wtVqAyg4L7IIQH4pAn2Ssh7pyCvX3bwK/ZqFbhrUz5 21 | PhoJYtu30jD4p6PUiFNmmrECgYBXKcdeYv6u+xEB7dAWJ2aBrVXpgMGzHSo4+2uw 22 | CyVl8X3Vu1zVFVGVSQfA8pgwABzHL+axSN+EYPSnBkFNY9HXqJKjBsDgQR8brG1V 23 | 4MNMJBpBJmer84UMUZEr8Nmt2QiwgBSHr5QNZPU46WPQoKPMwOpBjXOrkHVxYlOH 24 | onDV3QKBgEcXeMe0P7TyB4MyVW6PyM88S3MCKEmQaeYnVLNHiVI9XZFKtMyrRByq 25 | HJjD/ZG/+kNvnmwjJqubS/zR4oMKPJouyuc+FtfbwOapN8SpX3IObgTCX1GazET4 26 | /CnOIhBHy/UsRp6/rir28ijJs4Il3Qqw7dVi4hxxxYDOF9NnjDjm 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /grpc-example/grpc-client/cert/ca.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICuDCCAaACCQCZFaleThXYnDANBgkqhkiG9w0BAQsFADAeMRwwGgYDVQQDDBNl 3 | eGFtcGxlLmdycGNkZXYuY29tMB4XDTIxMTAxMjAxMzU0MloXDTM1MDYyMTAxMzU0 4 | MlowHjEcMBoGA1UEAwwTZXhhbXBsZS5ncnBjZGV2LmNvbTCCASIwDQYJKoZIhvcN 5 | AQEBBQADggEPADCCAQoCggEBAO8COdefZftAJ/D5gE4D3tL4BhJ+PG/J5GKNabze 6 | UGfj7cQ0Es5ebTO019N3BwHxvOllJuggO5mN5q2Z7+geRjLp87vHcMhblusikqgM 7 | leL4GjxyJkuK7DhgqeeD8t18uS0oIKJ27h8RXd+5pRHAsTA5K8EivhgzZktOAxhS 8 | UGqGh6spu+Zqt9ghH7HPBokIC8lv14LfnaJmjumBuIfUX4G4B4vyYn4gkovqzeQT 9 | ynqwT41ZG+YnbY15VmGsjxXk5UNl3+P6Aaufq0XhtDkNvPdA8/Gip1hbcRu8EgV9 10 | fRNtOsieHZJiX+Cg5LQ7o1jVNLGJaMtwH+NILmYHInQ5z10CAwEAATANBgkqhkiG 11 | 9w0BAQsFAAOCAQEA2shofflDwP6uBCVmJ0MuUBVARDAXBtJZYC2KwR9yEzFftPa2 12 | 27fevaatpWnz1l3DMdnYhtgPIKEujSjkXtKIl8JEqBLWT2w/iqQduLsnrB/llbMZ 13 | 13i+5Ig8uNERCxuYyzXzTrBKwfHDX64/V2YeyHfJBuuo4XfOvIkxEYQGiYhUwOR6 14 | 6msv5IDTeidM6nsYzPxNq32DMto+DXetEuIOdX+sQHZQ8aSiZUqNU3E8hCBSq1+B 15 | wCrYy63rW74m1+Ch68Td4EAUgzwAv8nVTobOI1+rz0THPyr8/IEhQplpZhtdvmz9 16 | AWgAzEjd7BmHPj6HiozYu3nscI/+LhBPNkPmJg== 17 | -----END CERTIFICATE----- 18 | -------------------------------------------------------------------------------- /grpc-example/grpc-client/cert/ca.srl: -------------------------------------------------------------------------------- 1 | C1EFFCD476734CEE 2 | -------------------------------------------------------------------------------- /grpc-example/grpc-client/cert/client.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIICAjCCAWsCAQAwdjELMAkGA1UEBhMCQ04xEDAOBgNVBAgTB0JlaWppbmcxEDAO 3 | BgNVBAcTB0JlaWppbmcxEDAOBgNVBAoTB2dycGNkZXYxEDAOBgNVBAsTB2dycGNk 4 | ZXYxHzAdBgNVBAMTFnd3dy5leGFtcGxlLmdycGNkZXYuY24wgZ8wDQYJKoZIhvcN 5 | AQEBBQADgY0AMIGJAoGBAJVYS25ejicq7E3nlUrjVxRIat0Ur3YW5r7sGTQwo5FU 6 | fwHIGOXYdiiOGNKtauFz9nPpIYy9IteG0RDlV1QajWgJs7zh9vhoKBmris6YQh8Q 7 | FSIGSrESVwRQyhrlY9+yj5lPM3oVj7KcKoi0qms+6HlUJ/6o7Rg48vMe/97PUAXP 8 | AgMBAAGgTDBKBgkqhkiG9w0BCQ4xPTA7MCEGA1UdEQQaMBiCFnd3dy5leGFtcGxl 9 | LmdycGNkZXYuY24wCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwDQYJKoZIhvcNAQEL 10 | BQADgYEAh9KRU2eJZsVOYnvIGKUKE5e3y1KbiifT8Y3WDgPYESNfo7fjeiuGaZAJ 11 | Yj07aVxeFqDh7HF3dJwY+bfS3s+fftWH5BDbP3f3Q4Wo5dEdgan5AP6i978Gw09C 12 | TZyLR07IVlcdS2zDeCv8NVRrYk1htmXYrxqN+ev81yx9XBuyjxA= 13 | -----END CERTIFICATE REQUEST----- 14 | -------------------------------------------------------------------------------- /grpc-example/grpc-client/cert/client.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJVYS25ejicq7E3n 3 | lUrjVxRIat0Ur3YW5r7sGTQwo5FUfwHIGOXYdiiOGNKtauFz9nPpIYy9IteG0RDl 4 | V1QajWgJs7zh9vhoKBmris6YQh8QFSIGSrESVwRQyhrlY9+yj5lPM3oVj7KcKoi0 5 | qms+6HlUJ/6o7Rg48vMe/97PUAXPAgMBAAECgYBw2aFWKxkbu7GIRMBpMFSyvO4T 6 | VPgpMbD3AA0jhMV0ofa+7+bwd5sBli5ntCcZabkHaViyspDLb9I3BDXzFYVXusY+ 7 | bGvRPUsYxbK17cqRrrJ+6tvsBqVjYvkd2o8YDe4gATfy6y11FGS5NFw8SEI/elCT 8 | VDVNLzfuzLndMttzkQJBAMX4kAMOBdr8MgLqh+q7xL9tnBRx//yk/lr8/R4zAPms 9 | QCNDeyhj1qCBkg44KUgh4bl83N3eY+6ADmsmeuvAKYUCQQDBHuhp8gbXQgT0cYaZ 10 | q/KRj4oC3sQyxXCAAhvjRCthIY61pAZ6cxpZAqpSwZ2DB5qsAaY1gLwFhjoWbTR4 11 | pQhDAkB7Fu0TuShS2/OMdJ5FiLHwBArDe44aW8v6bspCeJvmoP7P7ikpF8peybEy 12 | PiEMxGRAnC4HlTq1E9HjNW3AHx6xAkBGvJB6xfj1fawc8TxRK2dFI+N0W65XvnQP 13 | nzYhz4VoJYeFRthMn76F3fEPMPYF2ZIw8MW1kTrNdzXtowB2NFTLAkA7HBDmYRV2 14 | qgY5zjuwJz+KFyEqGCMmVy/PBZODE8P2Yh8n5kCoBodR3F1g+noHj4ac8jiAtqwP 15 | fJXYHAWCur4b 16 | -----END PRIVATE KEY----- 17 | -------------------------------------------------------------------------------- /grpc-example/grpc-client/cert/client.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICujCCAaKgAwIBAgIJAMHv/NR2c0zuMA0GCSqGSIb3DQEBBQUAMB4xHDAaBgNV 3 | BAMME2V4YW1wbGUuZ3JwY2Rldi5jb20wIBcNMjExMDEyMDE0OTM0WhgPMzAyMTAy 4 | MTIwMTQ5MzRaMHYxCzAJBgNVBAYTAkNOMRAwDgYDVQQIEwdCZWlqaW5nMRAwDgYD 5 | VQQHEwdCZWlqaW5nMRAwDgYDVQQKEwdncnBjZGV2MRAwDgYDVQQLEwdncnBjZGV2 6 | MR8wHQYDVQQDExZ3d3cuZXhhbXBsZS5ncnBjZGV2LmNuMIGfMA0GCSqGSIb3DQEB 7 | AQUAA4GNADCBiQKBgQCVWEtuXo4nKuxN55VK41cUSGrdFK92Fua+7Bk0MKORVH8B 8 | yBjl2HYojhjSrWrhc/Zz6SGMvSLXhtEQ5VdUGo1oCbO84fb4aCgZq4rOmEIfEBUi 9 | BkqxElcEUMoa5WPfso+ZTzN6FY+ynCqItKprPuh5VCf+qO0YOPLzHv/ez1AFzwID 10 | AQABoyUwIzAhBgNVHREEGjAYghZ3d3cuZXhhbXBsZS5ncnBjZGV2LmNuMA0GCSqG 11 | SIb3DQEBBQUAA4IBAQCCnsbFwJylVjNnlGdzdFlUB17j/vizhbasNRaVzJIL6NO6 12 | 6s/UhsMcQuza9esqfZ/XgoShT1dwPyUZTTicMip/tIWr3CROC9C2+0h5BUuNkHYg 13 | rgLvtyvBwbXDAxIunaF/sMmhJ5hsnNq0zpurOTlWiZHHThTI3M3tcAKJrfQ2o3Lw 14 | lAOT7nAbc9hCdhVjT4f7MV1yFDOuqCdFuVIz/oqxabS6RLHnSdAGZtpLuy3aq+ZS 15 | ryqU7J1NxJJ6sB//vgHIHsEKiuzso3F4B1Rx79CdFCrJHQcT4ObYu/eDC+8HxMOj 16 | 4C6WkCwVnYIwfCuTupqV0ydlEUAciivzT6iMEe+2 17 | -----END CERTIFICATE----- 18 | -------------------------------------------------------------------------------- /grpc-example/grpc-client/go.mod: -------------------------------------------------------------------------------- 1 | module grpc-client 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/golang/protobuf v1.5.2 7 | google.golang.org/grpc v1.41.0 8 | ) 9 | -------------------------------------------------------------------------------- /grpc-example/grpc-client/keys/server.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDYDCCAkgCCQDX7WMwAms1izANBgkqhkiG9w0BAQUFADByMQswCQYDVQQGEwJD 3 | TjEQMA4GA1UECAwHYmVpamluZzEQMA4GA1UEBwwHYmVpamluZzEQMA4GA1UECgwH 4 | Z3JwY2RldjEQMA4GA1UECwwHZ3JwY2RldjEbMBkGA1UEAwwSZXhhbXBsZS5ncnBj 5 | ZGV2LmNuMB4XDTIxMTAxMTEzMjg1NloXDTIyMTAxMTEzMjg1NlowcjELMAkGA1UE 6 | BhMCQ04xEDAOBgNVBAgMB2JlaWppbmcxEDAOBgNVBAcMB2JlaWppbmcxEDAOBgNV 7 | BAoMB2dycGNkZXYxEDAOBgNVBAsMB2dycGNkZXYxGzAZBgNVBAMMEmV4YW1wbGUu 8 | Z3JwY2Rldi5jbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMn6cB+e 9 | k18SKRClPb7oAjMk61pd80jN2z8DAwSyv8mmBkG+6995Q1hqUBT9u3+c3X72UGJI 10 | 0ERTlK5A9kwXqtQctkH9Q4IhPfLAOLPWsNKRmSQp5zJ6Te5chB5WW+Bb510LbAC/ 11 | pwwjO7lh9J/ljWfR416YWKhvH+FRuCMKgb2NJqYHywSyBNGs/kFErXVgeP9wA2A8 12 | 2AHztkGZzXsomhCOCATkWdj03ywLOqmxArdAh/DURM3q/x2G1wQpKcPKtrXp1OtA 13 | pdcFaRSJFrwPI0HHYxMIWIhBxaq340Gd3CY/+NXUoVEdLWvM9tH/P6fJ9PFh+9r7 14 | k2Xc+uUmhv1PCpUCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAsbxtI5+wPNhTpCQA 15 | tGukBB3woEYJCO/FxMd7S0ksM23OVBrWcBT+EnFATjFlB3gphBnQqUmV+riWM7Sd 16 | G+lYsrgGDm/c4XPxNiiBdD8MaRoWWYEmaiZd9NYmcN03uS3438HqfAlAOoHGGTYA 17 | AWIqBlyQEjrIvEgDQu5w/alh07bkFmamY6KQ3MNHUwd348VSsg5g20bCPgsR9N9J 18 | EuRi27jPPsx7nEH3VqootAuKxUDekIA3y86m4sY4ixsKUs90Cv2cJPwUg2TY99iJ 19 | 8DCky/gU5bCm9SOG20ZWZlCEerEtBLJRl21H/GSI1ffnbqueVNqWturOEXrKeCw5 20 | 6DgWkg== 21 | -----END CERTIFICATE----- 22 | -------------------------------------------------------------------------------- /grpc-example/grpc-client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "crypto/tls" 6 | "crypto/x509" 7 | "fmt" 8 | "grpc-client/proto" 9 | "io/ioutil" 10 | "log" 11 | 12 | "google.golang.org/grpc" 13 | "google.golang.org/grpc/credentials" 14 | ) 15 | 16 | type Authentication struct { 17 | User string 18 | Password string 19 | } 20 | 21 | func (a *Authentication) GetRequestMetadata(context.Context, ...string) ( 22 | map[string]string, error, 23 | ) { 24 | return map[string]string{"user": a.User, "password": a.Password}, nil 25 | } 26 | 27 | func (a *Authentication) RequireTransportSecurity() bool { 28 | return false 29 | } 30 | 31 | func main() { 32 | // 简单调用 33 | // conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure()) 34 | 35 | // auth := Authentication{ 36 | // User: "admin", 37 | // Password: "admin", 38 | // } 39 | 40 | // Token 认证 41 | // conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure(), grpc.WithPerRPCCredentials(&auth)) 42 | // if err != nil { 43 | // log.Fatal(err) 44 | // } 45 | 46 | // 证书认证-单向认证 47 | // creds, err := credentials.NewClientTLSFromFile("keys/server.crt", "example.grpcdev.cn") 48 | // if err != nil { 49 | // log.Fatal(err) 50 | // return 51 | // } 52 | 53 | // 证书认证-双向认证 54 | // 从证书相关文件中读取和解析信息,得到证书公钥、密钥对 55 | cert, _ := tls.LoadX509KeyPair("cert/client.pem", "cert/client.key") 56 | // 创建一个新的、空的 CertPool 57 | certPool := x509.NewCertPool() 58 | ca, _ := ioutil.ReadFile("cert/ca.pem") 59 | // 尝试解析所传入的 PEM 编码的证书。如果解析成功会将其加到 CertPool 中,便于后面的使用 60 | certPool.AppendCertsFromPEM(ca) 61 | // 构建基于 TLS 的 TransportCredentials 选项 62 | creds := credentials.NewTLS(&tls.Config{ 63 | // 设置证书链,允许包含一个或多个 64 | Certificates: []tls.Certificate{cert}, 65 | // 要求必须校验客户端的证书。可以根据实际情况选用以下参数 66 | ServerName: "www.example.grpcdev.cn", 67 | RootCAs: certPool, 68 | }) 69 | 70 | conn, err := grpc.Dial("localhost:50051", grpc.WithTransportCredentials(creds)) 71 | defer conn.Close() 72 | 73 | client := proto.NewGreeterClient(conn) 74 | // 简单调用 75 | reply, err := client.SayHello(context.Background(), &proto.HelloRequest{Name: "zzz"}) 76 | if err != nil { 77 | log.Fatal(err) 78 | } 79 | fmt.Println(reply.Message) 80 | 81 | // 流处理 82 | // stream, err := client.SayHelloStream(context.Background()) 83 | // if err != nil { 84 | // log.Fatal(err) 85 | // } 86 | 87 | // // 发送消息 88 | // go func() { 89 | // for { 90 | // if err := stream.Send(&proto.HelloRequest{Name: "zhangsan"}); err != nil { 91 | // log.Fatal(err) 92 | // } 93 | // time.Sleep(time.Second) 94 | // } 95 | // }() 96 | 97 | // // 接收消息 98 | // for { 99 | // reply, err := stream.Recv() 100 | // if err != nil { 101 | // if err == io.EOF { 102 | // break 103 | // } 104 | // log.Fatal(err) 105 | // } 106 | // fmt.Println(reply.Message) 107 | // } 108 | } 109 | -------------------------------------------------------------------------------- /grpc-example/grpc-client/proto/helloworld.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // source: helloworld.proto 3 | 4 | package proto 5 | 6 | import ( 7 | context "context" 8 | fmt "fmt" 9 | proto "github.com/golang/protobuf/proto" 10 | grpc "google.golang.org/grpc" 11 | codes "google.golang.org/grpc/codes" 12 | status "google.golang.org/grpc/status" 13 | math "math" 14 | ) 15 | 16 | // Reference imports to suppress errors if they are not otherwise used. 17 | var _ = proto.Marshal 18 | var _ = fmt.Errorf 19 | var _ = math.Inf 20 | 21 | // This is a compile-time assertion to ensure that this generated file 22 | // is compatible with the proto package it is being compiled against. 23 | // A compilation error at this line likely means your copy of the 24 | // proto package needs to be updated. 25 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 26 | 27 | // The request message containing the user's name. 28 | type HelloRequest struct { 29 | Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` 30 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 31 | XXX_unrecognized []byte `json:"-"` 32 | XXX_sizecache int32 `json:"-"` 33 | } 34 | 35 | func (m *HelloRequest) Reset() { *m = HelloRequest{} } 36 | func (m *HelloRequest) String() string { return proto.CompactTextString(m) } 37 | func (*HelloRequest) ProtoMessage() {} 38 | func (*HelloRequest) Descriptor() ([]byte, []int) { 39 | return fileDescriptor_17b8c58d586b62f2, []int{0} 40 | } 41 | 42 | func (m *HelloRequest) XXX_Unmarshal(b []byte) error { 43 | return xxx_messageInfo_HelloRequest.Unmarshal(m, b) 44 | } 45 | func (m *HelloRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 46 | return xxx_messageInfo_HelloRequest.Marshal(b, m, deterministic) 47 | } 48 | func (m *HelloRequest) XXX_Merge(src proto.Message) { 49 | xxx_messageInfo_HelloRequest.Merge(m, src) 50 | } 51 | func (m *HelloRequest) XXX_Size() int { 52 | return xxx_messageInfo_HelloRequest.Size(m) 53 | } 54 | func (m *HelloRequest) XXX_DiscardUnknown() { 55 | xxx_messageInfo_HelloRequest.DiscardUnknown(m) 56 | } 57 | 58 | var xxx_messageInfo_HelloRequest proto.InternalMessageInfo 59 | 60 | func (m *HelloRequest) GetName() string { 61 | if m != nil { 62 | return m.Name 63 | } 64 | return "" 65 | } 66 | 67 | // The response message containing the greetings 68 | type HelloReply struct { 69 | Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` 70 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 71 | XXX_unrecognized []byte `json:"-"` 72 | XXX_sizecache int32 `json:"-"` 73 | } 74 | 75 | func (m *HelloReply) Reset() { *m = HelloReply{} } 76 | func (m *HelloReply) String() string { return proto.CompactTextString(m) } 77 | func (*HelloReply) ProtoMessage() {} 78 | func (*HelloReply) Descriptor() ([]byte, []int) { 79 | return fileDescriptor_17b8c58d586b62f2, []int{1} 80 | } 81 | 82 | func (m *HelloReply) XXX_Unmarshal(b []byte) error { 83 | return xxx_messageInfo_HelloReply.Unmarshal(m, b) 84 | } 85 | func (m *HelloReply) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 86 | return xxx_messageInfo_HelloReply.Marshal(b, m, deterministic) 87 | } 88 | func (m *HelloReply) XXX_Merge(src proto.Message) { 89 | xxx_messageInfo_HelloReply.Merge(m, src) 90 | } 91 | func (m *HelloReply) XXX_Size() int { 92 | return xxx_messageInfo_HelloReply.Size(m) 93 | } 94 | func (m *HelloReply) XXX_DiscardUnknown() { 95 | xxx_messageInfo_HelloReply.DiscardUnknown(m) 96 | } 97 | 98 | var xxx_messageInfo_HelloReply proto.InternalMessageInfo 99 | 100 | func (m *HelloReply) GetMessage() string { 101 | if m != nil { 102 | return m.Message 103 | } 104 | return "" 105 | } 106 | 107 | func init() { 108 | proto.RegisterType((*HelloRequest)(nil), "proto.HelloRequest") 109 | proto.RegisterType((*HelloReply)(nil), "proto.HelloReply") 110 | } 111 | 112 | func init() { proto.RegisterFile("helloworld.proto", fileDescriptor_17b8c58d586b62f2) } 113 | 114 | var fileDescriptor_17b8c58d586b62f2 = []byte{ 115 | // 159 bytes of a gzipped FileDescriptorProto 116 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xc8, 0x48, 0xcd, 0xc9, 117 | 0xc9, 0x2f, 0xcf, 0x2f, 0xca, 0x49, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x05, 0x53, 118 | 0x4a, 0x4a, 0x5c, 0x3c, 0x1e, 0x20, 0xa9, 0xa0, 0xd4, 0xc2, 0xd2, 0xd4, 0xe2, 0x12, 0x21, 0x21, 119 | 0x2e, 0x96, 0xbc, 0xc4, 0xdc, 0x54, 0x09, 0x46, 0x05, 0x46, 0x0d, 0xce, 0x20, 0x30, 0x5b, 0x49, 120 | 0x8d, 0x8b, 0x0b, 0xaa, 0xa6, 0x20, 0xa7, 0x52, 0x48, 0x82, 0x8b, 0x3d, 0x37, 0xb5, 0xb8, 0x38, 121 | 0x31, 0x1d, 0xa6, 0x08, 0xc6, 0x35, 0xaa, 0xe7, 0x62, 0x77, 0x2f, 0x4a, 0x4d, 0x2d, 0x49, 0x2d, 122 | 0x12, 0x32, 0xe1, 0xe2, 0x08, 0x4e, 0xac, 0x04, 0xeb, 0x12, 0x12, 0x86, 0xd8, 0xa8, 0x87, 0x6c, 123 | 0x8f, 0x94, 0x20, 0xaa, 0x60, 0x41, 0x4e, 0xa5, 0x12, 0x83, 0x90, 0x1d, 0x17, 0x1f, 0x4c, 0x57, 124 | 0x70, 0x49, 0x51, 0x6a, 0x62, 0x2e, 0xf1, 0x7a, 0x35, 0x18, 0x0d, 0x18, 0x93, 0xd8, 0xc0, 0xe2, 125 | 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcd, 0x24, 0x7d, 0xbd, 0xee, 0x00, 0x00, 0x00, 126 | } 127 | 128 | // Reference imports to suppress errors if they are not otherwise used. 129 | var _ context.Context 130 | var _ grpc.ClientConn 131 | 132 | // This is a compile-time assertion to ensure that this generated file 133 | // is compatible with the grpc package it is being compiled against. 134 | const _ = grpc.SupportPackageIsVersion4 135 | 136 | // GreeterClient is the client API for Greeter service. 137 | // 138 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. 139 | type GreeterClient interface { 140 | // Sends a greeting 141 | SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) 142 | // Sends stream message 143 | SayHelloStream(ctx context.Context, opts ...grpc.CallOption) (Greeter_SayHelloStreamClient, error) 144 | } 145 | 146 | type greeterClient struct { 147 | cc *grpc.ClientConn 148 | } 149 | 150 | func NewGreeterClient(cc *grpc.ClientConn) GreeterClient { 151 | return &greeterClient{cc} 152 | } 153 | 154 | func (c *greeterClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) { 155 | out := new(HelloReply) 156 | err := c.cc.Invoke(ctx, "/proto.Greeter/SayHello", in, out, opts...) 157 | if err != nil { 158 | return nil, err 159 | } 160 | return out, nil 161 | } 162 | 163 | func (c *greeterClient) SayHelloStream(ctx context.Context, opts ...grpc.CallOption) (Greeter_SayHelloStreamClient, error) { 164 | stream, err := c.cc.NewStream(ctx, &_Greeter_serviceDesc.Streams[0], "/proto.Greeter/SayHelloStream", opts...) 165 | if err != nil { 166 | return nil, err 167 | } 168 | x := &greeterSayHelloStreamClient{stream} 169 | return x, nil 170 | } 171 | 172 | type Greeter_SayHelloStreamClient interface { 173 | Send(*HelloRequest) error 174 | Recv() (*HelloReply, error) 175 | grpc.ClientStream 176 | } 177 | 178 | type greeterSayHelloStreamClient struct { 179 | grpc.ClientStream 180 | } 181 | 182 | func (x *greeterSayHelloStreamClient) Send(m *HelloRequest) error { 183 | return x.ClientStream.SendMsg(m) 184 | } 185 | 186 | func (x *greeterSayHelloStreamClient) Recv() (*HelloReply, error) { 187 | m := new(HelloReply) 188 | if err := x.ClientStream.RecvMsg(m); err != nil { 189 | return nil, err 190 | } 191 | return m, nil 192 | } 193 | 194 | // GreeterServer is the server API for Greeter service. 195 | type GreeterServer interface { 196 | // Sends a greeting 197 | SayHello(context.Context, *HelloRequest) (*HelloReply, error) 198 | // Sends stream message 199 | SayHelloStream(Greeter_SayHelloStreamServer) error 200 | } 201 | 202 | // UnimplementedGreeterServer can be embedded to have forward compatible implementations. 203 | type UnimplementedGreeterServer struct { 204 | } 205 | 206 | func (*UnimplementedGreeterServer) SayHello(ctx context.Context, req *HelloRequest) (*HelloReply, error) { 207 | return nil, status.Errorf(codes.Unimplemented, "method SayHello not implemented") 208 | } 209 | func (*UnimplementedGreeterServer) SayHelloStream(srv Greeter_SayHelloStreamServer) error { 210 | return status.Errorf(codes.Unimplemented, "method SayHelloStream not implemented") 211 | } 212 | 213 | func RegisterGreeterServer(s *grpc.Server, srv GreeterServer) { 214 | s.RegisterService(&_Greeter_serviceDesc, srv) 215 | } 216 | 217 | func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 218 | in := new(HelloRequest) 219 | if err := dec(in); err != nil { 220 | return nil, err 221 | } 222 | if interceptor == nil { 223 | return srv.(GreeterServer).SayHello(ctx, in) 224 | } 225 | info := &grpc.UnaryServerInfo{ 226 | Server: srv, 227 | FullMethod: "/proto.Greeter/SayHello", 228 | } 229 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 230 | return srv.(GreeterServer).SayHello(ctx, req.(*HelloRequest)) 231 | } 232 | return interceptor(ctx, in, info, handler) 233 | } 234 | 235 | func _Greeter_SayHelloStream_Handler(srv interface{}, stream grpc.ServerStream) error { 236 | return srv.(GreeterServer).SayHelloStream(&greeterSayHelloStreamServer{stream}) 237 | } 238 | 239 | type Greeter_SayHelloStreamServer interface { 240 | Send(*HelloReply) error 241 | Recv() (*HelloRequest, error) 242 | grpc.ServerStream 243 | } 244 | 245 | type greeterSayHelloStreamServer struct { 246 | grpc.ServerStream 247 | } 248 | 249 | func (x *greeterSayHelloStreamServer) Send(m *HelloReply) error { 250 | return x.ServerStream.SendMsg(m) 251 | } 252 | 253 | func (x *greeterSayHelloStreamServer) Recv() (*HelloRequest, error) { 254 | m := new(HelloRequest) 255 | if err := x.ServerStream.RecvMsg(m); err != nil { 256 | return nil, err 257 | } 258 | return m, nil 259 | } 260 | 261 | var _Greeter_serviceDesc = grpc.ServiceDesc{ 262 | ServiceName: "proto.Greeter", 263 | HandlerType: (*GreeterServer)(nil), 264 | Methods: []grpc.MethodDesc{ 265 | { 266 | MethodName: "SayHello", 267 | Handler: _Greeter_SayHello_Handler, 268 | }, 269 | }, 270 | Streams: []grpc.StreamDesc{ 271 | { 272 | StreamName: "SayHelloStream", 273 | Handler: _Greeter_SayHelloStream_Handler, 274 | ServerStreams: true, 275 | ClientStreams: true, 276 | }, 277 | }, 278 | Metadata: "helloworld.proto", 279 | } 280 | -------------------------------------------------------------------------------- /grpc-example/grpc-server/cert/ca.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEowIBAAKCAQEA7wI5159l+0An8PmATgPe0vgGEn48b8nkYo1pvN5QZ+PtxDQS 3 | zl5tM7TX03cHAfG86WUm6CA7mY3mrZnv6B5GMunzu8dwyFuW6yKSqAyV4vgaPHIm 4 | S4rsOGCp54Py3Xy5LSggonbuHxFd37mlEcCxMDkrwSK+GDNmS04DGFJQaoaHqym7 5 | 5mq32CEfsc8GiQgLyW/Xgt+domaO6YG4h9RfgbgHi/JifiCSi+rN5BPKerBPjVkb 6 | 5idtjXlWYayPFeTlQ2Xf4/oBq5+rReG0OQ2890Dz8aKnWFtxG7wSBX19E206yJ4d 7 | kmJf4KDktDujWNU0sYloy3Af40guZgcidDnPXQIDAQABAoIBAFsgMyOFz6Eizdev 8 | mP6ltSAkllQYszw/8oasugLblDZ4DaA/5meuUt5i9eLXP+G65DbsbRAVsgOSub+4 9 | sGKEoGkrD9WpbdPGL91ImjfeTItz4rTnJLiqp/O6zyzI/yD5O7T+1qp6w8Euoub4 10 | 5fnFyQjE02zYrTeW6UqO3Nk6ERT7pzhVl978IZOqbBSdjCizzWkO7T5B2P8jbE4D 11 | x3cVmuXbTT1an7hgLFVHrXvJdbf23gP8cdN8BLMzRbPBGzQFv3pJzAB2OgPXQJiX 12 | 5PxxW11DrZLMXRXTfLLLJ/cd96XIPJ5dGqHvZZ1ZUCK2jrEcqD64OPmGhy4+N533 13 | iuKJHXUCgYEA/CkgAwveuPkCFR0VGl491U9KPU5Ke093WMKwbl9UY+07RtX0u4RB 14 | dv1JvJg1SguWY+r5kFMsX+190g/Nn7XwNgHoMdqT/SrlqGLp4CWi+za9ZYB03O8s 15 | IMZxMQMmCjWJUiL7Tf2xVpe2t9FPp8WH/oauyBKjQkSri5vC5Hl3YlcCgYEA8qXW 16 | SdbzYrwfi8OPvA1ympXtwyIzlfFQCRvSzRMLpbBPw7n/hsEni4tPQDR4KosGJazx 17 | El9lpMrhRPPCXHx6stdglINQyM14u9t5Ra7N7GBfDdE//NDh1VCM5v1Xsm5sGyZ7 18 | 621eo0ET64qcN/w4bi9bb2nn9RVu3xebXrEq02sCgYEAyPfd04+6SqHqzvkGwKUr 19 | kr5G5OVo5y5GaC+CffTsRVflTmdnTavyoOrtwaltjz389lVn4Wbojuuww6Jkt01B 20 | zUlnzZPvLm7p6nIrA8H7S0wtVqAyg4L7IIQH4pAn2Ssh7pyCvX3bwK/ZqFbhrUz5 21 | PhoJYtu30jD4p6PUiFNmmrECgYBXKcdeYv6u+xEB7dAWJ2aBrVXpgMGzHSo4+2uw 22 | CyVl8X3Vu1zVFVGVSQfA8pgwABzHL+axSN+EYPSnBkFNY9HXqJKjBsDgQR8brG1V 23 | 4MNMJBpBJmer84UMUZEr8Nmt2QiwgBSHr5QNZPU46WPQoKPMwOpBjXOrkHVxYlOH 24 | onDV3QKBgEcXeMe0P7TyB4MyVW6PyM88S3MCKEmQaeYnVLNHiVI9XZFKtMyrRByq 25 | HJjD/ZG/+kNvnmwjJqubS/zR4oMKPJouyuc+FtfbwOapN8SpX3IObgTCX1GazET4 26 | /CnOIhBHy/UsRp6/rir28ijJs4Il3Qqw7dVi4hxxxYDOF9NnjDjm 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /grpc-example/grpc-server/cert/ca.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICuDCCAaACCQCZFaleThXYnDANBgkqhkiG9w0BAQsFADAeMRwwGgYDVQQDDBNl 3 | eGFtcGxlLmdycGNkZXYuY29tMB4XDTIxMTAxMjAxMzU0MloXDTM1MDYyMTAxMzU0 4 | MlowHjEcMBoGA1UEAwwTZXhhbXBsZS5ncnBjZGV2LmNvbTCCASIwDQYJKoZIhvcN 5 | AQEBBQADggEPADCCAQoCggEBAO8COdefZftAJ/D5gE4D3tL4BhJ+PG/J5GKNabze 6 | UGfj7cQ0Es5ebTO019N3BwHxvOllJuggO5mN5q2Z7+geRjLp87vHcMhblusikqgM 7 | leL4GjxyJkuK7DhgqeeD8t18uS0oIKJ27h8RXd+5pRHAsTA5K8EivhgzZktOAxhS 8 | UGqGh6spu+Zqt9ghH7HPBokIC8lv14LfnaJmjumBuIfUX4G4B4vyYn4gkovqzeQT 9 | ynqwT41ZG+YnbY15VmGsjxXk5UNl3+P6Aaufq0XhtDkNvPdA8/Gip1hbcRu8EgV9 10 | fRNtOsieHZJiX+Cg5LQ7o1jVNLGJaMtwH+NILmYHInQ5z10CAwEAATANBgkqhkiG 11 | 9w0BAQsFAAOCAQEA2shofflDwP6uBCVmJ0MuUBVARDAXBtJZYC2KwR9yEzFftPa2 12 | 27fevaatpWnz1l3DMdnYhtgPIKEujSjkXtKIl8JEqBLWT2w/iqQduLsnrB/llbMZ 13 | 13i+5Ig8uNERCxuYyzXzTrBKwfHDX64/V2YeyHfJBuuo4XfOvIkxEYQGiYhUwOR6 14 | 6msv5IDTeidM6nsYzPxNq32DMto+DXetEuIOdX+sQHZQ8aSiZUqNU3E8hCBSq1+B 15 | wCrYy63rW74m1+Ch68Td4EAUgzwAv8nVTobOI1+rz0THPyr8/IEhQplpZhtdvmz9 16 | AWgAzEjd7BmHPj6HiozYu3nscI/+LhBPNkPmJg== 17 | -----END CERTIFICATE----- 18 | -------------------------------------------------------------------------------- /grpc-example/grpc-server/cert/ca.srl: -------------------------------------------------------------------------------- 1 | C1EFFCD476734CEC 2 | -------------------------------------------------------------------------------- /grpc-example/grpc-server/cert/server.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIICAjCCAWsCAQAwdjELMAkGA1UEBhMCQ04xEDAOBgNVBAgTB0JlaWppbmcxEDAO 3 | BgNVBAcTB0JlaWppbmcxEDAOBgNVBAoTB2dycGNkZXYxEDAOBgNVBAsTB2dycGNk 4 | ZXYxHzAdBgNVBAMTFnd3dy5leGFtcGxlLmdycGNkZXYuY24wgZ8wDQYJKoZIhvcN 5 | AQEBBQADgY0AMIGJAoGBAJluxrBFmsZNtC1rUPw7iC58zoqiAmByDWBHS0gyOf2x 6 | nSVmtxuAClnoER10GcIycxxF21LIgTi+YYK+mzlUdjEv4JPAYJRZSaHCKC19TlqI 7 | fErJwqkRJ1u+Xucb3NaNTS5oZGuj8CGrCRuOswPDOkieKbUm8jIh2qumAa7bEH+D 8 | AgMBAAGgTDBKBgkqhkiG9w0BCQ4xPTA7MCEGA1UdEQQaMBiCFnd3dy5leGFtcGxl 9 | LmdycGNkZXYuY24wCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwDQYJKoZIhvcNAQEL 10 | BQADgYEAYAJti6GFaI+ur878hdHJGOb/4kAFfNmFkDlD+xuIghwXwwlnIpG1kzq4 11 | 9pAOrWgOMMZtvSqT+AjOdSmX0VB2mtuYMEreFV3n42/uORvy+aCaq6oIJapB3kIj 12 | 9cuVji22Gp1PIlLmtpbfV6W76dVY6bSyy09TZU1g0rwvfNeQowQ= 13 | -----END CERTIFICATE REQUEST----- 14 | -------------------------------------------------------------------------------- /grpc-example/grpc-server/cert/server.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJluxrBFmsZNtC1r 3 | UPw7iC58zoqiAmByDWBHS0gyOf2xnSVmtxuAClnoER10GcIycxxF21LIgTi+YYK+ 4 | mzlUdjEv4JPAYJRZSaHCKC19TlqIfErJwqkRJ1u+Xucb3NaNTS5oZGuj8CGrCRuO 5 | swPDOkieKbUm8jIh2qumAa7bEH+DAgMBAAECgYAdKoumcnTLgXXgtGe+qupmO99f 6 | RxDAmK2mQacz4ChZ62t98pqYJazSDmVCfhFvcvuiwjzA7dByou4SVn1XVpDo2VmF 7 | MJkhl9fmlYOvy48ylLKbK6tkIZsxFt3lWvxaygMddeXgqj1yUk6+n8aRk2N7W6dQ 8 | CByEbukhw1M8of1mIQJBAMwM4ZqYLtRDV7XkKhBED4odMCzRY+lQAS4/MZ/Uk2GN 9 | Tr/sq3t+i86fFXSpsu7JI7QLQJcE8ULYFgeQdZmdhMkCQQDAftu8hiR7gA3Z6jpu 10 | QLQ092qLDaHFLbpHe7kVQH08Jk0KVf9dSyWrExUM+9lRRrczTQai/CkrVpM50EjO 11 | f0PrAkEAkazQk9H5/MhnIhBWh25PucbE0fpbXgIkFaRABV96KLb9db+9XVkm7shc 12 | RQGyIQ+wUaWG40pAA/zJHXVgv97ZIQJAQ5RF0InHhRQPyNFSciKFIZM69FZ01KSZ 13 | IT9uWuepD9Tidx556GbZcpXgbg583OvWpUwFaHLegTiDt2hIJzbGwQJBAKSOoTHM 14 | cjgcMbfW9BZQUMbAnAXnT78vSAoJagKH/0ceMp/HCXXuU4KDaeRc+iqioV0Kib6h 15 | bIfGGx7ze8EsCvA= 16 | -----END PRIVATE KEY----- 17 | -------------------------------------------------------------------------------- /grpc-example/grpc-server/cert/server.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICujCCAaKgAwIBAgIJAMHv/NR2c0zsMA0GCSqGSIb3DQEBBQUAMB4xHDAaBgNV 3 | BAMME2V4YW1wbGUuZ3JwY2Rldi5jb20wIBcNMjExMDEyMDE0MzMzWhgPMzAyMTAy 4 | MTIwMTQzMzNaMHYxCzAJBgNVBAYTAkNOMRAwDgYDVQQIEwdCZWlqaW5nMRAwDgYD 5 | VQQHEwdCZWlqaW5nMRAwDgYDVQQKEwdncnBjZGV2MRAwDgYDVQQLEwdncnBjZGV2 6 | MR8wHQYDVQQDExZ3d3cuZXhhbXBsZS5ncnBjZGV2LmNuMIGfMA0GCSqGSIb3DQEB 7 | AQUAA4GNADCBiQKBgQCZbsawRZrGTbQta1D8O4gufM6KogJgcg1gR0tIMjn9sZ0l 8 | ZrcbgApZ6BEddBnCMnMcRdtSyIE4vmGCvps5VHYxL+CTwGCUWUmhwigtfU5aiHxK 9 | ycKpESdbvl7nG9zWjU0uaGRro/AhqwkbjrMDwzpInim1JvIyIdqrpgGu2xB/gwID 10 | AQABoyUwIzAhBgNVHREEGjAYghZ3d3cuZXhhbXBsZS5ncnBjZGV2LmNuMA0GCSqG 11 | SIb3DQEBBQUAA4IBAQBMDzxkB/ejJLgifvmQr7Z2S8pPVX4iEKi3MOMZyH3Nt1l6 12 | jHGz0Fa0yJ8j5rxd+wATK7VZVP93TSB7wMXeSZxCETK1X8ZEAuR/VsM5RQdO/s9H 13 | RALrffXoA6xo6N9lh3tKe2/kbwE+mFCAhA8Pu4l+/6ZSSZHJWXX6t/ptnJnWI7Dc 14 | j2zFki+nCt/T2tR8r8m3ZbRmbFYZZMeX86CrTh0jRzOO/d3MZWY2dfFVi8Ibu9yh 15 | Nc0buDMPkjnC9M63s7ip6UXCapY0exwvHXU+sLeYE2lqrLOoKXuuHwCn8RqaGQhV 16 | 64LNe7uiMKHrOYqWXYfQ+QbN9wgJoFRCTdZzhWEE 17 | -----END CERTIFICATE----- 18 | -------------------------------------------------------------------------------- /grpc-example/grpc-server/go.mod: -------------------------------------------------------------------------------- 1 | module grpc-server 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/golang/protobuf v1.5.2 7 | github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect 8 | github.com/mwitkow/go-proto-validators v0.3.2 // indirect 9 | google.golang.org/grpc v1.41.0 10 | ) 11 | -------------------------------------------------------------------------------- /grpc-example/grpc-server/keys/server.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDYDCCAkgCCQDX7WMwAms1izANBgkqhkiG9w0BAQUFADByMQswCQYDVQQGEwJD 3 | TjEQMA4GA1UECAwHYmVpamluZzEQMA4GA1UEBwwHYmVpamluZzEQMA4GA1UECgwH 4 | Z3JwY2RldjEQMA4GA1UECwwHZ3JwY2RldjEbMBkGA1UEAwwSZXhhbXBsZS5ncnBj 5 | ZGV2LmNuMB4XDTIxMTAxMTEzMjg1NloXDTIyMTAxMTEzMjg1NlowcjELMAkGA1UE 6 | BhMCQ04xEDAOBgNVBAgMB2JlaWppbmcxEDAOBgNVBAcMB2JlaWppbmcxEDAOBgNV 7 | BAoMB2dycGNkZXYxEDAOBgNVBAsMB2dycGNkZXYxGzAZBgNVBAMMEmV4YW1wbGUu 8 | Z3JwY2Rldi5jbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMn6cB+e 9 | k18SKRClPb7oAjMk61pd80jN2z8DAwSyv8mmBkG+6995Q1hqUBT9u3+c3X72UGJI 10 | 0ERTlK5A9kwXqtQctkH9Q4IhPfLAOLPWsNKRmSQp5zJ6Te5chB5WW+Bb510LbAC/ 11 | pwwjO7lh9J/ljWfR416YWKhvH+FRuCMKgb2NJqYHywSyBNGs/kFErXVgeP9wA2A8 12 | 2AHztkGZzXsomhCOCATkWdj03ywLOqmxArdAh/DURM3q/x2G1wQpKcPKtrXp1OtA 13 | pdcFaRSJFrwPI0HHYxMIWIhBxaq340Gd3CY/+NXUoVEdLWvM9tH/P6fJ9PFh+9r7 14 | k2Xc+uUmhv1PCpUCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAsbxtI5+wPNhTpCQA 15 | tGukBB3woEYJCO/FxMd7S0ksM23OVBrWcBT+EnFATjFlB3gphBnQqUmV+riWM7Sd 16 | G+lYsrgGDm/c4XPxNiiBdD8MaRoWWYEmaiZd9NYmcN03uS3438HqfAlAOoHGGTYA 17 | AWIqBlyQEjrIvEgDQu5w/alh07bkFmamY6KQ3MNHUwd348VSsg5g20bCPgsR9N9J 18 | EuRi27jPPsx7nEH3VqootAuKxUDekIA3y86m4sY4ixsKUs90Cv2cJPwUg2TY99iJ 19 | 8DCky/gU5bCm9SOG20ZWZlCEerEtBLJRl21H/GSI1ffnbqueVNqWturOEXrKeCw5 20 | 6DgWkg== 21 | -----END CERTIFICATE----- 22 | -------------------------------------------------------------------------------- /grpc-example/grpc-server/keys/server.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIICtzCCAZ8CAQAwcjELMAkGA1UEBhMCQ04xEDAOBgNVBAgMB2JlaWppbmcxEDAO 3 | BgNVBAcMB2JlaWppbmcxEDAOBgNVBAoMB2dycGNkZXYxEDAOBgNVBAsMB2dycGNk 4 | ZXYxGzAZBgNVBAMMEmV4YW1wbGUuZ3JwY2Rldi5jbjCCASIwDQYJKoZIhvcNAQEB 5 | BQADggEPADCCAQoCggEBAMn6cB+ek18SKRClPb7oAjMk61pd80jN2z8DAwSyv8mm 6 | BkG+6995Q1hqUBT9u3+c3X72UGJI0ERTlK5A9kwXqtQctkH9Q4IhPfLAOLPWsNKR 7 | mSQp5zJ6Te5chB5WW+Bb510LbAC/pwwjO7lh9J/ljWfR416YWKhvH+FRuCMKgb2N 8 | JqYHywSyBNGs/kFErXVgeP9wA2A82AHztkGZzXsomhCOCATkWdj03ywLOqmxArdA 9 | h/DURM3q/x2G1wQpKcPKtrXp1OtApdcFaRSJFrwPI0HHYxMIWIhBxaq340Gd3CY/ 10 | +NXUoVEdLWvM9tH/P6fJ9PFh+9r7k2Xc+uUmhv1PCpUCAwEAAaAAMA0GCSqGSIb3 11 | DQEBCwUAA4IBAQCeRk/Vxe7ViBcowh/KOCx93d1SCa7m45krIZNou+5ZoLMj+CLq 12 | l+pJp/0t2VxGZKt7zM1PchS+vT9Ux1EHns1F1oWdZBaKg5oRxOwLtrveOMl+h4dW 13 | /bTMiycRGiBXn+Y15drnMIDNhTDf88/BW4qPGQLP7GkHFxe3I+tEfdShDn03idXR 14 | H35XqME8dhXoDqZXap5ERPHirm7+hU+34o/CzXHqvKcNjjrXOY3CgaLhgh5BBDq+ 15 | Xczt/hRTIgxlV0W6UUhpJ5elbYdlBohBYlnDaZLGVnM3++GUaM8mWaVvBEUbvdUE 16 | O6WhvLOnjmGRqWcTcDWX87upWKUhV7DkpyIi 17 | -----END CERTIFICATE REQUEST----- 18 | -------------------------------------------------------------------------------- /grpc-example/grpc-server/keys/server.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpgIBAAKCAQEAyfpwH56TXxIpEKU9vugCMyTrWl3zSM3bPwMDBLK/yaYGQb7r 3 | 33lDWGpQFP27f5zdfvZQYkjQRFOUrkD2TBeq1By2Qf1DgiE98sA4s9aw0pGZJCnn 4 | MnpN7lyEHlZb4FvnXQtsAL+nDCM7uWH0n+WNZ9HjXphYqG8f4VG4IwqBvY0mpgfL 5 | BLIE0az+QUStdWB4/3ADYDzYAfO2QZnNeyiaEI4IBORZ2PTfLAs6qbECt0CH8NRE 6 | zer/HYbXBCkpw8q2tenU60Cl1wVpFIkWvA8jQcdjEwhYiEHFqrfjQZ3cJj/41dSh 7 | UR0ta8z20f8/p8n08WH72vuTZdz65SaG/U8KlQIDAQABAoIBAQC/X5t9WjMokXx3 8 | WRn4GLx82S5moT4ybVqfiasCeJtf5P9orA2x4KP+0jyupvtRHsB/28KuXW94TflC 9 | Yir8TjB+afYG8IFWe0jHCXqwa2t/GJWRvmJhYaEViHNmi0zieDHv5zKeQvl0dq3Q 10 | KRAvsMEa7bQRnSfj7+a1B0kBaqMjhTs6+CLOaIUfNZCAQe9/PEuAIx2a85ujfMqV 11 | REaNfPUC0c75fWXujPVZTyEOr1jeP5qdof2P2HHE5dE1ec+voR2TTY9eCJwqTo9G 12 | fxgseoMms12kFDoNvb7VEjL2TEMax36YAY9vxXvD2zjcr9ez+nL8+h660sPpx/gl 13 | GjWm7sgBAoGBAOueBrZ8WlyzXX0lvTXhaELYV/tSduuQhmGBgehxIZwz7PN/2iDB 14 | kQ1Klf3UOYR5GtrbysJHkhgKYZydmGSRKdm7GcCdGGjg7Ajovp2CVQZBpwxDxLbs 15 | nHNQZ/6SZnqi9ySUXOJYUarEUM0BBoU+OJUYHEhltBW2jG0Gdk8JOtChAoGBANtz 16 | cWxeFG0uoAurpZzoazSmeRJJM0MWoMonqLMITD3ph5x8z0FJk0vzg2B2ac7K8SIt 17 | QmOllrPmILeuv7bYUpPPKm/QM71P5Uq2YnTTAzN9GSGc/j8eOBokJxhuDHdzA5iP 18 | 1JcgBbUkljtlSPx9rXIW9YIp8a3aAmF9QJDdsxF1AoGBAKZPNefLILE8PeofIE4O 19 | 29wK/xc7nwspSWE726lpaVLrZ/58KUhjuPILypGPIkY6gVUoPRcjE6D6eunkZ3Pc 20 | 7xBru4K0oE0vLgwf1KQzIba30qSalRiVLN1MTQto5QL9Urs0KdfuhT6nMW1yotqc 21 | D65VhWkouJN29eni3NFu71/hAoGBALE0yn1ghwwXX2OtKqHGyHMOjqumcn+VMSes 22 | 2LwhUjeYcUp7On0U5Z2qOQdW91/mXstjUr3WhBgnF3pb4THMAvqaikEaFf2kG5q2 23 | JlEB6A7W0Mlk1aWwSEtLsEo461Y1iMzUMC4MzK8WqT2zLzm8XqfHRF7kceUaK1v/ 24 | 4XhZnfTVAoGBAJ3rAh1C48Ypq2Hgq1XgUPwJefOm+sZsbLGaa36UGXdK6s9JnjZI 25 | zFRHOCOHd+ltPslAWZwRPEqWuuCLaKGV6hjXktyL9T4MTGiDBr/0tXQZmreiP9gL 26 | r5Cn4XeYiKUSLUAlY64TMlU6DBPJsPSPsFjCkTiZt9eKYnrdPKZDYcuq 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /grpc-example/grpc-server/keys/server.pass.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | Proc-Type: 4,ENCRYPTED 3 | DEK-Info: DES-EDE3-CBC,7EFA2000786A3A41 4 | 5 | ViFoq8TVqM1EGCXHzldnmuTbdzjRdI5BESEnLThtoqTFFA0X08nHGzyjNVQyUR/l 6 | 76rOu48Z3NnRV2RXz4VU8e9C1f5vaIgGO7sNlqyXkd901/b36TQsh+zGEj80jLFR 7 | wkTjxpBsLfTb0AU/YcuW6QL1AkswoTfSSqwe86Jjpkp3tk2+hYOcPE226orbmGzU 8 | 37js6l8vkv4fb6UcYOQUKGyGmMmDbud9VjiA3YLgUi3Z5iNVA0lW3VIwTc62nv+N 9 | awhxYtEYGy6APY1y3cOey+KSRZ1pBTVzPsh0kvXmSzf/B7/lOq5f58I1kDDFycG1 10 | Ay6Ce2CRrlWCT1bdl6iIxL0G7OLto6h/Bdcv+FGZWgO2xST9IMRroKm1OYWTdpR4 11 | 5/njgSYvxdrpV/ARfl2oGMIM/iMGuTbi9frwWMWsXWyL7STcMB3m7JTCfkmJ0iod 12 | lhtoxzSU8SB4rg29W7dfy06WcxtcELS9IL+G4m4czVv2Ug8j09CU8i291qcW00un 13 | g943WTO2RUNv3nmPMD1V6wyZBnYp0DfvTPaNn++H0zOKiDYjRJXbI3iIP6zFYUPC 14 | 3too3xxP2i6g4UZ6hG2jXbuNM84PiAYc6T0Yg+2foMLcveCKcjcGK6X47pCsOwq7 15 | a0p0fCQr8N8GiB99liw1uqpRgau4sCykZ22kx2HVkUkxM0ejg5nEffuBSN0fhidj 16 | YgEZyHOr1r/6gSkPKj9WHFZKW/p8AnpJoZOmDK/j+UgnmSmrloTsgeXIGB97CK+O 17 | JFASUXlKJGeoOvnsdvxESlieSf/rinWKh5HaXj1sZCgbBDKPW8BvR7d1ntbECm31 18 | Af9GsMCv3aUt50AGoAX0Qgg12BEKYsjRJt4lcHqNdyv9BQvLKD4cjSE5BMqFAmpr 19 | zJNGvklMmr3hM8bQnZewkDza/Fnb7Gj8aSXjxKzY3ev1YDXmYcMsskBzlmaNYT63 20 | N5xfx5pN/kdutCiVSWcmX+GVSnaDHgaXXPJc/YrcnMC/fkBskBEu04e9qu0ILms8 21 | rvPOdaoMW5UqEcqlNlPo5g70jQCCAbG5HUz6SKwHu5hQTyuORUCcn0N7e9fRXOwo 22 | bil1I4ND0k83ypnBX7UW9r2CZJx0786MUzzrWZaotmYceQ2/TBtm4MOTJan7ZVgW 23 | zKAyKNoZmQPEqoimeC9OG2bocsMdXvwFfErEKOdbmGpoTCsy8oIhG4cJ+LuO7Ciy 24 | g0HcF3R4aF45TJjiFJB2BrlBGHb7HHomTBT5BMb0RYnF+ei0S2pnYyPYp7q9u+63 25 | EbmmTD96tXEhLBwbYo8zDLfYX/9XCzYZQaBNE3zDsdbcvziwM/mYwEvJYwehnVY9 26 | plTigwmjvYeMAz8SJUv+ZWz8AdQAp7K+hJPdHBYu2LSi9Wdnx8/c0k6RrQ8vZeAq 27 | A37H8wk1T1NUrpJqDIPQ/zUQ/u3F4DE32H9wqp11h5WGWvvOVRj0cz8J7zvDbDE8 28 | bsIcyPqov5n4kl2utFyEUx5JJXpGX/E0/b4KZYFv0Lyq4m29pgBeYuYcdnG4msB6 29 | 4fGG9YuBTiMjekhn1l9VyUXrNEewQ+GhxToz9kRYVsAAovbR6H7ac8Tk/eoEP6O9 30 | -----END RSA PRIVATE KEY----- 31 | -------------------------------------------------------------------------------- /grpc-example/grpc-server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "crypto/tls" 6 | "crypto/x509" 7 | "fmt" 8 | "grpc-server/proto" 9 | "io" 10 | "io/ioutil" 11 | "log" 12 | "net" 13 | 14 | grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware" 15 | grpc_validator "github.com/grpc-ecosystem/go-grpc-middleware/validator" 16 | "google.golang.org/grpc" 17 | "google.golang.org/grpc/codes" 18 | "google.golang.org/grpc/credentials" 19 | "google.golang.org/grpc/metadata" 20 | "google.golang.org/grpc/reflection" 21 | ) 22 | 23 | // Token 认证 24 | func Auth(ctx context.Context) error { 25 | md, ok := metadata.FromIncomingContext(ctx) 26 | if !ok { 27 | return fmt.Errorf("missing credentials") 28 | } 29 | 30 | var user string 31 | var password string 32 | 33 | if val, ok := md["user"]; ok { 34 | user = val[0] 35 | } 36 | if val, ok := md["password"]; ok { 37 | password = val[0] 38 | } 39 | 40 | if user != "admin" || password != "admin" { 41 | return grpc.Errorf(codes.Unauthenticated, "invalid token") 42 | } 43 | 44 | return nil 45 | } 46 | 47 | type greeter struct { 48 | } 49 | 50 | func (*greeter) SayHello(ctx context.Context, req *proto.HelloRequest) (*proto.HelloReply, error) { 51 | fmt.Println(req) 52 | reply := &proto.HelloReply{Message: "hello"} 53 | return reply, nil 54 | } 55 | 56 | func (*greeter) SayHelloStream(stream proto.Greeter_SayHelloStreamServer) error { 57 | for { 58 | args, err := stream.Recv() 59 | if err != nil { 60 | if err == io.EOF { 61 | return nil 62 | } 63 | return err 64 | } 65 | 66 | fmt.Println("Recv: " + args.Name) 67 | reply := &proto.HelloReply{Message: "hi " + args.Name} 68 | 69 | err = stream.Send(reply) 70 | if err != nil { 71 | return err 72 | } 73 | } 74 | } 75 | 76 | func main() { 77 | lis, err := net.Listen("tcp", ":50051") 78 | if err != nil { 79 | log.Fatalf("failed to listen: %v", err) 80 | } 81 | 82 | // 简单调用 83 | // server := grpc.NewServer() 84 | 85 | // Token 认证 86 | // var authInterceptor grpc.UnaryServerInterceptor 87 | // authInterceptor = func( 88 | // ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler, 89 | // ) (resp interface{}, err error) { 90 | // //拦截普通方法请求,验证 Token 91 | // err = Auth(ctx) 92 | // if err != nil { 93 | // return 94 | // } 95 | // // 继续处理请求 96 | // return handler(ctx, req) 97 | // } 98 | // server := grpc.NewServer(grpc.UnaryInterceptor(interceptor)) 99 | 100 | // 证书认证-单向认证 101 | // creds, err := credentials.NewServerTLSFromFile("keys/server.crt", "keys/server.key") 102 | // if err != nil { 103 | // log.Fatal(err) 104 | // return 105 | // } 106 | 107 | // 证书认证-双向认证 108 | // 从证书相关文件中读取和解析信息,得到证书公钥、密钥对 109 | cert, _ := tls.LoadX509KeyPair("cert/server.pem", "cert/server.key") 110 | // 创建一个新的、空的 CertPool 111 | certPool := x509.NewCertPool() 112 | ca, _ := ioutil.ReadFile("cert/ca.pem") 113 | // 尝试解析所传入的 PEM 编码的证书。如果解析成功会将其加到 CertPool 中,便于后面的使用 114 | certPool.AppendCertsFromPEM(ca) 115 | // 构建基于 TLS 的 TransportCredentials 选项 116 | creds := credentials.NewTLS(&tls.Config{ 117 | // 设置证书链,允许包含一个或多个 118 | Certificates: []tls.Certificate{cert}, 119 | // 要求必须校验客户端的证书。可以根据实际情况选用以下参数 120 | ClientAuth: tls.RequireAndVerifyClientCert, 121 | // 设置根证书的集合,校验方式使用 ClientAuth 中设定的模式 122 | ClientCAs: certPool, 123 | }) 124 | 125 | // 增加验证器,分别是标准模式和流模式 126 | server := grpc.NewServer(grpc.Creds(creds), 127 | grpc.UnaryInterceptor( 128 | grpc_middleware.ChainUnaryServer( 129 | // Token 认证 130 | // authInterceptor, 131 | grpc_validator.UnaryServerInterceptor(), 132 | ), 133 | ), 134 | grpc.StreamInterceptor( 135 | grpc_middleware.ChainStreamServer( 136 | grpc_validator.StreamServerInterceptor(), 137 | ), 138 | ), 139 | ) 140 | // 注册 grpcurl 所需的 reflection 服务 141 | reflection.Register(server) 142 | // 注册业务服务 143 | proto.RegisterGreeterServer(server, &greeter{}) 144 | 145 | fmt.Println("grpc server start ...") 146 | if err := server.Serve(lis); err != nil { 147 | log.Fatalf("failed to serve: %v", err) 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /grpc-example/grpc-server/proto/gen_proto.sh: -------------------------------------------------------------------------------- 1 | 2 | # protoc --go_out=plugins=grpc:. *.proto 3 | 4 | protoc \ 5 | --proto_path=${GOPATH}/pkg/mod \ 6 | --proto_path=${GOPATH}/pkg/mod/github.com/gogo/protobuf@v1.3.2 \ 7 | --proto_path=. \ 8 | --govalidators_out=. --go_out=plugins=grpc:.\ 9 | *.proto -------------------------------------------------------------------------------- /grpc-example/grpc-server/proto/helloworld.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package proto; 4 | 5 | // 验证器引入 6 | import "github.com/mwitkow/go-proto-validators@v0.3.2/validator.proto"; 7 | 8 | // The greeting service definition. 9 | service Greeter { 10 | // Sends a greeting 11 | rpc SayHello (HelloRequest) returns (HelloReply) {} 12 | // Sends stream message 13 | rpc SayHelloStream (stream HelloRequest) returns (stream HelloReply) {} 14 | } 15 | 16 | // The request message containing the user's name. 17 | // message HelloRequest { 18 | // string name = 1; 19 | // } 20 | 21 | // 增加验证器 22 | message HelloRequest { 23 | string name = 1 [ 24 | (validator.field) = {regex: "^[z]{2,5}$"} 25 | ]; 26 | } 27 | 28 | // The response message containing the greetings 29 | message HelloReply { 30 | string message = 1; 31 | } -------------------------------------------------------------------------------- /grpc-example/grpc-server/proto/helloworld.validator.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-gogo. DO NOT EDIT. 2 | // source: helloworld.proto 3 | 4 | package proto 5 | 6 | import ( 7 | fmt "fmt" 8 | math "math" 9 | proto "github.com/golang/protobuf/proto" 10 | _ "github.com/mwitkow/go-proto-validators" 11 | regexp "regexp" 12 | github_com_mwitkow_go_proto_validators "github.com/mwitkow/go-proto-validators" 13 | ) 14 | 15 | // Reference imports to suppress errors if they are not otherwise used. 16 | var _ = proto.Marshal 17 | var _ = fmt.Errorf 18 | var _ = math.Inf 19 | 20 | var _regex_HelloRequest_Name = regexp.MustCompile(`^[z]{2,5}$`) 21 | 22 | func (this *HelloRequest) Validate() error { 23 | if !_regex_HelloRequest_Name.MatchString(this.Name) { 24 | return github_com_mwitkow_go_proto_validators.FieldError("Name", fmt.Errorf(`value '%v' must be a string conforming to regex "^[z]{2,5}$"`, this.Name)) 25 | } 26 | return nil 27 | } 28 | func (this *HelloReply) Validate() error { 29 | return nil 30 | } 31 | -------------------------------------------------------------------------------- /grpc-example/pubsub/client/go.mod: -------------------------------------------------------------------------------- 1 | module client 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/golang/protobuf v1.5.2 7 | google.golang.org/grpc v1.41.0 8 | google.golang.org/protobuf v1.26.0 // indirect 9 | ) 10 | -------------------------------------------------------------------------------- /grpc-example/pubsub/client/proto/helloworld.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // source: helloworld.proto 3 | 4 | package proto 5 | 6 | import ( 7 | context "context" 8 | fmt "fmt" 9 | proto "github.com/golang/protobuf/proto" 10 | grpc "google.golang.org/grpc" 11 | codes "google.golang.org/grpc/codes" 12 | status "google.golang.org/grpc/status" 13 | math "math" 14 | ) 15 | 16 | // Reference imports to suppress errors if they are not otherwise used. 17 | var _ = proto.Marshal 18 | var _ = fmt.Errorf 19 | var _ = math.Inf 20 | 21 | // This is a compile-time assertion to ensure that this generated file 22 | // is compatible with the proto package it is being compiled against. 23 | // A compilation error at this line likely means your copy of the 24 | // proto package needs to be updated. 25 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 26 | 27 | type String struct { 28 | Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` 29 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 30 | XXX_unrecognized []byte `json:"-"` 31 | XXX_sizecache int32 `json:"-"` 32 | } 33 | 34 | func (m *String) Reset() { *m = String{} } 35 | func (m *String) String() string { return proto.CompactTextString(m) } 36 | func (*String) ProtoMessage() {} 37 | func (*String) Descriptor() ([]byte, []int) { 38 | return fileDescriptor_17b8c58d586b62f2, []int{0} 39 | } 40 | 41 | func (m *String) XXX_Unmarshal(b []byte) error { 42 | return xxx_messageInfo_String.Unmarshal(m, b) 43 | } 44 | func (m *String) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 45 | return xxx_messageInfo_String.Marshal(b, m, deterministic) 46 | } 47 | func (m *String) XXX_Merge(src proto.Message) { 48 | xxx_messageInfo_String.Merge(m, src) 49 | } 50 | func (m *String) XXX_Size() int { 51 | return xxx_messageInfo_String.Size(m) 52 | } 53 | func (m *String) XXX_DiscardUnknown() { 54 | xxx_messageInfo_String.DiscardUnknown(m) 55 | } 56 | 57 | var xxx_messageInfo_String proto.InternalMessageInfo 58 | 59 | func (m *String) GetValue() string { 60 | if m != nil { 61 | return m.Value 62 | } 63 | return "" 64 | } 65 | 66 | func init() { 67 | proto.RegisterType((*String)(nil), "proto.String") 68 | } 69 | 70 | func init() { proto.RegisterFile("helloworld.proto", fileDescriptor_17b8c58d586b62f2) } 71 | 72 | var fileDescriptor_17b8c58d586b62f2 = []byte{ 73 | // 148 bytes of a gzipped FileDescriptorProto 74 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xc8, 0x48, 0xcd, 0xc9, 75 | 0xc9, 0x2f, 0xcf, 0x2f, 0xca, 0x49, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x05, 0x53, 76 | 0x4a, 0x72, 0x5c, 0x6c, 0xc1, 0x25, 0x45, 0x99, 0x79, 0xe9, 0x42, 0x22, 0x5c, 0xac, 0x65, 0x89, 77 | 0x39, 0xa5, 0xa9, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0x10, 0x8e, 0xd1, 0x74, 0x46, 0x2e, 78 | 0xde, 0x80, 0xd2, 0xa4, 0xe2, 0xd2, 0xa4, 0xe0, 0xd4, 0xa2, 0xb2, 0xcc, 0xe4, 0x54, 0x21, 0x75, 79 | 0x2e, 0xf6, 0x80, 0xd2, 0xa4, 0x9c, 0xcc, 0xe2, 0x0c, 0x21, 0x5e, 0x88, 0x59, 0x7a, 0x10, 0x13, 80 | 0xa4, 0x50, 0xb9, 0x42, 0x06, 0x5c, 0x7c, 0xc1, 0xa5, 0x49, 0xc5, 0xc9, 0x45, 0x99, 0x49, 0xa9, 81 | 0x21, 0xf9, 0x05, 0x99, 0xc9, 0xf8, 0xd5, 0x1b, 0x30, 0x0a, 0x69, 0x73, 0x71, 0xc2, 0x75, 0x10, 82 | 0x52, 0x9c, 0xc4, 0x06, 0xe6, 0x1b, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x30, 0xe5, 0x07, 0xe2, 83 | 0xdb, 0x00, 0x00, 0x00, 84 | } 85 | 86 | // Reference imports to suppress errors if they are not otherwise used. 87 | var _ context.Context 88 | var _ grpc.ClientConn 89 | 90 | // This is a compile-time assertion to ensure that this generated file 91 | // is compatible with the grpc package it is being compiled against. 92 | const _ = grpc.SupportPackageIsVersion4 93 | 94 | // PubsubServiceClient is the client API for PubsubService service. 95 | // 96 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. 97 | type PubsubServiceClient interface { 98 | Publish(ctx context.Context, in *String, opts ...grpc.CallOption) (*String, error) 99 | SubscribeTopic(ctx context.Context, in *String, opts ...grpc.CallOption) (PubsubService_SubscribeTopicClient, error) 100 | Subscribe(ctx context.Context, in *String, opts ...grpc.CallOption) (PubsubService_SubscribeClient, error) 101 | } 102 | 103 | type pubsubServiceClient struct { 104 | cc *grpc.ClientConn 105 | } 106 | 107 | func NewPubsubServiceClient(cc *grpc.ClientConn) PubsubServiceClient { 108 | return &pubsubServiceClient{cc} 109 | } 110 | 111 | func (c *pubsubServiceClient) Publish(ctx context.Context, in *String, opts ...grpc.CallOption) (*String, error) { 112 | out := new(String) 113 | err := c.cc.Invoke(ctx, "/proto.PubsubService/Publish", in, out, opts...) 114 | if err != nil { 115 | return nil, err 116 | } 117 | return out, nil 118 | } 119 | 120 | func (c *pubsubServiceClient) SubscribeTopic(ctx context.Context, in *String, opts ...grpc.CallOption) (PubsubService_SubscribeTopicClient, error) { 121 | stream, err := c.cc.NewStream(ctx, &_PubsubService_serviceDesc.Streams[0], "/proto.PubsubService/SubscribeTopic", opts...) 122 | if err != nil { 123 | return nil, err 124 | } 125 | x := &pubsubServiceSubscribeTopicClient{stream} 126 | if err := x.ClientStream.SendMsg(in); err != nil { 127 | return nil, err 128 | } 129 | if err := x.ClientStream.CloseSend(); err != nil { 130 | return nil, err 131 | } 132 | return x, nil 133 | } 134 | 135 | type PubsubService_SubscribeTopicClient interface { 136 | Recv() (*String, error) 137 | grpc.ClientStream 138 | } 139 | 140 | type pubsubServiceSubscribeTopicClient struct { 141 | grpc.ClientStream 142 | } 143 | 144 | func (x *pubsubServiceSubscribeTopicClient) Recv() (*String, error) { 145 | m := new(String) 146 | if err := x.ClientStream.RecvMsg(m); err != nil { 147 | return nil, err 148 | } 149 | return m, nil 150 | } 151 | 152 | func (c *pubsubServiceClient) Subscribe(ctx context.Context, in *String, opts ...grpc.CallOption) (PubsubService_SubscribeClient, error) { 153 | stream, err := c.cc.NewStream(ctx, &_PubsubService_serviceDesc.Streams[1], "/proto.PubsubService/Subscribe", opts...) 154 | if err != nil { 155 | return nil, err 156 | } 157 | x := &pubsubServiceSubscribeClient{stream} 158 | if err := x.ClientStream.SendMsg(in); err != nil { 159 | return nil, err 160 | } 161 | if err := x.ClientStream.CloseSend(); err != nil { 162 | return nil, err 163 | } 164 | return x, nil 165 | } 166 | 167 | type PubsubService_SubscribeClient interface { 168 | Recv() (*String, error) 169 | grpc.ClientStream 170 | } 171 | 172 | type pubsubServiceSubscribeClient struct { 173 | grpc.ClientStream 174 | } 175 | 176 | func (x *pubsubServiceSubscribeClient) Recv() (*String, error) { 177 | m := new(String) 178 | if err := x.ClientStream.RecvMsg(m); err != nil { 179 | return nil, err 180 | } 181 | return m, nil 182 | } 183 | 184 | // PubsubServiceServer is the server API for PubsubService service. 185 | type PubsubServiceServer interface { 186 | Publish(context.Context, *String) (*String, error) 187 | SubscribeTopic(*String, PubsubService_SubscribeTopicServer) error 188 | Subscribe(*String, PubsubService_SubscribeServer) error 189 | } 190 | 191 | // UnimplementedPubsubServiceServer can be embedded to have forward compatible implementations. 192 | type UnimplementedPubsubServiceServer struct { 193 | } 194 | 195 | func (*UnimplementedPubsubServiceServer) Publish(ctx context.Context, req *String) (*String, error) { 196 | return nil, status.Errorf(codes.Unimplemented, "method Publish not implemented") 197 | } 198 | func (*UnimplementedPubsubServiceServer) SubscribeTopic(req *String, srv PubsubService_SubscribeTopicServer) error { 199 | return status.Errorf(codes.Unimplemented, "method SubscribeTopic not implemented") 200 | } 201 | func (*UnimplementedPubsubServiceServer) Subscribe(req *String, srv PubsubService_SubscribeServer) error { 202 | return status.Errorf(codes.Unimplemented, "method Subscribe not implemented") 203 | } 204 | 205 | func RegisterPubsubServiceServer(s *grpc.Server, srv PubsubServiceServer) { 206 | s.RegisterService(&_PubsubService_serviceDesc, srv) 207 | } 208 | 209 | func _PubsubService_Publish_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 210 | in := new(String) 211 | if err := dec(in); err != nil { 212 | return nil, err 213 | } 214 | if interceptor == nil { 215 | return srv.(PubsubServiceServer).Publish(ctx, in) 216 | } 217 | info := &grpc.UnaryServerInfo{ 218 | Server: srv, 219 | FullMethod: "/proto.PubsubService/Publish", 220 | } 221 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 222 | return srv.(PubsubServiceServer).Publish(ctx, req.(*String)) 223 | } 224 | return interceptor(ctx, in, info, handler) 225 | } 226 | 227 | func _PubsubService_SubscribeTopic_Handler(srv interface{}, stream grpc.ServerStream) error { 228 | m := new(String) 229 | if err := stream.RecvMsg(m); err != nil { 230 | return err 231 | } 232 | return srv.(PubsubServiceServer).SubscribeTopic(m, &pubsubServiceSubscribeTopicServer{stream}) 233 | } 234 | 235 | type PubsubService_SubscribeTopicServer interface { 236 | Send(*String) error 237 | grpc.ServerStream 238 | } 239 | 240 | type pubsubServiceSubscribeTopicServer struct { 241 | grpc.ServerStream 242 | } 243 | 244 | func (x *pubsubServiceSubscribeTopicServer) Send(m *String) error { 245 | return x.ServerStream.SendMsg(m) 246 | } 247 | 248 | func _PubsubService_Subscribe_Handler(srv interface{}, stream grpc.ServerStream) error { 249 | m := new(String) 250 | if err := stream.RecvMsg(m); err != nil { 251 | return err 252 | } 253 | return srv.(PubsubServiceServer).Subscribe(m, &pubsubServiceSubscribeServer{stream}) 254 | } 255 | 256 | type PubsubService_SubscribeServer interface { 257 | Send(*String) error 258 | grpc.ServerStream 259 | } 260 | 261 | type pubsubServiceSubscribeServer struct { 262 | grpc.ServerStream 263 | } 264 | 265 | func (x *pubsubServiceSubscribeServer) Send(m *String) error { 266 | return x.ServerStream.SendMsg(m) 267 | } 268 | 269 | var _PubsubService_serviceDesc = grpc.ServiceDesc{ 270 | ServiceName: "proto.PubsubService", 271 | HandlerType: (*PubsubServiceServer)(nil), 272 | Methods: []grpc.MethodDesc{ 273 | { 274 | MethodName: "Publish", 275 | Handler: _PubsubService_Publish_Handler, 276 | }, 277 | }, 278 | Streams: []grpc.StreamDesc{ 279 | { 280 | StreamName: "SubscribeTopic", 281 | Handler: _PubsubService_SubscribeTopic_Handler, 282 | ServerStreams: true, 283 | }, 284 | { 285 | StreamName: "Subscribe", 286 | Handler: _PubsubService_Subscribe_Handler, 287 | ServerStreams: true, 288 | }, 289 | }, 290 | Metadata: "helloworld.proto", 291 | } 292 | -------------------------------------------------------------------------------- /grpc-example/pubsub/client/pub_client.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "client/proto" 5 | "context" 6 | "log" 7 | 8 | "google.golang.org/grpc" 9 | ) 10 | 11 | func main() { 12 | conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure()) 13 | if err != nil { 14 | log.Fatal(err) 15 | } 16 | defer conn.Close() 17 | client := proto.NewPubsubServiceClient(conn) 18 | 19 | _, err = client.Publish( 20 | context.Background(), &proto.String{Value: "golang: hello Go"}, 21 | ) 22 | if err != nil { 23 | log.Fatal(err) 24 | } 25 | 26 | _, err = client.Publish( 27 | context.Background(), &proto.String{Value: "docker: hello Docker"}, 28 | ) 29 | if nil != err { 30 | log.Fatal(err) 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /grpc-example/pubsub/client/sub_client.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "client/proto" 5 | "context" 6 | "fmt" 7 | "io" 8 | "log" 9 | 10 | "google.golang.org/grpc" 11 | ) 12 | 13 | func main() { 14 | conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure()) 15 | if err != nil { 16 | log.Fatal(err) 17 | } 18 | defer conn.Close() 19 | 20 | client := proto.NewPubsubServiceClient(conn) 21 | stream, err := client.Subscribe( 22 | context.Background(), &proto.String{Value: "golang:"}, 23 | ) 24 | if nil != err { 25 | log.Fatal(err) 26 | } 27 | 28 | go func() { 29 | for { 30 | reply, err := stream.Recv() 31 | if nil != err { 32 | if io.EOF == err { 33 | break 34 | } 35 | log.Fatal(err) 36 | } 37 | fmt.Println("sub1: ", reply.GetValue()) 38 | } 39 | }() 40 | 41 | streamTopic, err := client.SubscribeTopic( 42 | context.Background(), &proto.String{Value: "golang:"}, 43 | ) 44 | if nil != err { 45 | log.Fatal(err) 46 | } 47 | 48 | go func() { 49 | for { 50 | reply, err := streamTopic.Recv() 51 | if nil != err { 52 | if io.EOF == err { 53 | break 54 | } 55 | log.Fatal(err) 56 | } 57 | fmt.Println("subTopic: ", reply.GetValue()) 58 | } 59 | }() 60 | 61 | <-make(chan bool) 62 | } 63 | -------------------------------------------------------------------------------- /grpc-example/pubsub/server/go.mod: -------------------------------------------------------------------------------- 1 | module server 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/golang/protobuf v1.5.2 7 | github.com/moby/moby v20.10.9+incompatible // indirect 8 | google.golang.org/grpc v1.41.0 9 | google.golang.org/protobuf v1.26.0 // indirect 10 | ) 11 | -------------------------------------------------------------------------------- /grpc-example/pubsub/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "log" 7 | "net" 8 | "server/proto" 9 | "strings" 10 | "time" 11 | 12 | "github.com/moby/moby/pkg/pubsub" 13 | "google.golang.org/grpc" 14 | "google.golang.org/grpc/reflection" 15 | ) 16 | 17 | type PubsubService struct { 18 | pub *pubsub.Publisher 19 | } 20 | 21 | func (p *PubsubService) Publish(ctx context.Context, arg *proto.String) (*proto.String, error) { 22 | p.pub.Publish(arg.GetValue()) 23 | return &proto.String{}, nil 24 | } 25 | 26 | func (p *PubsubService) SubscribeTopic(arg *proto.String, stream proto.PubsubService_SubscribeTopicServer) error { 27 | ch := p.pub.SubscribeTopic(func(v interface{}) bool { 28 | if key, ok := v.(string); ok { 29 | if strings.HasPrefix(key, arg.GetValue()) { 30 | return true 31 | } 32 | } 33 | return false 34 | }) 35 | 36 | for v := range ch { 37 | if err := stream.Send(&proto.String{Value: v.(string)}); nil != err { 38 | return err 39 | } 40 | } 41 | return nil 42 | } 43 | 44 | func (p *PubsubService) Subscribe(arg *proto.String, stream proto.PubsubService_SubscribeServer) error { 45 | ch := p.pub.Subscribe() 46 | 47 | for v := range ch { 48 | if err := stream.Send(&proto.String{Value: v.(string)}); nil != err { 49 | return err 50 | } 51 | } 52 | return nil 53 | } 54 | 55 | func NewPubsubService() *PubsubService { 56 | return &PubsubService{pub: pubsub.NewPublisher(100*time.Millisecond, 10)} 57 | } 58 | 59 | func main() { 60 | lis, err := net.Listen("tcp", ":50051") 61 | if err != nil { 62 | log.Fatalf("failed to listen: %v", err) 63 | } 64 | 65 | // 简单调用 66 | server := grpc.NewServer() 67 | // 注册 grpcurl 所需的 reflection 服务 68 | reflection.Register(server) 69 | // 注册业务服务 70 | proto.RegisterPubsubServiceServer(server, NewPubsubService()) 71 | 72 | fmt.Println("grpc server start ...") 73 | if err := server.Serve(lis); err != nil { 74 | log.Fatalf("failed to serve: %v", err) 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /grpc-example/pubsub/server/proto/gen_proto.sh: -------------------------------------------------------------------------------- 1 | 2 | protoc --go_out=plugins=grpc:. *.proto 3 | -------------------------------------------------------------------------------- /grpc-example/pubsub/server/proto/helloworld.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // source: helloworld.proto 3 | 4 | package proto 5 | 6 | import ( 7 | context "context" 8 | fmt "fmt" 9 | proto "github.com/golang/protobuf/proto" 10 | grpc "google.golang.org/grpc" 11 | codes "google.golang.org/grpc/codes" 12 | status "google.golang.org/grpc/status" 13 | math "math" 14 | ) 15 | 16 | // Reference imports to suppress errors if they are not otherwise used. 17 | var _ = proto.Marshal 18 | var _ = fmt.Errorf 19 | var _ = math.Inf 20 | 21 | // This is a compile-time assertion to ensure that this generated file 22 | // is compatible with the proto package it is being compiled against. 23 | // A compilation error at this line likely means your copy of the 24 | // proto package needs to be updated. 25 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 26 | 27 | type String struct { 28 | Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` 29 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 30 | XXX_unrecognized []byte `json:"-"` 31 | XXX_sizecache int32 `json:"-"` 32 | } 33 | 34 | func (m *String) Reset() { *m = String{} } 35 | func (m *String) String() string { return proto.CompactTextString(m) } 36 | func (*String) ProtoMessage() {} 37 | func (*String) Descriptor() ([]byte, []int) { 38 | return fileDescriptor_17b8c58d586b62f2, []int{0} 39 | } 40 | 41 | func (m *String) XXX_Unmarshal(b []byte) error { 42 | return xxx_messageInfo_String.Unmarshal(m, b) 43 | } 44 | func (m *String) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 45 | return xxx_messageInfo_String.Marshal(b, m, deterministic) 46 | } 47 | func (m *String) XXX_Merge(src proto.Message) { 48 | xxx_messageInfo_String.Merge(m, src) 49 | } 50 | func (m *String) XXX_Size() int { 51 | return xxx_messageInfo_String.Size(m) 52 | } 53 | func (m *String) XXX_DiscardUnknown() { 54 | xxx_messageInfo_String.DiscardUnknown(m) 55 | } 56 | 57 | var xxx_messageInfo_String proto.InternalMessageInfo 58 | 59 | func (m *String) GetValue() string { 60 | if m != nil { 61 | return m.Value 62 | } 63 | return "" 64 | } 65 | 66 | func init() { 67 | proto.RegisterType((*String)(nil), "proto.String") 68 | } 69 | 70 | func init() { proto.RegisterFile("helloworld.proto", fileDescriptor_17b8c58d586b62f2) } 71 | 72 | var fileDescriptor_17b8c58d586b62f2 = []byte{ 73 | // 148 bytes of a gzipped FileDescriptorProto 74 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xc8, 0x48, 0xcd, 0xc9, 75 | 0xc9, 0x2f, 0xcf, 0x2f, 0xca, 0x49, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x05, 0x53, 76 | 0x4a, 0x72, 0x5c, 0x6c, 0xc1, 0x25, 0x45, 0x99, 0x79, 0xe9, 0x42, 0x22, 0x5c, 0xac, 0x65, 0x89, 77 | 0x39, 0xa5, 0xa9, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0x10, 0x8e, 0xd1, 0x74, 0x46, 0x2e, 78 | 0xde, 0x80, 0xd2, 0xa4, 0xe2, 0xd2, 0xa4, 0xe0, 0xd4, 0xa2, 0xb2, 0xcc, 0xe4, 0x54, 0x21, 0x75, 79 | 0x2e, 0xf6, 0x80, 0xd2, 0xa4, 0x9c, 0xcc, 0xe2, 0x0c, 0x21, 0x5e, 0x88, 0x59, 0x7a, 0x10, 0x13, 80 | 0xa4, 0x50, 0xb9, 0x42, 0x06, 0x5c, 0x7c, 0xc1, 0xa5, 0x49, 0xc5, 0xc9, 0x45, 0x99, 0x49, 0xa9, 81 | 0x21, 0xf9, 0x05, 0x99, 0xc9, 0xf8, 0xd5, 0x1b, 0x30, 0x0a, 0x69, 0x73, 0x71, 0xc2, 0x75, 0x10, 82 | 0x52, 0x9c, 0xc4, 0x06, 0xe6, 0x1b, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x30, 0xe5, 0x07, 0xe2, 83 | 0xdb, 0x00, 0x00, 0x00, 84 | } 85 | 86 | // Reference imports to suppress errors if they are not otherwise used. 87 | var _ context.Context 88 | var _ grpc.ClientConn 89 | 90 | // This is a compile-time assertion to ensure that this generated file 91 | // is compatible with the grpc package it is being compiled against. 92 | const _ = grpc.SupportPackageIsVersion4 93 | 94 | // PubsubServiceClient is the client API for PubsubService service. 95 | // 96 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. 97 | type PubsubServiceClient interface { 98 | Publish(ctx context.Context, in *String, opts ...grpc.CallOption) (*String, error) 99 | SubscribeTopic(ctx context.Context, in *String, opts ...grpc.CallOption) (PubsubService_SubscribeTopicClient, error) 100 | Subscribe(ctx context.Context, in *String, opts ...grpc.CallOption) (PubsubService_SubscribeClient, error) 101 | } 102 | 103 | type pubsubServiceClient struct { 104 | cc *grpc.ClientConn 105 | } 106 | 107 | func NewPubsubServiceClient(cc *grpc.ClientConn) PubsubServiceClient { 108 | return &pubsubServiceClient{cc} 109 | } 110 | 111 | func (c *pubsubServiceClient) Publish(ctx context.Context, in *String, opts ...grpc.CallOption) (*String, error) { 112 | out := new(String) 113 | err := c.cc.Invoke(ctx, "/proto.PubsubService/Publish", in, out, opts...) 114 | if err != nil { 115 | return nil, err 116 | } 117 | return out, nil 118 | } 119 | 120 | func (c *pubsubServiceClient) SubscribeTopic(ctx context.Context, in *String, opts ...grpc.CallOption) (PubsubService_SubscribeTopicClient, error) { 121 | stream, err := c.cc.NewStream(ctx, &_PubsubService_serviceDesc.Streams[0], "/proto.PubsubService/SubscribeTopic", opts...) 122 | if err != nil { 123 | return nil, err 124 | } 125 | x := &pubsubServiceSubscribeTopicClient{stream} 126 | if err := x.ClientStream.SendMsg(in); err != nil { 127 | return nil, err 128 | } 129 | if err := x.ClientStream.CloseSend(); err != nil { 130 | return nil, err 131 | } 132 | return x, nil 133 | } 134 | 135 | type PubsubService_SubscribeTopicClient interface { 136 | Recv() (*String, error) 137 | grpc.ClientStream 138 | } 139 | 140 | type pubsubServiceSubscribeTopicClient struct { 141 | grpc.ClientStream 142 | } 143 | 144 | func (x *pubsubServiceSubscribeTopicClient) Recv() (*String, error) { 145 | m := new(String) 146 | if err := x.ClientStream.RecvMsg(m); err != nil { 147 | return nil, err 148 | } 149 | return m, nil 150 | } 151 | 152 | func (c *pubsubServiceClient) Subscribe(ctx context.Context, in *String, opts ...grpc.CallOption) (PubsubService_SubscribeClient, error) { 153 | stream, err := c.cc.NewStream(ctx, &_PubsubService_serviceDesc.Streams[1], "/proto.PubsubService/Subscribe", opts...) 154 | if err != nil { 155 | return nil, err 156 | } 157 | x := &pubsubServiceSubscribeClient{stream} 158 | if err := x.ClientStream.SendMsg(in); err != nil { 159 | return nil, err 160 | } 161 | if err := x.ClientStream.CloseSend(); err != nil { 162 | return nil, err 163 | } 164 | return x, nil 165 | } 166 | 167 | type PubsubService_SubscribeClient interface { 168 | Recv() (*String, error) 169 | grpc.ClientStream 170 | } 171 | 172 | type pubsubServiceSubscribeClient struct { 173 | grpc.ClientStream 174 | } 175 | 176 | func (x *pubsubServiceSubscribeClient) Recv() (*String, error) { 177 | m := new(String) 178 | if err := x.ClientStream.RecvMsg(m); err != nil { 179 | return nil, err 180 | } 181 | return m, nil 182 | } 183 | 184 | // PubsubServiceServer is the server API for PubsubService service. 185 | type PubsubServiceServer interface { 186 | Publish(context.Context, *String) (*String, error) 187 | SubscribeTopic(*String, PubsubService_SubscribeTopicServer) error 188 | Subscribe(*String, PubsubService_SubscribeServer) error 189 | } 190 | 191 | // UnimplementedPubsubServiceServer can be embedded to have forward compatible implementations. 192 | type UnimplementedPubsubServiceServer struct { 193 | } 194 | 195 | func (*UnimplementedPubsubServiceServer) Publish(ctx context.Context, req *String) (*String, error) { 196 | return nil, status.Errorf(codes.Unimplemented, "method Publish not implemented") 197 | } 198 | func (*UnimplementedPubsubServiceServer) SubscribeTopic(req *String, srv PubsubService_SubscribeTopicServer) error { 199 | return status.Errorf(codes.Unimplemented, "method SubscribeTopic not implemented") 200 | } 201 | func (*UnimplementedPubsubServiceServer) Subscribe(req *String, srv PubsubService_SubscribeServer) error { 202 | return status.Errorf(codes.Unimplemented, "method Subscribe not implemented") 203 | } 204 | 205 | func RegisterPubsubServiceServer(s *grpc.Server, srv PubsubServiceServer) { 206 | s.RegisterService(&_PubsubService_serviceDesc, srv) 207 | } 208 | 209 | func _PubsubService_Publish_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 210 | in := new(String) 211 | if err := dec(in); err != nil { 212 | return nil, err 213 | } 214 | if interceptor == nil { 215 | return srv.(PubsubServiceServer).Publish(ctx, in) 216 | } 217 | info := &grpc.UnaryServerInfo{ 218 | Server: srv, 219 | FullMethod: "/proto.PubsubService/Publish", 220 | } 221 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 222 | return srv.(PubsubServiceServer).Publish(ctx, req.(*String)) 223 | } 224 | return interceptor(ctx, in, info, handler) 225 | } 226 | 227 | func _PubsubService_SubscribeTopic_Handler(srv interface{}, stream grpc.ServerStream) error { 228 | m := new(String) 229 | if err := stream.RecvMsg(m); err != nil { 230 | return err 231 | } 232 | return srv.(PubsubServiceServer).SubscribeTopic(m, &pubsubServiceSubscribeTopicServer{stream}) 233 | } 234 | 235 | type PubsubService_SubscribeTopicServer interface { 236 | Send(*String) error 237 | grpc.ServerStream 238 | } 239 | 240 | type pubsubServiceSubscribeTopicServer struct { 241 | grpc.ServerStream 242 | } 243 | 244 | func (x *pubsubServiceSubscribeTopicServer) Send(m *String) error { 245 | return x.ServerStream.SendMsg(m) 246 | } 247 | 248 | func _PubsubService_Subscribe_Handler(srv interface{}, stream grpc.ServerStream) error { 249 | m := new(String) 250 | if err := stream.RecvMsg(m); err != nil { 251 | return err 252 | } 253 | return srv.(PubsubServiceServer).Subscribe(m, &pubsubServiceSubscribeServer{stream}) 254 | } 255 | 256 | type PubsubService_SubscribeServer interface { 257 | Send(*String) error 258 | grpc.ServerStream 259 | } 260 | 261 | type pubsubServiceSubscribeServer struct { 262 | grpc.ServerStream 263 | } 264 | 265 | func (x *pubsubServiceSubscribeServer) Send(m *String) error { 266 | return x.ServerStream.SendMsg(m) 267 | } 268 | 269 | var _PubsubService_serviceDesc = grpc.ServiceDesc{ 270 | ServiceName: "proto.PubsubService", 271 | HandlerType: (*PubsubServiceServer)(nil), 272 | Methods: []grpc.MethodDesc{ 273 | { 274 | MethodName: "Publish", 275 | Handler: _PubsubService_Publish_Handler, 276 | }, 277 | }, 278 | Streams: []grpc.StreamDesc{ 279 | { 280 | StreamName: "SubscribeTopic", 281 | Handler: _PubsubService_SubscribeTopic_Handler, 282 | ServerStreams: true, 283 | }, 284 | { 285 | StreamName: "Subscribe", 286 | Handler: _PubsubService_Subscribe_Handler, 287 | ServerStreams: true, 288 | }, 289 | }, 290 | Metadata: "helloworld.proto", 291 | } 292 | -------------------------------------------------------------------------------- /grpc-example/pubsub/server/proto/helloworld.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package proto; 4 | 5 | message String { 6 | string value = 1; 7 | } 8 | 9 | service PubsubService { 10 | rpc Publish (String) returns (String); 11 | rpc SubscribeTopic (String) returns (stream String); 12 | rpc Subscribe (String) returns (stream String); 13 | } 14 | -------------------------------------------------------------------------------- /grpc-example/pubsub/server/pubsub.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | "time" 7 | 8 | "github.com/moby/moby/pkg/pubsub" 9 | ) 10 | 11 | func main() { 12 | p := pubsub.NewPublisher(100*time.Millisecond, 10) 13 | 14 | golang := p.SubscribeTopic(func(v interface{}) bool { 15 | if key, ok := v.(string); ok { 16 | if strings.HasPrefix(key, "golang:") { 17 | return true 18 | } 19 | } 20 | return false 21 | }) 22 | docker := p.SubscribeTopic(func(v interface{}) bool { 23 | if key, ok := v.(string); ok { 24 | if strings.HasPrefix(key, "docker:") { 25 | return true 26 | } 27 | } 28 | return false 29 | }) 30 | 31 | go p.Publish("hi") 32 | go p.Publish("golang: https://golang.org") 33 | go p.Publish("docker: https://www.docker.com/") 34 | time.Sleep(1) 35 | 36 | go func() { 37 | fmt.Println("golang topic:", <-golang) 38 | }() 39 | go func() { 40 | fmt.Println("docker topic:", <-docker) 41 | }() 42 | 43 | <-make(chan bool) 44 | } 45 | -------------------------------------------------------------------------------- /grpc-example/py-client/helloworld.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package proto; 4 | 5 | // The greeting service definition. 6 | service Greeter { 7 | // Sends a greeting 8 | rpc SayHello (HelloRequest) returns (HelloReply) {} 9 | // Sends stream message 10 | rpc SayHelloStream (stream HelloRequest) returns (stream HelloReply) {} 11 | } 12 | 13 | // The request message containing the user's name. 14 | message HelloRequest { 15 | string name = 1; 16 | } 17 | 18 | // The response message containing the greetings 19 | message HelloReply { 20 | string message = 1; 21 | } 22 | -------------------------------------------------------------------------------- /grpc-example/py-client/helloworld_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: helloworld.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf import descriptor as _descriptor 6 | from google.protobuf import message as _message 7 | from google.protobuf import reflection as _reflection 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | 15 | 16 | DESCRIPTOR = _descriptor.FileDescriptor( 17 | name='helloworld.proto', 18 | package='proto', 19 | syntax='proto3', 20 | serialized_options=None, 21 | create_key=_descriptor._internal_create_key, 22 | serialized_pb=b'\n\x10helloworld.proto\x12\x05proto\"\x1c\n\x0cHelloRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1d\n\nHelloReply\x12\x0f\n\x07message\x18\x01 \x01(\t2\x7f\n\x07Greeter\x12\x34\n\x08SayHello\x12\x13.proto.HelloRequest\x1a\x11.proto.HelloReply\"\x00\x12>\n\x0eSayHelloStream\x12\x13.proto.HelloRequest\x1a\x11.proto.HelloReply\"\x00(\x01\x30\x01\x62\x06proto3' 23 | ) 24 | 25 | 26 | 27 | 28 | _HELLOREQUEST = _descriptor.Descriptor( 29 | name='HelloRequest', 30 | full_name='proto.HelloRequest', 31 | filename=None, 32 | file=DESCRIPTOR, 33 | containing_type=None, 34 | create_key=_descriptor._internal_create_key, 35 | fields=[ 36 | _descriptor.FieldDescriptor( 37 | name='name', full_name='proto.HelloRequest.name', index=0, 38 | number=1, type=9, cpp_type=9, label=1, 39 | has_default_value=False, default_value=b"".decode('utf-8'), 40 | message_type=None, enum_type=None, containing_type=None, 41 | is_extension=False, extension_scope=None, 42 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 43 | ], 44 | extensions=[ 45 | ], 46 | nested_types=[], 47 | enum_types=[ 48 | ], 49 | serialized_options=None, 50 | is_extendable=False, 51 | syntax='proto3', 52 | extension_ranges=[], 53 | oneofs=[ 54 | ], 55 | serialized_start=27, 56 | serialized_end=55, 57 | ) 58 | 59 | 60 | _HELLOREPLY = _descriptor.Descriptor( 61 | name='HelloReply', 62 | full_name='proto.HelloReply', 63 | filename=None, 64 | file=DESCRIPTOR, 65 | containing_type=None, 66 | create_key=_descriptor._internal_create_key, 67 | fields=[ 68 | _descriptor.FieldDescriptor( 69 | name='message', full_name='proto.HelloReply.message', index=0, 70 | number=1, type=9, cpp_type=9, label=1, 71 | has_default_value=False, default_value=b"".decode('utf-8'), 72 | message_type=None, enum_type=None, containing_type=None, 73 | is_extension=False, extension_scope=None, 74 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 75 | ], 76 | extensions=[ 77 | ], 78 | nested_types=[], 79 | enum_types=[ 80 | ], 81 | serialized_options=None, 82 | is_extendable=False, 83 | syntax='proto3', 84 | extension_ranges=[], 85 | oneofs=[ 86 | ], 87 | serialized_start=57, 88 | serialized_end=86, 89 | ) 90 | 91 | DESCRIPTOR.message_types_by_name['HelloRequest'] = _HELLOREQUEST 92 | DESCRIPTOR.message_types_by_name['HelloReply'] = _HELLOREPLY 93 | _sym_db.RegisterFileDescriptor(DESCRIPTOR) 94 | 95 | HelloRequest = _reflection.GeneratedProtocolMessageType('HelloRequest', (_message.Message,), { 96 | 'DESCRIPTOR' : _HELLOREQUEST, 97 | '__module__' : 'helloworld_pb2' 98 | # @@protoc_insertion_point(class_scope:proto.HelloRequest) 99 | }) 100 | _sym_db.RegisterMessage(HelloRequest) 101 | 102 | HelloReply = _reflection.GeneratedProtocolMessageType('HelloReply', (_message.Message,), { 103 | 'DESCRIPTOR' : _HELLOREPLY, 104 | '__module__' : 'helloworld_pb2' 105 | # @@protoc_insertion_point(class_scope:proto.HelloReply) 106 | }) 107 | _sym_db.RegisterMessage(HelloReply) 108 | 109 | 110 | 111 | _GREETER = _descriptor.ServiceDescriptor( 112 | name='Greeter', 113 | full_name='proto.Greeter', 114 | file=DESCRIPTOR, 115 | index=0, 116 | serialized_options=None, 117 | create_key=_descriptor._internal_create_key, 118 | serialized_start=88, 119 | serialized_end=215, 120 | methods=[ 121 | _descriptor.MethodDescriptor( 122 | name='SayHello', 123 | full_name='proto.Greeter.SayHello', 124 | index=0, 125 | containing_service=None, 126 | input_type=_HELLOREQUEST, 127 | output_type=_HELLOREPLY, 128 | serialized_options=None, 129 | create_key=_descriptor._internal_create_key, 130 | ), 131 | _descriptor.MethodDescriptor( 132 | name='SayHelloStream', 133 | full_name='proto.Greeter.SayHelloStream', 134 | index=1, 135 | containing_service=None, 136 | input_type=_HELLOREQUEST, 137 | output_type=_HELLOREPLY, 138 | serialized_options=None, 139 | create_key=_descriptor._internal_create_key, 140 | ), 141 | ]) 142 | _sym_db.RegisterServiceDescriptor(_GREETER) 143 | 144 | DESCRIPTOR.services_by_name['Greeter'] = _GREETER 145 | 146 | # @@protoc_insertion_point(module_scope) 147 | -------------------------------------------------------------------------------- /grpc-example/py-client/helloworld_pb2_grpc.py: -------------------------------------------------------------------------------- 1 | # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! 2 | """Client and server classes corresponding to protobuf-defined services.""" 3 | import grpc 4 | 5 | import helloworld_pb2 as helloworld__pb2 6 | 7 | 8 | class GreeterStub(object): 9 | """The greeting service definition. 10 | """ 11 | 12 | def __init__(self, channel): 13 | """Constructor. 14 | 15 | Args: 16 | channel: A grpc.Channel. 17 | """ 18 | self.SayHello = channel.unary_unary( 19 | '/proto.Greeter/SayHello', 20 | request_serializer=helloworld__pb2.HelloRequest.SerializeToString, 21 | response_deserializer=helloworld__pb2.HelloReply.FromString, 22 | ) 23 | self.SayHelloStream = channel.stream_stream( 24 | '/proto.Greeter/SayHelloStream', 25 | request_serializer=helloworld__pb2.HelloRequest.SerializeToString, 26 | response_deserializer=helloworld__pb2.HelloReply.FromString, 27 | ) 28 | 29 | 30 | class GreeterServicer(object): 31 | """The greeting service definition. 32 | """ 33 | 34 | def SayHello(self, request, context): 35 | """Sends a greeting 36 | """ 37 | context.set_code(grpc.StatusCode.UNIMPLEMENTED) 38 | context.set_details('Method not implemented!') 39 | raise NotImplementedError('Method not implemented!') 40 | 41 | def SayHelloStream(self, request_iterator, context): 42 | """Sends stream message 43 | """ 44 | context.set_code(grpc.StatusCode.UNIMPLEMENTED) 45 | context.set_details('Method not implemented!') 46 | raise NotImplementedError('Method not implemented!') 47 | 48 | 49 | def add_GreeterServicer_to_server(servicer, server): 50 | rpc_method_handlers = { 51 | 'SayHello': grpc.unary_unary_rpc_method_handler( 52 | servicer.SayHello, 53 | request_deserializer=helloworld__pb2.HelloRequest.FromString, 54 | response_serializer=helloworld__pb2.HelloReply.SerializeToString, 55 | ), 56 | 'SayHelloStream': grpc.stream_stream_rpc_method_handler( 57 | servicer.SayHelloStream, 58 | request_deserializer=helloworld__pb2.HelloRequest.FromString, 59 | response_serializer=helloworld__pb2.HelloReply.SerializeToString, 60 | ), 61 | } 62 | generic_handler = grpc.method_handlers_generic_handler( 63 | 'proto.Greeter', rpc_method_handlers) 64 | server.add_generic_rpc_handlers((generic_handler,)) 65 | 66 | 67 | # This class is part of an EXPERIMENTAL API. 68 | class Greeter(object): 69 | """The greeting service definition. 70 | """ 71 | 72 | @staticmethod 73 | def SayHello(request, 74 | target, 75 | options=(), 76 | channel_credentials=None, 77 | call_credentials=None, 78 | insecure=False, 79 | compression=None, 80 | wait_for_ready=None, 81 | timeout=None, 82 | metadata=None): 83 | return grpc.experimental.unary_unary(request, target, '/proto.Greeter/SayHello', 84 | helloworld__pb2.HelloRequest.SerializeToString, 85 | helloworld__pb2.HelloReply.FromString, 86 | options, channel_credentials, 87 | insecure, call_credentials, compression, wait_for_ready, timeout, metadata) 88 | 89 | @staticmethod 90 | def SayHelloStream(request_iterator, 91 | target, 92 | options=(), 93 | channel_credentials=None, 94 | call_credentials=None, 95 | insecure=False, 96 | compression=None, 97 | wait_for_ready=None, 98 | timeout=None, 99 | metadata=None): 100 | return grpc.experimental.stream_stream(request_iterator, target, '/proto.Greeter/SayHelloStream', 101 | helloworld__pb2.HelloRequest.SerializeToString, 102 | helloworld__pb2.HelloReply.FromString, 103 | options, channel_credentials, 104 | insecure, call_credentials, compression, wait_for_ready, timeout, metadata) 105 | -------------------------------------------------------------------------------- /grpc-example/py-client/main.py: -------------------------------------------------------------------------------- 1 | import grpc 2 | 3 | import helloworld_pb2 4 | import helloworld_pb2_grpc 5 | 6 | 7 | def main(): 8 | channel = grpc.insecure_channel("127.0.0.1:50051") 9 | stub = helloworld_pb2_grpc.GreeterStub(channel) 10 | response = stub.SayHello(helloworld_pb2.HelloRequest(name="zhangsan")) 11 | print(response.message) 12 | 13 | 14 | if __name__ == '__main__': 15 | main() 16 | -------------------------------------------------------------------------------- /grpc-example/rest/go.mod: -------------------------------------------------------------------------------- 1 | module rest 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/golang/protobuf v1.5.2 7 | github.com/grpc-ecosystem/grpc-gateway v1.16.0 8 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.6.0 9 | google.golang.org/genproto v0.0.0-20211021150943-2b146023228c 10 | google.golang.org/grpc v1.40.0 11 | ) 12 | -------------------------------------------------------------------------------- /grpc-example/rest/grpc_service.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "net" 6 | 7 | "rest/proto" 8 | 9 | "google.golang.org/grpc" 10 | ) 11 | 12 | type RestServiceImpl struct{} 13 | 14 | func (r *RestServiceImpl) Get(ctx context.Context, message *proto.StringMessage) (*proto.StringMessage, error) { 15 | return &proto.StringMessage{Value: "Get hi:" + message.Value + "#"}, nil 16 | } 17 | 18 | func (r *RestServiceImpl) Post(ctx context.Context, message *proto.StringMessage) (*proto.StringMessage, error) { 19 | return &proto.StringMessage{Value: "Post hi:" + message.Value + "@"}, nil 20 | } 21 | 22 | func main() { 23 | grpcServer := grpc.NewServer() 24 | proto.RegisterRestServiceServer(grpcServer, new(RestServiceImpl)) 25 | lis, _ := net.Listen("tcp", ":50051") 26 | grpcServer.Serve(lis) 27 | } 28 | -------------------------------------------------------------------------------- /grpc-example/rest/proto/gen_proto.sh: -------------------------------------------------------------------------------- 1 | protoc -I/usr/local/include -I. \ 2 | -I$GOPATH/pkg/mod \ 3 | -I$GOPATH/pkg/mod/github.com/grpc-ecosystem/grpc-gateway@v1.16.0/third_party/googleapis \ 4 | --grpc-gateway_out=. --go_out=plugins=grpc:.\ 5 | --swagger_out=. \ 6 | helloworld.proto -------------------------------------------------------------------------------- /grpc-example/rest/proto/helloworld.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // source: helloworld.proto 3 | 4 | package proto 5 | 6 | import ( 7 | context "context" 8 | fmt "fmt" 9 | proto "github.com/golang/protobuf/proto" 10 | _ "google.golang.org/genproto/googleapis/api/annotations" 11 | grpc "google.golang.org/grpc" 12 | codes "google.golang.org/grpc/codes" 13 | status "google.golang.org/grpc/status" 14 | math "math" 15 | ) 16 | 17 | // Reference imports to suppress errors if they are not otherwise used. 18 | var _ = proto.Marshal 19 | var _ = fmt.Errorf 20 | var _ = math.Inf 21 | 22 | // This is a compile-time assertion to ensure that this generated file 23 | // is compatible with the proto package it is being compiled against. 24 | // A compilation error at this line likely means your copy of the 25 | // proto package needs to be updated. 26 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 27 | 28 | type StringMessage struct { 29 | Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` 30 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 31 | XXX_unrecognized []byte `json:"-"` 32 | XXX_sizecache int32 `json:"-"` 33 | } 34 | 35 | func (m *StringMessage) Reset() { *m = StringMessage{} } 36 | func (m *StringMessage) String() string { return proto.CompactTextString(m) } 37 | func (*StringMessage) ProtoMessage() {} 38 | func (*StringMessage) Descriptor() ([]byte, []int) { 39 | return fileDescriptor_17b8c58d586b62f2, []int{0} 40 | } 41 | 42 | func (m *StringMessage) XXX_Unmarshal(b []byte) error { 43 | return xxx_messageInfo_StringMessage.Unmarshal(m, b) 44 | } 45 | func (m *StringMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 46 | return xxx_messageInfo_StringMessage.Marshal(b, m, deterministic) 47 | } 48 | func (m *StringMessage) XXX_Merge(src proto.Message) { 49 | xxx_messageInfo_StringMessage.Merge(m, src) 50 | } 51 | func (m *StringMessage) XXX_Size() int { 52 | return xxx_messageInfo_StringMessage.Size(m) 53 | } 54 | func (m *StringMessage) XXX_DiscardUnknown() { 55 | xxx_messageInfo_StringMessage.DiscardUnknown(m) 56 | } 57 | 58 | var xxx_messageInfo_StringMessage proto.InternalMessageInfo 59 | 60 | func (m *StringMessage) GetValue() string { 61 | if m != nil { 62 | return m.Value 63 | } 64 | return "" 65 | } 66 | 67 | func init() { 68 | proto.RegisterType((*StringMessage)(nil), "proto.StringMessage") 69 | } 70 | 71 | func init() { proto.RegisterFile("helloworld.proto", fileDescriptor_17b8c58d586b62f2) } 72 | 73 | var fileDescriptor_17b8c58d586b62f2 = []byte{ 74 | // 188 bytes of a gzipped FileDescriptorProto 75 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xc8, 0x48, 0xcd, 0xc9, 76 | 0xc9, 0x2f, 0xcf, 0x2f, 0xca, 0x49, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x05, 0x53, 77 | 0x52, 0x32, 0xe9, 0xf9, 0xf9, 0xe9, 0x39, 0xa9, 0xfa, 0x89, 0x05, 0x99, 0xfa, 0x89, 0x79, 0x79, 78 | 0xf9, 0x25, 0x89, 0x25, 0x99, 0xf9, 0x79, 0xc5, 0x10, 0x45, 0x4a, 0xaa, 0x5c, 0xbc, 0xc1, 0x25, 79 | 0x45, 0x99, 0x79, 0xe9, 0xbe, 0xa9, 0xc5, 0xc5, 0x89, 0xe9, 0xa9, 0x42, 0x22, 0x5c, 0xac, 0x65, 80 | 0x89, 0x39, 0xa5, 0xa9, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0x10, 0x8e, 0xd1, 0x1c, 0x46, 81 | 0x2e, 0xee, 0xa0, 0xd4, 0xe2, 0x92, 0xe0, 0xd4, 0xa2, 0xb2, 0xcc, 0xe4, 0x54, 0x21, 0x77, 0x2e, 82 | 0x66, 0xf7, 0xd4, 0x12, 0x21, 0x11, 0x88, 0x29, 0x7a, 0x28, 0x46, 0x48, 0x61, 0x15, 0x55, 0x12, 83 | 0x69, 0xba, 0xfc, 0x64, 0x32, 0x13, 0x9f, 0x10, 0x8f, 0x7e, 0x7a, 0x6a, 0x89, 0x7e, 0x35, 0xd8, 84 | 0xdc, 0x5a, 0x21, 0x17, 0x2e, 0x96, 0x80, 0xfc, 0x62, 0xd2, 0x4c, 0x12, 0x00, 0x9b, 0xc4, 0xa5, 85 | 0xc4, 0xaa, 0x5f, 0x90, 0x5f, 0x5c, 0x62, 0xc5, 0xa8, 0x95, 0xc4, 0x06, 0x56, 0x66, 0x0c, 0x08, 86 | 0x00, 0x00, 0xff, 0xff, 0x55, 0x2e, 0xbc, 0xcc, 0x05, 0x01, 0x00, 0x00, 87 | } 88 | 89 | // Reference imports to suppress errors if they are not otherwise used. 90 | var _ context.Context 91 | var _ grpc.ClientConn 92 | 93 | // This is a compile-time assertion to ensure that this generated file 94 | // is compatible with the grpc package it is being compiled against. 95 | const _ = grpc.SupportPackageIsVersion4 96 | 97 | // RestServiceClient is the client API for RestService service. 98 | // 99 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. 100 | type RestServiceClient interface { 101 | Get(ctx context.Context, in *StringMessage, opts ...grpc.CallOption) (*StringMessage, error) 102 | Post(ctx context.Context, in *StringMessage, opts ...grpc.CallOption) (*StringMessage, error) 103 | } 104 | 105 | type restServiceClient struct { 106 | cc *grpc.ClientConn 107 | } 108 | 109 | func NewRestServiceClient(cc *grpc.ClientConn) RestServiceClient { 110 | return &restServiceClient{cc} 111 | } 112 | 113 | func (c *restServiceClient) Get(ctx context.Context, in *StringMessage, opts ...grpc.CallOption) (*StringMessage, error) { 114 | out := new(StringMessage) 115 | err := c.cc.Invoke(ctx, "/proto.RestService/Get", in, out, opts...) 116 | if err != nil { 117 | return nil, err 118 | } 119 | return out, nil 120 | } 121 | 122 | func (c *restServiceClient) Post(ctx context.Context, in *StringMessage, opts ...grpc.CallOption) (*StringMessage, error) { 123 | out := new(StringMessage) 124 | err := c.cc.Invoke(ctx, "/proto.RestService/Post", in, out, opts...) 125 | if err != nil { 126 | return nil, err 127 | } 128 | return out, nil 129 | } 130 | 131 | // RestServiceServer is the server API for RestService service. 132 | type RestServiceServer interface { 133 | Get(context.Context, *StringMessage) (*StringMessage, error) 134 | Post(context.Context, *StringMessage) (*StringMessage, error) 135 | } 136 | 137 | // UnimplementedRestServiceServer can be embedded to have forward compatible implementations. 138 | type UnimplementedRestServiceServer struct { 139 | } 140 | 141 | func (*UnimplementedRestServiceServer) Get(ctx context.Context, req *StringMessage) (*StringMessage, error) { 142 | return nil, status.Errorf(codes.Unimplemented, "method Get not implemented") 143 | } 144 | func (*UnimplementedRestServiceServer) Post(ctx context.Context, req *StringMessage) (*StringMessage, error) { 145 | return nil, status.Errorf(codes.Unimplemented, "method Post not implemented") 146 | } 147 | 148 | func RegisterRestServiceServer(s *grpc.Server, srv RestServiceServer) { 149 | s.RegisterService(&_RestService_serviceDesc, srv) 150 | } 151 | 152 | func _RestService_Get_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 153 | in := new(StringMessage) 154 | if err := dec(in); err != nil { 155 | return nil, err 156 | } 157 | if interceptor == nil { 158 | return srv.(RestServiceServer).Get(ctx, in) 159 | } 160 | info := &grpc.UnaryServerInfo{ 161 | Server: srv, 162 | FullMethod: "/proto.RestService/Get", 163 | } 164 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 165 | return srv.(RestServiceServer).Get(ctx, req.(*StringMessage)) 166 | } 167 | return interceptor(ctx, in, info, handler) 168 | } 169 | 170 | func _RestService_Post_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 171 | in := new(StringMessage) 172 | if err := dec(in); err != nil { 173 | return nil, err 174 | } 175 | if interceptor == nil { 176 | return srv.(RestServiceServer).Post(ctx, in) 177 | } 178 | info := &grpc.UnaryServerInfo{ 179 | Server: srv, 180 | FullMethod: "/proto.RestService/Post", 181 | } 182 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 183 | return srv.(RestServiceServer).Post(ctx, req.(*StringMessage)) 184 | } 185 | return interceptor(ctx, in, info, handler) 186 | } 187 | 188 | var _RestService_serviceDesc = grpc.ServiceDesc{ 189 | ServiceName: "proto.RestService", 190 | HandlerType: (*RestServiceServer)(nil), 191 | Methods: []grpc.MethodDesc{ 192 | { 193 | MethodName: "Get", 194 | Handler: _RestService_Get_Handler, 195 | }, 196 | { 197 | MethodName: "Post", 198 | Handler: _RestService_Post_Handler, 199 | }, 200 | }, 201 | Streams: []grpc.StreamDesc{}, 202 | Metadata: "helloworld.proto", 203 | } 204 | -------------------------------------------------------------------------------- /grpc-example/rest/proto/helloworld.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package proto; 4 | 5 | import "google/api/annotations.proto"; 6 | 7 | message StringMessage { 8 | string value = 1; 9 | } 10 | 11 | service RestService { 12 | rpc Get(StringMessage) returns (StringMessage) { 13 | option (google.api.http) = { 14 | get: "/get/{value}" 15 | }; 16 | } 17 | rpc Post(StringMessage) returns (StringMessage) { 18 | option (google.api.http) = { 19 | post: "/post" 20 | body: "*" 21 | }; 22 | } 23 | } -------------------------------------------------------------------------------- /grpc-example/rest/proto/helloworld.swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "title": "helloworld.proto", 5 | "version": "version not set" 6 | }, 7 | "consumes": [ 8 | "application/json" 9 | ], 10 | "produces": [ 11 | "application/json" 12 | ], 13 | "paths": { 14 | "/get/{value}": { 15 | "get": { 16 | "operationId": "RestService_Get", 17 | "responses": { 18 | "200": { 19 | "description": "A successful response.", 20 | "schema": { 21 | "$ref": "#/definitions/protoStringMessage" 22 | } 23 | }, 24 | "default": { 25 | "description": "An unexpected error response.", 26 | "schema": { 27 | "$ref": "#/definitions/runtimeError" 28 | } 29 | } 30 | }, 31 | "parameters": [ 32 | { 33 | "name": "value", 34 | "in": "path", 35 | "required": true, 36 | "type": "string" 37 | } 38 | ], 39 | "tags": [ 40 | "RestService" 41 | ] 42 | } 43 | }, 44 | "/post": { 45 | "post": { 46 | "operationId": "RestService_Post", 47 | "responses": { 48 | "200": { 49 | "description": "A successful response.", 50 | "schema": { 51 | "$ref": "#/definitions/protoStringMessage" 52 | } 53 | }, 54 | "default": { 55 | "description": "An unexpected error response.", 56 | "schema": { 57 | "$ref": "#/definitions/runtimeError" 58 | } 59 | } 60 | }, 61 | "parameters": [ 62 | { 63 | "name": "body", 64 | "in": "body", 65 | "required": true, 66 | "schema": { 67 | "$ref": "#/definitions/protoStringMessage" 68 | } 69 | } 70 | ], 71 | "tags": [ 72 | "RestService" 73 | ] 74 | } 75 | } 76 | }, 77 | "definitions": { 78 | "protoStringMessage": { 79 | "type": "object", 80 | "properties": { 81 | "value": { 82 | "type": "string" 83 | } 84 | } 85 | }, 86 | "protobufAny": { 87 | "type": "object", 88 | "properties": { 89 | "type_url": { 90 | "type": "string" 91 | }, 92 | "value": { 93 | "type": "string", 94 | "format": "byte" 95 | } 96 | } 97 | }, 98 | "runtimeError": { 99 | "type": "object", 100 | "properties": { 101 | "error": { 102 | "type": "string" 103 | }, 104 | "code": { 105 | "type": "integer", 106 | "format": "int32" 107 | }, 108 | "message": { 109 | "type": "string" 110 | }, 111 | "details": { 112 | "type": "array", 113 | "items": { 114 | "$ref": "#/definitions/protobufAny" 115 | } 116 | } 117 | } 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /grpc-example/rest/rest_service.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "net/http" 7 | 8 | "rest/proto" 9 | 10 | "github.com/grpc-ecosystem/grpc-gateway/runtime" 11 | "google.golang.org/grpc" 12 | ) 13 | 14 | func main() { 15 | ctx := context.Background() 16 | ctx, cancel := context.WithCancel(ctx) 17 | defer cancel() 18 | 19 | mux := runtime.NewServeMux() 20 | 21 | err := proto.RegisterRestServiceHandlerFromEndpoint( 22 | ctx, mux, "localhost:50051", 23 | []grpc.DialOption{grpc.WithInsecure()}, 24 | ) 25 | if err != nil { 26 | log.Fatal(err) 27 | } 28 | 29 | http.ListenAndServe(":8080", mux) 30 | } 31 | -------------------------------------------------------------------------------- /grpc-example/simple/client/go.mod: -------------------------------------------------------------------------------- 1 | module client 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/golang/protobuf v1.5.2 7 | google.golang.org/grpc v1.41.0 8 | ) 9 | -------------------------------------------------------------------------------- /grpc-example/simple/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "client/proto" 5 | "context" 6 | "fmt" 7 | "log" 8 | 9 | "google.golang.org/grpc" 10 | ) 11 | 12 | func main() { 13 | // 简单调用 14 | conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure()) 15 | defer conn.Close() 16 | 17 | client := proto.NewGreeterClient(conn) 18 | // 简单调用 19 | reply, err := client.SayHello(context.Background(), &proto.HelloRequest{Name: "zzz"}) 20 | if err != nil { 21 | log.Fatal(err) 22 | } 23 | fmt.Println(reply.Message) 24 | 25 | // 流处理 26 | // stream, err := client.SayHelloStream(context.Background()) 27 | // if err != nil { 28 | // log.Fatal(err) 29 | // } 30 | 31 | // // 发送消息 32 | // go func() { 33 | // for { 34 | // if err := stream.Send(&proto.HelloRequest{Name: "zhangsan"}); err != nil { 35 | // log.Fatal(err) 36 | // } 37 | // time.Sleep(time.Second) 38 | // } 39 | // }() 40 | 41 | // // 接收消息 42 | // for { 43 | // reply, err := stream.Recv() 44 | // if err != nil { 45 | // if err == io.EOF { 46 | // break 47 | // } 48 | // log.Fatal(err) 49 | // } 50 | // fmt.Println(reply.Message) 51 | // } 52 | } 53 | -------------------------------------------------------------------------------- /grpc-example/simple/client/proto/helloworld.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // source: helloworld.proto 3 | 4 | package proto 5 | 6 | import ( 7 | context "context" 8 | fmt "fmt" 9 | proto "github.com/golang/protobuf/proto" 10 | grpc "google.golang.org/grpc" 11 | codes "google.golang.org/grpc/codes" 12 | status "google.golang.org/grpc/status" 13 | math "math" 14 | ) 15 | 16 | // Reference imports to suppress errors if they are not otherwise used. 17 | var _ = proto.Marshal 18 | var _ = fmt.Errorf 19 | var _ = math.Inf 20 | 21 | // This is a compile-time assertion to ensure that this generated file 22 | // is compatible with the proto package it is being compiled against. 23 | // A compilation error at this line likely means your copy of the 24 | // proto package needs to be updated. 25 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 26 | 27 | // The request message containing the user's name. 28 | type HelloRequest struct { 29 | Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` 30 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 31 | XXX_unrecognized []byte `json:"-"` 32 | XXX_sizecache int32 `json:"-"` 33 | } 34 | 35 | func (m *HelloRequest) Reset() { *m = HelloRequest{} } 36 | func (m *HelloRequest) String() string { return proto.CompactTextString(m) } 37 | func (*HelloRequest) ProtoMessage() {} 38 | func (*HelloRequest) Descriptor() ([]byte, []int) { 39 | return fileDescriptor_17b8c58d586b62f2, []int{0} 40 | } 41 | 42 | func (m *HelloRequest) XXX_Unmarshal(b []byte) error { 43 | return xxx_messageInfo_HelloRequest.Unmarshal(m, b) 44 | } 45 | func (m *HelloRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 46 | return xxx_messageInfo_HelloRequest.Marshal(b, m, deterministic) 47 | } 48 | func (m *HelloRequest) XXX_Merge(src proto.Message) { 49 | xxx_messageInfo_HelloRequest.Merge(m, src) 50 | } 51 | func (m *HelloRequest) XXX_Size() int { 52 | return xxx_messageInfo_HelloRequest.Size(m) 53 | } 54 | func (m *HelloRequest) XXX_DiscardUnknown() { 55 | xxx_messageInfo_HelloRequest.DiscardUnknown(m) 56 | } 57 | 58 | var xxx_messageInfo_HelloRequest proto.InternalMessageInfo 59 | 60 | func (m *HelloRequest) GetName() string { 61 | if m != nil { 62 | return m.Name 63 | } 64 | return "" 65 | } 66 | 67 | // The response message containing the greetings 68 | type HelloReply struct { 69 | Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` 70 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 71 | XXX_unrecognized []byte `json:"-"` 72 | XXX_sizecache int32 `json:"-"` 73 | } 74 | 75 | func (m *HelloReply) Reset() { *m = HelloReply{} } 76 | func (m *HelloReply) String() string { return proto.CompactTextString(m) } 77 | func (*HelloReply) ProtoMessage() {} 78 | func (*HelloReply) Descriptor() ([]byte, []int) { 79 | return fileDescriptor_17b8c58d586b62f2, []int{1} 80 | } 81 | 82 | func (m *HelloReply) XXX_Unmarshal(b []byte) error { 83 | return xxx_messageInfo_HelloReply.Unmarshal(m, b) 84 | } 85 | func (m *HelloReply) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 86 | return xxx_messageInfo_HelloReply.Marshal(b, m, deterministic) 87 | } 88 | func (m *HelloReply) XXX_Merge(src proto.Message) { 89 | xxx_messageInfo_HelloReply.Merge(m, src) 90 | } 91 | func (m *HelloReply) XXX_Size() int { 92 | return xxx_messageInfo_HelloReply.Size(m) 93 | } 94 | func (m *HelloReply) XXX_DiscardUnknown() { 95 | xxx_messageInfo_HelloReply.DiscardUnknown(m) 96 | } 97 | 98 | var xxx_messageInfo_HelloReply proto.InternalMessageInfo 99 | 100 | func (m *HelloReply) GetMessage() string { 101 | if m != nil { 102 | return m.Message 103 | } 104 | return "" 105 | } 106 | 107 | func init() { 108 | proto.RegisterType((*HelloRequest)(nil), "proto.HelloRequest") 109 | proto.RegisterType((*HelloReply)(nil), "proto.HelloReply") 110 | } 111 | 112 | func init() { proto.RegisterFile("helloworld.proto", fileDescriptor_17b8c58d586b62f2) } 113 | 114 | var fileDescriptor_17b8c58d586b62f2 = []byte{ 115 | // 159 bytes of a gzipped FileDescriptorProto 116 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xc8, 0x48, 0xcd, 0xc9, 117 | 0xc9, 0x2f, 0xcf, 0x2f, 0xca, 0x49, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x05, 0x53, 118 | 0x4a, 0x4a, 0x5c, 0x3c, 0x1e, 0x20, 0xa9, 0xa0, 0xd4, 0xc2, 0xd2, 0xd4, 0xe2, 0x12, 0x21, 0x21, 119 | 0x2e, 0x96, 0xbc, 0xc4, 0xdc, 0x54, 0x09, 0x46, 0x05, 0x46, 0x0d, 0xce, 0x20, 0x30, 0x5b, 0x49, 120 | 0x8d, 0x8b, 0x0b, 0xaa, 0xa6, 0x20, 0xa7, 0x52, 0x48, 0x82, 0x8b, 0x3d, 0x37, 0xb5, 0xb8, 0x38, 121 | 0x31, 0x1d, 0xa6, 0x08, 0xc6, 0x35, 0xaa, 0xe7, 0x62, 0x77, 0x2f, 0x4a, 0x4d, 0x2d, 0x49, 0x2d, 122 | 0x12, 0x32, 0xe1, 0xe2, 0x08, 0x4e, 0xac, 0x04, 0xeb, 0x12, 0x12, 0x86, 0xd8, 0xa8, 0x87, 0x6c, 123 | 0x8f, 0x94, 0x20, 0xaa, 0x60, 0x41, 0x4e, 0xa5, 0x12, 0x83, 0x90, 0x1d, 0x17, 0x1f, 0x4c, 0x57, 124 | 0x70, 0x49, 0x51, 0x6a, 0x62, 0x2e, 0xf1, 0x7a, 0x35, 0x18, 0x0d, 0x18, 0x93, 0xd8, 0xc0, 0xe2, 125 | 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcd, 0x24, 0x7d, 0xbd, 0xee, 0x00, 0x00, 0x00, 126 | } 127 | 128 | // Reference imports to suppress errors if they are not otherwise used. 129 | var _ context.Context 130 | var _ grpc.ClientConn 131 | 132 | // This is a compile-time assertion to ensure that this generated file 133 | // is compatible with the grpc package it is being compiled against. 134 | const _ = grpc.SupportPackageIsVersion4 135 | 136 | // GreeterClient is the client API for Greeter service. 137 | // 138 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. 139 | type GreeterClient interface { 140 | // Sends a greeting 141 | SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) 142 | // Sends stream message 143 | SayHelloStream(ctx context.Context, opts ...grpc.CallOption) (Greeter_SayHelloStreamClient, error) 144 | } 145 | 146 | type greeterClient struct { 147 | cc *grpc.ClientConn 148 | } 149 | 150 | func NewGreeterClient(cc *grpc.ClientConn) GreeterClient { 151 | return &greeterClient{cc} 152 | } 153 | 154 | func (c *greeterClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) { 155 | out := new(HelloReply) 156 | err := c.cc.Invoke(ctx, "/proto.Greeter/SayHello", in, out, opts...) 157 | if err != nil { 158 | return nil, err 159 | } 160 | return out, nil 161 | } 162 | 163 | func (c *greeterClient) SayHelloStream(ctx context.Context, opts ...grpc.CallOption) (Greeter_SayHelloStreamClient, error) { 164 | stream, err := c.cc.NewStream(ctx, &_Greeter_serviceDesc.Streams[0], "/proto.Greeter/SayHelloStream", opts...) 165 | if err != nil { 166 | return nil, err 167 | } 168 | x := &greeterSayHelloStreamClient{stream} 169 | return x, nil 170 | } 171 | 172 | type Greeter_SayHelloStreamClient interface { 173 | Send(*HelloRequest) error 174 | Recv() (*HelloReply, error) 175 | grpc.ClientStream 176 | } 177 | 178 | type greeterSayHelloStreamClient struct { 179 | grpc.ClientStream 180 | } 181 | 182 | func (x *greeterSayHelloStreamClient) Send(m *HelloRequest) error { 183 | return x.ClientStream.SendMsg(m) 184 | } 185 | 186 | func (x *greeterSayHelloStreamClient) Recv() (*HelloReply, error) { 187 | m := new(HelloReply) 188 | if err := x.ClientStream.RecvMsg(m); err != nil { 189 | return nil, err 190 | } 191 | return m, nil 192 | } 193 | 194 | // GreeterServer is the server API for Greeter service. 195 | type GreeterServer interface { 196 | // Sends a greeting 197 | SayHello(context.Context, *HelloRequest) (*HelloReply, error) 198 | // Sends stream message 199 | SayHelloStream(Greeter_SayHelloStreamServer) error 200 | } 201 | 202 | // UnimplementedGreeterServer can be embedded to have forward compatible implementations. 203 | type UnimplementedGreeterServer struct { 204 | } 205 | 206 | func (*UnimplementedGreeterServer) SayHello(ctx context.Context, req *HelloRequest) (*HelloReply, error) { 207 | return nil, status.Errorf(codes.Unimplemented, "method SayHello not implemented") 208 | } 209 | func (*UnimplementedGreeterServer) SayHelloStream(srv Greeter_SayHelloStreamServer) error { 210 | return status.Errorf(codes.Unimplemented, "method SayHelloStream not implemented") 211 | } 212 | 213 | func RegisterGreeterServer(s *grpc.Server, srv GreeterServer) { 214 | s.RegisterService(&_Greeter_serviceDesc, srv) 215 | } 216 | 217 | func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 218 | in := new(HelloRequest) 219 | if err := dec(in); err != nil { 220 | return nil, err 221 | } 222 | if interceptor == nil { 223 | return srv.(GreeterServer).SayHello(ctx, in) 224 | } 225 | info := &grpc.UnaryServerInfo{ 226 | Server: srv, 227 | FullMethod: "/proto.Greeter/SayHello", 228 | } 229 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 230 | return srv.(GreeterServer).SayHello(ctx, req.(*HelloRequest)) 231 | } 232 | return interceptor(ctx, in, info, handler) 233 | } 234 | 235 | func _Greeter_SayHelloStream_Handler(srv interface{}, stream grpc.ServerStream) error { 236 | return srv.(GreeterServer).SayHelloStream(&greeterSayHelloStreamServer{stream}) 237 | } 238 | 239 | type Greeter_SayHelloStreamServer interface { 240 | Send(*HelloReply) error 241 | Recv() (*HelloRequest, error) 242 | grpc.ServerStream 243 | } 244 | 245 | type greeterSayHelloStreamServer struct { 246 | grpc.ServerStream 247 | } 248 | 249 | func (x *greeterSayHelloStreamServer) Send(m *HelloReply) error { 250 | return x.ServerStream.SendMsg(m) 251 | } 252 | 253 | func (x *greeterSayHelloStreamServer) Recv() (*HelloRequest, error) { 254 | m := new(HelloRequest) 255 | if err := x.ServerStream.RecvMsg(m); err != nil { 256 | return nil, err 257 | } 258 | return m, nil 259 | } 260 | 261 | var _Greeter_serviceDesc = grpc.ServiceDesc{ 262 | ServiceName: "proto.Greeter", 263 | HandlerType: (*GreeterServer)(nil), 264 | Methods: []grpc.MethodDesc{ 265 | { 266 | MethodName: "SayHello", 267 | Handler: _Greeter_SayHello_Handler, 268 | }, 269 | }, 270 | Streams: []grpc.StreamDesc{ 271 | { 272 | StreamName: "SayHelloStream", 273 | Handler: _Greeter_SayHelloStream_Handler, 274 | ServerStreams: true, 275 | ClientStreams: true, 276 | }, 277 | }, 278 | Metadata: "helloworld.proto", 279 | } 280 | -------------------------------------------------------------------------------- /grpc-example/simple/server/go.mod: -------------------------------------------------------------------------------- 1 | module server 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/golang/protobuf v1.5.2 7 | google.golang.org/grpc v1.41.0 8 | ) 9 | -------------------------------------------------------------------------------- /grpc-example/simple/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "io" 7 | "log" 8 | "net" 9 | "server/proto" 10 | 11 | "google.golang.org/grpc" 12 | "google.golang.org/grpc/reflection" 13 | ) 14 | 15 | type greeter struct { 16 | } 17 | 18 | func (*greeter) SayHello(ctx context.Context, req *proto.HelloRequest) (*proto.HelloReply, error) { 19 | fmt.Println(req) 20 | reply := &proto.HelloReply{Message: "hello"} 21 | return reply, nil 22 | } 23 | 24 | func (*greeter) SayHelloStream(stream proto.Greeter_SayHelloStreamServer) error { 25 | for { 26 | args, err := stream.Recv() 27 | if err != nil { 28 | if err == io.EOF { 29 | return nil 30 | } 31 | return err 32 | } 33 | 34 | fmt.Println("Recv: " + args.Name) 35 | reply := &proto.HelloReply{Message: "hi " + args.Name} 36 | 37 | err = stream.Send(reply) 38 | if err != nil { 39 | return err 40 | } 41 | } 42 | } 43 | 44 | func main() { 45 | lis, err := net.Listen("tcp", ":50051") 46 | if err != nil { 47 | log.Fatalf("failed to listen: %v", err) 48 | } 49 | 50 | // 简单调用 51 | server := grpc.NewServer() 52 | // 注册 grpcurl 所需的 reflection 服务 53 | reflection.Register(server) 54 | // 注册业务服务 55 | proto.RegisterGreeterServer(server, &greeter{}) 56 | 57 | fmt.Println("grpc server start ...") 58 | if err := server.Serve(lis); err != nil { 59 | log.Fatalf("failed to serve: %v", err) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /grpc-example/simple/server/proto/gen_proto.sh: -------------------------------------------------------------------------------- 1 | 2 | protoc --go_out=plugins=grpc:. *.proto 3 | -------------------------------------------------------------------------------- /grpc-example/simple/server/proto/helloworld.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // source: helloworld.proto 3 | 4 | package proto 5 | 6 | import ( 7 | context "context" 8 | fmt "fmt" 9 | proto "github.com/golang/protobuf/proto" 10 | grpc "google.golang.org/grpc" 11 | codes "google.golang.org/grpc/codes" 12 | status "google.golang.org/grpc/status" 13 | math "math" 14 | ) 15 | 16 | // Reference imports to suppress errors if they are not otherwise used. 17 | var _ = proto.Marshal 18 | var _ = fmt.Errorf 19 | var _ = math.Inf 20 | 21 | // This is a compile-time assertion to ensure that this generated file 22 | // is compatible with the proto package it is being compiled against. 23 | // A compilation error at this line likely means your copy of the 24 | // proto package needs to be updated. 25 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 26 | 27 | // The request message containing the user's name. 28 | type HelloRequest struct { 29 | Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` 30 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 31 | XXX_unrecognized []byte `json:"-"` 32 | XXX_sizecache int32 `json:"-"` 33 | } 34 | 35 | func (m *HelloRequest) Reset() { *m = HelloRequest{} } 36 | func (m *HelloRequest) String() string { return proto.CompactTextString(m) } 37 | func (*HelloRequest) ProtoMessage() {} 38 | func (*HelloRequest) Descriptor() ([]byte, []int) { 39 | return fileDescriptor_17b8c58d586b62f2, []int{0} 40 | } 41 | 42 | func (m *HelloRequest) XXX_Unmarshal(b []byte) error { 43 | return xxx_messageInfo_HelloRequest.Unmarshal(m, b) 44 | } 45 | func (m *HelloRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 46 | return xxx_messageInfo_HelloRequest.Marshal(b, m, deterministic) 47 | } 48 | func (m *HelloRequest) XXX_Merge(src proto.Message) { 49 | xxx_messageInfo_HelloRequest.Merge(m, src) 50 | } 51 | func (m *HelloRequest) XXX_Size() int { 52 | return xxx_messageInfo_HelloRequest.Size(m) 53 | } 54 | func (m *HelloRequest) XXX_DiscardUnknown() { 55 | xxx_messageInfo_HelloRequest.DiscardUnknown(m) 56 | } 57 | 58 | var xxx_messageInfo_HelloRequest proto.InternalMessageInfo 59 | 60 | func (m *HelloRequest) GetName() string { 61 | if m != nil { 62 | return m.Name 63 | } 64 | return "" 65 | } 66 | 67 | // The response message containing the greetings 68 | type HelloReply struct { 69 | Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` 70 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 71 | XXX_unrecognized []byte `json:"-"` 72 | XXX_sizecache int32 `json:"-"` 73 | } 74 | 75 | func (m *HelloReply) Reset() { *m = HelloReply{} } 76 | func (m *HelloReply) String() string { return proto.CompactTextString(m) } 77 | func (*HelloReply) ProtoMessage() {} 78 | func (*HelloReply) Descriptor() ([]byte, []int) { 79 | return fileDescriptor_17b8c58d586b62f2, []int{1} 80 | } 81 | 82 | func (m *HelloReply) XXX_Unmarshal(b []byte) error { 83 | return xxx_messageInfo_HelloReply.Unmarshal(m, b) 84 | } 85 | func (m *HelloReply) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 86 | return xxx_messageInfo_HelloReply.Marshal(b, m, deterministic) 87 | } 88 | func (m *HelloReply) XXX_Merge(src proto.Message) { 89 | xxx_messageInfo_HelloReply.Merge(m, src) 90 | } 91 | func (m *HelloReply) XXX_Size() int { 92 | return xxx_messageInfo_HelloReply.Size(m) 93 | } 94 | func (m *HelloReply) XXX_DiscardUnknown() { 95 | xxx_messageInfo_HelloReply.DiscardUnknown(m) 96 | } 97 | 98 | var xxx_messageInfo_HelloReply proto.InternalMessageInfo 99 | 100 | func (m *HelloReply) GetMessage() string { 101 | if m != nil { 102 | return m.Message 103 | } 104 | return "" 105 | } 106 | 107 | func init() { 108 | proto.RegisterType((*HelloRequest)(nil), "proto.HelloRequest") 109 | proto.RegisterType((*HelloReply)(nil), "proto.HelloReply") 110 | } 111 | 112 | func init() { proto.RegisterFile("helloworld.proto", fileDescriptor_17b8c58d586b62f2) } 113 | 114 | var fileDescriptor_17b8c58d586b62f2 = []byte{ 115 | // 159 bytes of a gzipped FileDescriptorProto 116 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xc8, 0x48, 0xcd, 0xc9, 117 | 0xc9, 0x2f, 0xcf, 0x2f, 0xca, 0x49, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x05, 0x53, 118 | 0x4a, 0x4a, 0x5c, 0x3c, 0x1e, 0x20, 0xa9, 0xa0, 0xd4, 0xc2, 0xd2, 0xd4, 0xe2, 0x12, 0x21, 0x21, 119 | 0x2e, 0x96, 0xbc, 0xc4, 0xdc, 0x54, 0x09, 0x46, 0x05, 0x46, 0x0d, 0xce, 0x20, 0x30, 0x5b, 0x49, 120 | 0x8d, 0x8b, 0x0b, 0xaa, 0xa6, 0x20, 0xa7, 0x52, 0x48, 0x82, 0x8b, 0x3d, 0x37, 0xb5, 0xb8, 0x38, 121 | 0x31, 0x1d, 0xa6, 0x08, 0xc6, 0x35, 0xaa, 0xe7, 0x62, 0x77, 0x2f, 0x4a, 0x4d, 0x2d, 0x49, 0x2d, 122 | 0x12, 0x32, 0xe1, 0xe2, 0x08, 0x4e, 0xac, 0x04, 0xeb, 0x12, 0x12, 0x86, 0xd8, 0xa8, 0x87, 0x6c, 123 | 0x8f, 0x94, 0x20, 0xaa, 0x60, 0x41, 0x4e, 0xa5, 0x12, 0x83, 0x90, 0x1d, 0x17, 0x1f, 0x4c, 0x57, 124 | 0x70, 0x49, 0x51, 0x6a, 0x62, 0x2e, 0xf1, 0x7a, 0x35, 0x18, 0x0d, 0x18, 0x93, 0xd8, 0xc0, 0xe2, 125 | 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcd, 0x24, 0x7d, 0xbd, 0xee, 0x00, 0x00, 0x00, 126 | } 127 | 128 | // Reference imports to suppress errors if they are not otherwise used. 129 | var _ context.Context 130 | var _ grpc.ClientConn 131 | 132 | // This is a compile-time assertion to ensure that this generated file 133 | // is compatible with the grpc package it is being compiled against. 134 | const _ = grpc.SupportPackageIsVersion4 135 | 136 | // GreeterClient is the client API for Greeter service. 137 | // 138 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. 139 | type GreeterClient interface { 140 | // Sends a greeting 141 | SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) 142 | // Sends stream message 143 | SayHelloStream(ctx context.Context, opts ...grpc.CallOption) (Greeter_SayHelloStreamClient, error) 144 | } 145 | 146 | type greeterClient struct { 147 | cc *grpc.ClientConn 148 | } 149 | 150 | func NewGreeterClient(cc *grpc.ClientConn) GreeterClient { 151 | return &greeterClient{cc} 152 | } 153 | 154 | func (c *greeterClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) { 155 | out := new(HelloReply) 156 | err := c.cc.Invoke(ctx, "/proto.Greeter/SayHello", in, out, opts...) 157 | if err != nil { 158 | return nil, err 159 | } 160 | return out, nil 161 | } 162 | 163 | func (c *greeterClient) SayHelloStream(ctx context.Context, opts ...grpc.CallOption) (Greeter_SayHelloStreamClient, error) { 164 | stream, err := c.cc.NewStream(ctx, &_Greeter_serviceDesc.Streams[0], "/proto.Greeter/SayHelloStream", opts...) 165 | if err != nil { 166 | return nil, err 167 | } 168 | x := &greeterSayHelloStreamClient{stream} 169 | return x, nil 170 | } 171 | 172 | type Greeter_SayHelloStreamClient interface { 173 | Send(*HelloRequest) error 174 | Recv() (*HelloReply, error) 175 | grpc.ClientStream 176 | } 177 | 178 | type greeterSayHelloStreamClient struct { 179 | grpc.ClientStream 180 | } 181 | 182 | func (x *greeterSayHelloStreamClient) Send(m *HelloRequest) error { 183 | return x.ClientStream.SendMsg(m) 184 | } 185 | 186 | func (x *greeterSayHelloStreamClient) Recv() (*HelloReply, error) { 187 | m := new(HelloReply) 188 | if err := x.ClientStream.RecvMsg(m); err != nil { 189 | return nil, err 190 | } 191 | return m, nil 192 | } 193 | 194 | // GreeterServer is the server API for Greeter service. 195 | type GreeterServer interface { 196 | // Sends a greeting 197 | SayHello(context.Context, *HelloRequest) (*HelloReply, error) 198 | // Sends stream message 199 | SayHelloStream(Greeter_SayHelloStreamServer) error 200 | } 201 | 202 | // UnimplementedGreeterServer can be embedded to have forward compatible implementations. 203 | type UnimplementedGreeterServer struct { 204 | } 205 | 206 | func (*UnimplementedGreeterServer) SayHello(ctx context.Context, req *HelloRequest) (*HelloReply, error) { 207 | return nil, status.Errorf(codes.Unimplemented, "method SayHello not implemented") 208 | } 209 | func (*UnimplementedGreeterServer) SayHelloStream(srv Greeter_SayHelloStreamServer) error { 210 | return status.Errorf(codes.Unimplemented, "method SayHelloStream not implemented") 211 | } 212 | 213 | func RegisterGreeterServer(s *grpc.Server, srv GreeterServer) { 214 | s.RegisterService(&_Greeter_serviceDesc, srv) 215 | } 216 | 217 | func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 218 | in := new(HelloRequest) 219 | if err := dec(in); err != nil { 220 | return nil, err 221 | } 222 | if interceptor == nil { 223 | return srv.(GreeterServer).SayHello(ctx, in) 224 | } 225 | info := &grpc.UnaryServerInfo{ 226 | Server: srv, 227 | FullMethod: "/proto.Greeter/SayHello", 228 | } 229 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 230 | return srv.(GreeterServer).SayHello(ctx, req.(*HelloRequest)) 231 | } 232 | return interceptor(ctx, in, info, handler) 233 | } 234 | 235 | func _Greeter_SayHelloStream_Handler(srv interface{}, stream grpc.ServerStream) error { 236 | return srv.(GreeterServer).SayHelloStream(&greeterSayHelloStreamServer{stream}) 237 | } 238 | 239 | type Greeter_SayHelloStreamServer interface { 240 | Send(*HelloReply) error 241 | Recv() (*HelloRequest, error) 242 | grpc.ServerStream 243 | } 244 | 245 | type greeterSayHelloStreamServer struct { 246 | grpc.ServerStream 247 | } 248 | 249 | func (x *greeterSayHelloStreamServer) Send(m *HelloReply) error { 250 | return x.ServerStream.SendMsg(m) 251 | } 252 | 253 | func (x *greeterSayHelloStreamServer) Recv() (*HelloRequest, error) { 254 | m := new(HelloRequest) 255 | if err := x.ServerStream.RecvMsg(m); err != nil { 256 | return nil, err 257 | } 258 | return m, nil 259 | } 260 | 261 | var _Greeter_serviceDesc = grpc.ServiceDesc{ 262 | ServiceName: "proto.Greeter", 263 | HandlerType: (*GreeterServer)(nil), 264 | Methods: []grpc.MethodDesc{ 265 | { 266 | MethodName: "SayHello", 267 | Handler: _Greeter_SayHello_Handler, 268 | }, 269 | }, 270 | Streams: []grpc.StreamDesc{ 271 | { 272 | StreamName: "SayHelloStream", 273 | Handler: _Greeter_SayHelloStream_Handler, 274 | ServerStreams: true, 275 | ClientStreams: true, 276 | }, 277 | }, 278 | Metadata: "helloworld.proto", 279 | } 280 | -------------------------------------------------------------------------------- /grpc-example/simple/server/proto/helloworld.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package proto; 4 | 5 | // The greeting service definition. 6 | service Greeter { 7 | // Sends a greeting 8 | rpc SayHello (HelloRequest) returns (HelloReply) {} 9 | // Sends stream message 10 | rpc SayHelloStream (stream HelloRequest) returns (stream HelloReply) {} 11 | } 12 | 13 | // The request message containing the user's name. 14 | message HelloRequest { 15 | string name = 1; 16 | } 17 | 18 | // The response message containing the greetings 19 | message HelloReply { 20 | string message = 1; 21 | } -------------------------------------------------------------------------------- /leetcode/206-reverse-linked-list.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type ListNode struct { 6 | Val int 7 | Next *ListNode 8 | } 9 | 10 | func reverse(head *ListNode) *ListNode { 11 | var pre *ListNode 12 | cur := head 13 | 14 | for cur != nil { 15 | next := cur.Next 16 | cur.Next = pre 17 | pre = cur 18 | cur = next 19 | } 20 | 21 | return pre 22 | } 23 | 24 | func main() { 25 | head := &ListNode{Val: 1} 26 | node1 := &ListNode{Val: 2} 27 | node2 := &ListNode{Val: 3} 28 | node3 := &ListNode{Val: 4} 29 | node4 := &ListNode{Val: 5} 30 | 31 | head.Next = node1 32 | node1.Next = node2 33 | node2.Next = node3 34 | node3.Next = node4 35 | 36 | reversedHead := reverse(head) 37 | 38 | for reversedHead != nil { 39 | fmt.Println(reversedHead.Val) 40 | reversedHead = reversedHead.Next 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /openai-example/go.mod: -------------------------------------------------------------------------------- 1 | module openai-example 2 | 3 | go 1.17 4 | 5 | require github.com/sashabaranov/go-openai v1.5.7 6 | -------------------------------------------------------------------------------- /openai-example/go.sum: -------------------------------------------------------------------------------- 1 | github.com/sashabaranov/go-openai v1.5.7 h1:8DGgRG+P7yWixte5j720y6yiXgY3Hlgcd0gcpHdltfo= 2 | github.com/sashabaranov/go-openai v1.5.7/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg= 3 | -------------------------------------------------------------------------------- /openai-example/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "net/http" 7 | "net/url" 8 | 9 | openai "github.com/sashabaranov/go-openai" 10 | ) 11 | 12 | func main() { 13 | // use proxy 14 | config := openai.DefaultConfig("your openai key") 15 | proxyUrl, err := url.Parse("your proxy url") 16 | if err != nil { 17 | panic(err) 18 | } 19 | transport := &http.Transport{ 20 | Proxy: http.ProxyURL(proxyUrl), 21 | } 22 | config.HTTPClient = &http.Client{ 23 | Transport: transport, 24 | } 25 | 26 | client := openai.NewClientWithConfig(config) 27 | 28 | // direct 29 | // client := openai.NewClient("your openai key") 30 | resp, err := client.CreateChatCompletion( 31 | context.Background(), 32 | openai.ChatCompletionRequest{ 33 | Model: openai.GPT3Dot5Turbo, 34 | Messages: []openai.ChatCompletionMessage{ 35 | { 36 | Role: openai.ChatMessageRoleUser, 37 | Content: "Hello!", 38 | }, 39 | }, 40 | }, 41 | ) 42 | 43 | if err != nil { 44 | fmt.Printf("ChatCompletion error: %v\n", err) 45 | return 46 | } 47 | 48 | fmt.Println(resp.Choices[0].Message.Content) 49 | } 50 | --------------------------------------------------------------------------------