├── LICENSE.md ├── README.md ├── apt.txt ├── examples ├── Elman_srnn.png ├── Feed-Forward-Recurrent-NN.ipynb ├── Feed_forward_neural_net.gif ├── Pattern-Recognition.ipynb ├── Simple-Example.ipynb ├── Stateful-Goroutines.ipynb ├── Time-Formatting-Parsing.ipynb ├── Worker-Pools.ipynb └── iris.jpg ├── index.ipynb └── postBuild /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 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 | mybinder-go 2 | ========= 3 | 4 | A [mybinder](https://mybinder.org) compatible Jupyter notebook for [Go](https://golang.org). 5 | 6 | [![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/gopherdata/mybinder-go/master?urlpath=lab) 7 | 8 | -------------------------------------------------------------------------------- /apt.txt: -------------------------------------------------------------------------------- 1 | build-essential 2 | ca-certificates 3 | curl 4 | gcc 5 | git 6 | libgles2 7 | libgles2-mesa-dev 8 | mercurial 9 | pkg-config 10 | python3-pip 11 | -------------------------------------------------------------------------------- /examples/Elman_srnn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gopherdata/mybinder-go/5416b6cd1576b545a8d8c98574b4df55d8cfbd23/examples/Elman_srnn.png -------------------------------------------------------------------------------- /examples/Feed-Forward-Recurrent-NN.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": { 7 | "collapsed": true 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "import \"github.com/goml/gobrain\"" 12 | ] 13 | }, 14 | { 15 | "cell_type": "code", 16 | "execution_count": 2, 17 | "metadata": { 18 | "collapsed": true 19 | }, 20 | "outputs": [], 21 | "source": [ 22 | "import \"math/rand\"" 23 | ] 24 | }, 25 | { 26 | "cell_type": "markdown", 27 | "metadata": {}, 28 | "source": [ 29 | "# Feed Forward vs. Recurrent Neural Networks" 30 | ] 31 | }, 32 | { 33 | "cell_type": "markdown", 34 | "metadata": {}, 35 | "source": [ 36 | "(comments from [wikipedia](https://en.wikipedia.org), examples from the [gobrain](https://github.com/goml/gobrain) documentation)" 37 | ] 38 | }, 39 | { 40 | "cell_type": "markdown", 41 | "metadata": {}, 42 | "source": [ 43 | "## Feed Forward Description:" 44 | ] 45 | }, 46 | { 47 | "cell_type": "markdown", 48 | "metadata": {}, 49 | "source": [ 50 | "" 51 | ] 52 | }, 53 | { 54 | "cell_type": "markdown", 55 | "metadata": {}, 56 | "source": [ 57 | "A feedforward neural network is an artificial neural network where connections between the units do not form a cycle. This is different from recurrent neural networks.\n", 58 | "\n", 59 | "The feedforward neural network was the first and simplest type of artificial neural network devised. In this network, the information moves in only one direction, forward, from the input nodes, through the hidden nodes (if any) and to the output nodes. There are no cycles or loops in the network." 60 | ] 61 | }, 62 | { 63 | "cell_type": "markdown", 64 | "metadata": {}, 65 | "source": [ 66 | "## [Gobrain](https://github.com/goml/gobrain) Example - Feed Forward Function" 67 | ] 68 | }, 69 | { 70 | "cell_type": "code", 71 | "execution_count": 3, 72 | "metadata": { 73 | "collapsed": true 74 | }, 75 | "outputs": [], 76 | "source": [ 77 | "// set the random seed to 0\n", 78 | "rand.Seed(0)" 79 | ] 80 | }, 81 | { 82 | "cell_type": "code", 83 | "execution_count": 4, 84 | "metadata": { 85 | "collapsed": false 86 | }, 87 | "outputs": [ 88 | { 89 | "data": { 90 | "text/plain": [ 91 | "&gobrain.\u001b[32mFeedForward\u001b[0m{\n", 92 | " \u001b[33mNInputs\u001b[0m: \u001b[34m\u001b[1m0\u001b[0m,\n", 93 | " \u001b[33mNHiddens\u001b[0m: \u001b[34m\u001b[1m0\u001b[0m,\n", 94 | " \u001b[33mNOutputs\u001b[0m: \u001b[34m\u001b[1m0\u001b[0m,\n", 95 | " \u001b[33mRegression\u001b[0m: \u001b[36m\u001b[1mfalse\u001b[0m,\n", 96 | " \u001b[33mInputActivations\u001b[0m: []\u001b[32mfloat64\u001b[0m{},\n", 97 | " \u001b[33mHiddenActivations\u001b[0m: []\u001b[32mfloat64\u001b[0m{},\n", 98 | " \u001b[33mOutputActivations\u001b[0m: []\u001b[32mfloat64\u001b[0m{},\n", 99 | " \u001b[33mContexts\u001b[0m: []\u001b[32m[]float64\u001b[0m{},\n", 100 | " \u001b[33mInputWeights\u001b[0m: []\u001b[32m[]float64\u001b[0m{},\n", 101 | " \u001b[33mOutputWeights\u001b[0m: []\u001b[32m[]float64\u001b[0m{},\n", 102 | " \u001b[33mInputChanges\u001b[0m: []\u001b[32m[]float64\u001b[0m{},\n", 103 | " \u001b[33mOutputChanges\u001b[0m: []\u001b[32m[]float64\u001b[0m{},\n", 104 | "}\n" 105 | ] 106 | }, 107 | "execution_count": 4, 108 | "metadata": {}, 109 | "output_type": "execute_result" 110 | } 111 | ], 112 | "source": [ 113 | "// create the XOR representation patter to train the network\n", 114 | "patterns := [][][]float64{\n", 115 | " {{0, 0}, {0}},\n", 116 | " {{0, 1}, {1}},\n", 117 | " {{1, 0}, {1}},\n", 118 | " {{1, 1}, {0}},\n", 119 | "}\n", 120 | "\n", 121 | "// instantiate the Feed Forward\n", 122 | "ff := &gobrain.FeedForward{}" 123 | ] 124 | }, 125 | { 126 | "cell_type": "code", 127 | "execution_count": 5, 128 | "metadata": { 129 | "collapsed": true 130 | }, 131 | "outputs": [], 132 | "source": [ 133 | "// initialize the Neural Network;\n", 134 | "// the networks structure will contain:\n", 135 | "// 2 inputs, 2 hidden nodes and 1 output.\n", 136 | "ff.Init(2, 2, 1)" 137 | ] 138 | }, 139 | { 140 | "cell_type": "code", 141 | "execution_count": 6, 142 | "metadata": { 143 | "collapsed": false 144 | }, 145 | "outputs": [ 146 | { 147 | "data": { 148 | "text/plain": [ 149 | "0 0.5524794213542835\n", 150 | "[0 0] -> [0.05750394570844524] : [0]\n", 151 | "[0 1] -> [0.9301006350712102] : [1]\n", 152 | "[1 0] -> [0.927809966227284] : [1]\n", 153 | "[1 1] -> [0.09740879532462095] : [0]\n" 154 | ] 155 | }, 156 | "execution_count": 6, 157 | "metadata": {}, 158 | "output_type": "execute_result" 159 | } 160 | ], 161 | "source": [ 162 | "// train the network using the XOR patterns\n", 163 | "// the training will run for 1000 epochs\n", 164 | "// the learning rate is set to 0.6 and the momentum factor to 0.4\n", 165 | "// use true in the last parameter to receive reports about the learning error\n", 166 | "ff.Train(patterns, 1000, 0.6, 0.4, true)\n", 167 | "ff.Test(patterns)" 168 | ] 169 | }, 170 | { 171 | "cell_type": "markdown", 172 | "metadata": {}, 173 | "source": [ 174 | "Where the first values are the inputs, the values after the arrow `->` are the output values from the network and the values after `:` are the expected outputs." 175 | ] 176 | }, 177 | { 178 | "cell_type": "markdown", 179 | "metadata": {}, 180 | "source": [ 181 | "## Recurrent Description:" 182 | ] 183 | }, 184 | { 185 | "cell_type": "markdown", 186 | "metadata": {}, 187 | "source": [ 188 | "" 189 | ] 190 | }, 191 | { 192 | "cell_type": "markdown", 193 | "metadata": {}, 194 | "source": [ 195 | "A recurrent neural network (RNN) is a class of artificial neural network where connections between units form a directed cycle. This creates an internal state of the network which allows it to exhibit dynamic temporal behavior. Unlike feedforward neural networks, RNNs can use their internal memory to process arbitrary sequences of inputs. This makes them applicable to tasks such as unsegmented connected handwriting recognition or speech recognition." 196 | ] 197 | }, 198 | { 199 | "cell_type": "markdown", 200 | "metadata": {}, 201 | "source": [ 202 | "## [Gobrain](https://github.com/goml/gobrain) - Recurrent Example" 203 | ] 204 | }, 205 | { 206 | "cell_type": "markdown", 207 | "metadata": {}, 208 | "source": [ 209 | "Gobrain implements Elman's Simple Recurrent Network. To take advantage of this, one can use the `SetContexts` function." 210 | ] 211 | }, 212 | { 213 | "cell_type": "code", 214 | "execution_count": 7, 215 | "metadata": { 216 | "collapsed": false 217 | }, 218 | "outputs": [ 219 | { 220 | "data": { 221 | "text/plain": [ 222 | "0 0.5524794213542835\n", 223 | "[0 0] -> [0.05750394570844524] : [0]\n", 224 | "[0 1] -> [0.9301006350712102] : [1]\n", 225 | "[1 0] -> [0.927809966227284] : [1]\n", 226 | "[1 1] -> [0.09740879532462095] : [0]\n" 227 | ] 228 | }, 229 | "execution_count": 7, 230 | "metadata": {}, 231 | "output_type": "execute_result" 232 | } 233 | ], 234 | "source": [ 235 | "ff.SetContexts(1, nil)" 236 | ] 237 | }, 238 | { 239 | "cell_type": "markdown", 240 | "metadata": {}, 241 | "source": [ 242 | "In the example above, a single context will be created initilized with 0.5. " 243 | ] 244 | } 245 | ], 246 | "metadata": { 247 | "kernelspec": { 248 | "display_name": "Golang", 249 | "language": "go", 250 | "name": "gophernotes" 251 | }, 252 | "language_info": { 253 | "name": "go" 254 | } 255 | }, 256 | "nbformat": 4, 257 | "nbformat_minor": 0 258 | } 259 | -------------------------------------------------------------------------------- /examples/Feed_forward_neural_net.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gopherdata/mybinder-go/5416b6cd1576b545a8d8c98574b4df55d8cfbd23/examples/Feed_forward_neural_net.gif -------------------------------------------------------------------------------- /examples/Pattern-Recognition.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Imports" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": 1, 13 | "metadata": { 14 | "collapsed": true 15 | }, 16 | "outputs": [], 17 | "source": [ 18 | "import \"fmt\"" 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": 2, 24 | "metadata": { 25 | "collapsed": false 26 | }, 27 | "outputs": [], 28 | "source": [ 29 | "import \"github.com/sjwhitworth/golearn/base\"" 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": 3, 35 | "metadata": { 36 | "collapsed": true 37 | }, 38 | "outputs": [], 39 | "source": [ 40 | "import \"github.com/sjwhitworth/golearn/evaluation\"" 41 | ] 42 | }, 43 | { 44 | "cell_type": "code", 45 | "execution_count": 4, 46 | "metadata": { 47 | "collapsed": true 48 | }, 49 | "outputs": [], 50 | "source": [ 51 | "import \"github.com/sjwhitworth/golearn/knn\"" 52 | ] 53 | }, 54 | { 55 | "cell_type": "markdown", 56 | "metadata": {}, 57 | "source": [ 58 | "# Problem/Data Description" 59 | ] 60 | }, 61 | { 62 | "cell_type": "markdown", 63 | "metadata": {}, 64 | "source": [ 65 | "" 66 | ] 67 | }, 68 | { 69 | "cell_type": "markdown", 70 | "metadata": {}, 71 | "source": [ 72 | "Information about this dataset comes from [here](https://archive.ics.uci.edu/ml/datasets/Iris)" 73 | ] 74 | }, 75 | { 76 | "cell_type": "markdown", 77 | "metadata": {}, 78 | "source": [ 79 | "## Data Set Information:" 80 | ] 81 | }, 82 | { 83 | "cell_type": "markdown", 84 | "metadata": {}, 85 | "source": [ 86 | "This is perhaps the best known database to be found in the pattern recognition literature. Fisher's paper is a classic in the field and is referenced frequently to this day. (See Duda & Hart, for example.) The data set contains 3 classes of 50 instances each, where each class refers to a type of iris plant. One class is linearly separable from the other 2; the latter are NOT linearly separable from each other. \n", 87 | "\n", 88 | "Predicted attribute: class of iris plant. " 89 | ] 90 | }, 91 | { 92 | "cell_type": "markdown", 93 | "metadata": {}, 94 | "source": [ 95 | "## Attribute Information:" 96 | ] 97 | }, 98 | { 99 | "cell_type": "markdown", 100 | "metadata": {}, 101 | "source": [ 102 | "1. sepal length in cm \n", 103 | "2. sepal width in cm \n", 104 | "3. petal length in cm \n", 105 | "4. petal width in cm \n", 106 | "5. class: \n", 107 | "-- Iris Setosa \n", 108 | "-- Iris Versicolour \n", 109 | "-- Iris Virginica" 110 | ] 111 | }, 112 | { 113 | "cell_type": "markdown", 114 | "metadata": {}, 115 | "source": [ 116 | "# Building a Pattern Recognition Model" 117 | ] 118 | }, 119 | { 120 | "cell_type": "markdown", 121 | "metadata": {}, 122 | "source": [ 123 | "This example model comes from the [golearn](https://github.com/sjwhitworth/golearn) documentation." 124 | ] 125 | }, 126 | { 127 | "cell_type": "code", 128 | "execution_count": 5, 129 | "metadata": { 130 | "collapsed": false 131 | }, 132 | "outputs": [ 133 | { 134 | "data": { 135 | "text/plain": [ 136 | "Optimisations are switched off\n", 137 | "KNN: 1.14 % done\n", 138 | "KNN: 2.27 % done\n", 139 | "KNN: 3.41 % done\n", 140 | "KNN: 4.55 % done\n", 141 | "KNN: 5.68 % done\n", 142 | "KNN: 6.82 % done\n", 143 | "KNN: 7.95 % done\n", 144 | "KNN: 9.09 % done\n", 145 | "KNN: 10.23 % done\n", 146 | "KNN: 11.36 % done\n", 147 | "KNN: 12.50 % done\n", 148 | "KNN: 13.64 % done\n", 149 | "KNN: 14.77 % done\n", 150 | "KNN: 15.91 % done\n", 151 | "KNN: 17.05 % done\n", 152 | "KNN: 18.18 % done\n", 153 | "KNN: 19.32 % done\n", 154 | "KNN: 20.45 % done\n", 155 | "KNN: 21.59 % done\n", 156 | "KNN: 22.73 % done\n", 157 | "KNN: 23.86 % done\n", 158 | "KNN: 25.00 % done\n", 159 | "KNN: 26.14 % done\n", 160 | "KNN: 27.27 % done\n", 161 | "KNN: 28.41 % done\n", 162 | "KNN: 29.55 % done\n", 163 | "KNN: 30.68 % done\n", 164 | "KNN: 31.82 % done\n", 165 | "KNN: 32.95 % done\n", 166 | "KNN: 34.09 % done\n", 167 | "KNN: 35.23 % done\n", 168 | "KNN: 36.36 % done\n", 169 | "KNN: 37.50 % done\n", 170 | "KNN: 38.64 % done\n", 171 | "KNN: 39.77 % done\n", 172 | "KNN: 40.91 % done\n", 173 | "KNN: 42.05 % done\n", 174 | "KNN: 43.18 % done\n", 175 | "KNN: 44.32 % done\n", 176 | "KNN: 45.45 % done\n", 177 | "KNN: 46.59 % done\n", 178 | "KNN: 47.73 % done\n", 179 | "KNN: 48.86 % done\n", 180 | "KNN: 50.00 % done\n", 181 | "KNN: 51.14 % done\n", 182 | "KNN: 52.27 % done\n", 183 | "KNN: 53.41 % done\n", 184 | "KNN: 54.55 % done\n", 185 | "KNN: 55.68 % done\n", 186 | "KNN: 56.82 % done\n", 187 | "KNN: 57.95 % done\n", 188 | "KNN: 59.09 % done\n", 189 | "KNN: 60.23 % done\n", 190 | "KNN: 61.36 % done\n", 191 | "KNN: 62.50 % done\n", 192 | "KNN: 63.64 % done\n", 193 | "KNN: 64.77 % done\n", 194 | "KNN: 65.91 % done\n", 195 | "KNN: 67.05 % done\n", 196 | "KNN: 68.18 % done\n", 197 | "KNN: 69.32 % done\n", 198 | "KNN: 70.45 % done\n", 199 | "KNN: 71.59 % done\n", 200 | "KNN: 72.73 % done\n", 201 | "KNN: 73.86 % done\n", 202 | "KNN: 75.00 % done\n", 203 | "KNN: 76.14 % done\n", 204 | "KNN: 77.27 % done\n", 205 | "KNN: 78.41 % done\n", 206 | "KNN: 79.55 % done\n", 207 | "KNN: 80.68 % done\n", 208 | "KNN: 81.82 % done\n", 209 | "KNN: 82.95 % done\n", 210 | "KNN: 84.09 % done\n", 211 | "KNN: 85.23 % done\n", 212 | "KNN: 86.36 % done\n", 213 | "KNN: 87.50 % done\n", 214 | "KNN: 88.64 % done\n", 215 | "KNN: 89.77 % done\n", 216 | "KNN: 90.91 % done\n", 217 | "KNN: 92.05 % done\n", 218 | "KNN: 93.18 % done\n", 219 | "KNN: 94.32 % done\n", 220 | "KNN: 95.45 % done\n", 221 | "KNN: 96.59 % done\n", 222 | "KNN: 97.73 % done\n", 223 | "KNN: 98.86 % done\n", 224 | "Reference Class\tTrue Positives\tFalse Positives\tTrue Negatives\tPrecision\tRecall\tF1 Score\n", 225 | "---------------\t--------------\t---------------\t--------------\t---------\t------\t--------\n", 226 | "Iris-setosa\t30\t\t0\t\t58\t\t1.0000\t\t1.0000\t1.0000\n", 227 | "Iris-virginica\t27\t\t1\t\t58\t\t0.9643\t\t0.9310\t0.9474\n", 228 | "Iris-versicolor\t28\t\t2\t\t57\t\t0.9333\t\t0.9655\t0.9492\n", 229 | "Overall accuracy: 0.9659\n", 230 | "\n" 231 | ] 232 | }, 233 | "execution_count": 5, 234 | "metadata": {}, 235 | "output_type": "execute_result" 236 | } 237 | ], 238 | "source": [ 239 | "// Load in a dataset, with headers. Header attributes will be stored.\n", 240 | "// Think of instances as a Data Frame structure in R or Pandas.\n", 241 | "// You can also create instances from scratch.\n", 242 | "rawData, err := base.ParseCSVToInstances(\"datasets/iris.csv\", false)\n", 243 | "\n", 244 | "//Initialises a new KNN classifier\n", 245 | "cls := knn.NewKnnClassifier(\"euclidean\", 2)\n", 246 | "\n", 247 | "//Do a training-test split\n", 248 | "trainData, testData := base.InstancesTrainTestSplit(rawData, 0.50)\n", 249 | "cls.Fit(trainData)\n", 250 | "\n", 251 | "//Calculates the Euclidean distance and returns the most popular label\n", 252 | "predictions := cls.Predict(testData)\n", 253 | "\n", 254 | "// Calculate precision/recall metrics, and summarize results\n", 255 | "confusionMat, err := evaluation.GetConfusionMatrix(testData, predictions)\n", 256 | "fmt.Println(evaluation.GetSummary(confusionMat))" 257 | ] 258 | } 259 | ], 260 | "metadata": { 261 | "kernelspec": { 262 | "display_name": "Golang", 263 | "language": "go", 264 | "name": "gophernotes" 265 | }, 266 | "language_info": { 267 | "name": "go" 268 | } 269 | }, 270 | "nbformat": 4, 271 | "nbformat_minor": 0 272 | } 273 | -------------------------------------------------------------------------------- /examples/Simple-Example.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Imports" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": 1, 13 | "metadata": { 14 | "collapsed": true 15 | }, 16 | "outputs": [], 17 | "source": [ 18 | "import \"fmt\"" 19 | ] 20 | }, 21 | { 22 | "cell_type": "markdown", 23 | "metadata": {}, 24 | "source": [ 25 | "# Hello World" 26 | ] 27 | }, 28 | { 29 | "cell_type": "code", 30 | "execution_count": 2, 31 | "metadata": { 32 | "collapsed": false 33 | }, 34 | "outputs": [ 35 | { 36 | "data": { 37 | "text/plain": [ 38 | "\u001b[31m\u001b[1m\"\u001b[0m\u001b[31mworld\u001b[0m\u001b[31m\u001b[1m\"\u001b[0m\n" 39 | ] 40 | }, 41 | "execution_count": 2, 42 | "metadata": {}, 43 | "output_type": "execute_result" 44 | } 45 | ], 46 | "source": [ 47 | "world := \"world\"" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": 3, 53 | "metadata": { 54 | "collapsed": false 55 | }, 56 | "outputs": [ 57 | { 58 | "data": { 59 | "text/plain": [ 60 | "\u001b[31m\u001b[1m\"\u001b[0m\u001b[31mhello world\u001b[0m\u001b[31m\u001b[1m\"\u001b[0m\n" 61 | ] 62 | }, 63 | "execution_count": 3, 64 | "metadata": {}, 65 | "output_type": "execute_result" 66 | } 67 | ], 68 | "source": [ 69 | "fmt.Sprintf(\"hello %s\", world)" 70 | ] 71 | }, 72 | { 73 | "cell_type": "markdown", 74 | "metadata": {}, 75 | "source": [ 76 | "# Channels" 77 | ] 78 | }, 79 | { 80 | "cell_type": "markdown", 81 | "metadata": {}, 82 | "source": [ 83 | "Here is a simple example of a channel. " 84 | ] 85 | }, 86 | { 87 | "cell_type": "code", 88 | "execution_count": 4, 89 | "metadata": { 90 | "collapsed": false 91 | }, 92 | "outputs": [ 93 | { 94 | "data": { 95 | "text/plain": [ 96 | "(\u001b[32mchan string\u001b[0m)(\u001b[34m\u001b[1m0xc820018120\u001b[0m)\n" 97 | ] 98 | }, 99 | "execution_count": 4, 100 | "metadata": {}, 101 | "output_type": "execute_result" 102 | } 103 | ], 104 | "source": [ 105 | "messages := make(chan string)" 106 | ] 107 | }, 108 | { 109 | "cell_type": "code", 110 | "execution_count": 5, 111 | "metadata": { 112 | "collapsed": true 113 | }, 114 | "outputs": [], 115 | "source": [ 116 | "go func() { messages <- \"ping\" }()" 117 | ] 118 | }, 119 | { 120 | "cell_type": "code", 121 | "execution_count": 6, 122 | "metadata": { 123 | "collapsed": false 124 | }, 125 | "outputs": [ 126 | { 127 | "data": { 128 | "text/plain": [ 129 | "\u001b[31m\u001b[1m\"\u001b[0m\u001b[31mping\u001b[0m\u001b[31m\u001b[1m\"\u001b[0m\n" 130 | ] 131 | }, 132 | "execution_count": 6, 133 | "metadata": {}, 134 | "output_type": "execute_result" 135 | } 136 | ], 137 | "source": [ 138 | "msg := <- messages" 139 | ] 140 | }, 141 | { 142 | "cell_type": "code", 143 | "execution_count": null, 144 | "metadata": { 145 | "collapsed": true 146 | }, 147 | "outputs": [], 148 | "source": [] 149 | } 150 | ], 151 | "metadata": { 152 | "kernelspec": { 153 | "display_name": "Golang", 154 | "language": "go", 155 | "name": "gophernotes" 156 | }, 157 | "language_info": { 158 | "name": "go" 159 | } 160 | }, 161 | "nbformat": 4, 162 | "nbformat_minor": 0 163 | } 164 | -------------------------------------------------------------------------------- /examples/Stateful-Goroutines.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Stateful Goroutines" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "To synchronize access to shared state across multiple goroutines, one option is to use the built-in synchronization features of goroutines and channels. This channel-based approach aligns with Go’s ideas of sharing memory by communicating and having each piece of data owned by exactly 1 goroutine.\n", 15 | "\n", 16 | "Comments from [Go by Example](https://gobyexample.com)." 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": 1, 22 | "metadata": { 23 | "collapsed": true 24 | }, 25 | "outputs": [], 26 | "source": [ 27 | "import \"fmt\"" 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": 2, 33 | "metadata": { 34 | "collapsed": true 35 | }, 36 | "outputs": [], 37 | "source": [ 38 | "import \"math/rand\"" 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "execution_count": 3, 44 | "metadata": { 45 | "collapsed": true 46 | }, 47 | "outputs": [], 48 | "source": [ 49 | "import \"sync/atomic\"" 50 | ] 51 | }, 52 | { 53 | "cell_type": "code", 54 | "execution_count": 4, 55 | "metadata": { 56 | "collapsed": true 57 | }, 58 | "outputs": [], 59 | "source": [ 60 | "import \"time\"" 61 | ] 62 | }, 63 | { 64 | "cell_type": "markdown", 65 | "metadata": {}, 66 | "source": [ 67 | "## `structs` to Encapsulate Requests" 68 | ] 69 | }, 70 | { 71 | "cell_type": "markdown", 72 | "metadata": {}, 73 | "source": [ 74 | "In this example our state will be owned by a single goroutine. This will guarantee that the data is never corrupted with concurrent access. In order to read or write that state, other goroutines will send messages to the owning goroutine and receive corresponding replies. These readOp and writeOp structs encapsulate those requests and a way for the owning goroutine to respond." 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": 5, 80 | "metadata": { 81 | "collapsed": true 82 | }, 83 | "outputs": [], 84 | "source": [ 85 | "type readOp struct {\n", 86 | " key int\n", 87 | " resp chan int\n", 88 | "}" 89 | ] 90 | }, 91 | { 92 | "cell_type": "code", 93 | "execution_count": 6, 94 | "metadata": { 95 | "collapsed": true 96 | }, 97 | "outputs": [], 98 | "source": [ 99 | "type writeOp struct {\n", 100 | " key int\n", 101 | " val int\n", 102 | " resp chan bool\n", 103 | "}" 104 | ] 105 | }, 106 | { 107 | "cell_type": "markdown", 108 | "metadata": {}, 109 | "source": [ 110 | "## Definitions" 111 | ] 112 | }, 113 | { 114 | "cell_type": "markdown", 115 | "metadata": {}, 116 | "source": [ 117 | "Count how many operations we perform." 118 | ] 119 | }, 120 | { 121 | "cell_type": "code", 122 | "execution_count": 7, 123 | "metadata": { 124 | "collapsed": true 125 | }, 126 | "outputs": [], 127 | "source": [ 128 | "var ops int64 = 0" 129 | ] 130 | }, 131 | { 132 | "cell_type": "markdown", 133 | "metadata": {}, 134 | "source": [ 135 | "The reads and writes channels will be used by other goroutines to issue read and write requests, respectively." 136 | ] 137 | }, 138 | { 139 | "cell_type": "code", 140 | "execution_count": 8, 141 | "metadata": { 142 | "collapsed": false 143 | }, 144 | "outputs": [ 145 | { 146 | "data": { 147 | "text/plain": [ 148 | "(chan *main.\u001b[32mwriteOp\u001b[0m)(\u001b[34m\u001b[1m0xc820018180\u001b[0m)\n" 149 | ] 150 | }, 151 | "execution_count": 8, 152 | "metadata": {}, 153 | "output_type": "execute_result" 154 | } 155 | ], 156 | "source": [ 157 | "reads := make(chan *readOp)\n", 158 | "writes := make(chan *writeOp)" 159 | ] 160 | }, 161 | { 162 | "cell_type": "markdown", 163 | "metadata": {}, 164 | "source": [ 165 | "## Goroutines" 166 | ] 167 | }, 168 | { 169 | "cell_type": "markdown", 170 | "metadata": {}, 171 | "source": [ 172 | "Here is the goroutine that owns the state, which is a map as in the previous example but now private to the stateful goroutine. This goroutine repeatedly selects on the reads and writes channels, responding to requests as they arrive. A response is executed by first performing the requested operation and then sending a value on the response channel resp to indicate success (and the desired value in the case of reads)." 173 | ] 174 | }, 175 | { 176 | "cell_type": "code", 177 | "execution_count": 9, 178 | "metadata": { 179 | "collapsed": true 180 | }, 181 | "outputs": [], 182 | "source": [ 183 | "go func() {\n", 184 | " var state = make(map[int]int)\n", 185 | " for {\n", 186 | " select {\n", 187 | " case read := <-reads:\n", 188 | " read.resp <- state[read.key]\n", 189 | " case write := <-writes:\n", 190 | " state[write.key] = write.val\n", 191 | " write.resp <- true\n", 192 | " }\n", 193 | " }\n", 194 | "}()" 195 | ] 196 | }, 197 | { 198 | "cell_type": "markdown", 199 | "metadata": {}, 200 | "source": [ 201 | "This starts 100 goroutines to issue reads to the state-owning goroutine via the reads channel. Each read requires constructing a readOp, sending it over the reads channel, and the receiving the result over the provided resp channel." 202 | ] 203 | }, 204 | { 205 | "cell_type": "code", 206 | "execution_count": 10, 207 | "metadata": { 208 | "collapsed": true 209 | }, 210 | "outputs": [], 211 | "source": [ 212 | "for r := 0; r < 100; r++ {\n", 213 | " go func() {\n", 214 | " for {\n", 215 | " read := &readOp{\n", 216 | " key: rand.Intn(5),\n", 217 | " resp: make(chan int)}\n", 218 | " reads <- read\n", 219 | " <-read.resp\n", 220 | " atomic.AddInt64(&ops, 1)\n", 221 | " }\n", 222 | " }()\n", 223 | "}" 224 | ] 225 | }, 226 | { 227 | "cell_type": "markdown", 228 | "metadata": {}, 229 | "source": [ 230 | "We start 10 writes as well, using a similar approach." 231 | ] 232 | }, 233 | { 234 | "cell_type": "code", 235 | "execution_count": 11, 236 | "metadata": { 237 | "collapsed": true 238 | }, 239 | "outputs": [], 240 | "source": [ 241 | "for w := 0; w < 10; w++ {\n", 242 | " go func() {\n", 243 | " for {\n", 244 | " write := &writeOp{\n", 245 | " key: rand.Intn(5),\n", 246 | " val: rand.Intn(100),\n", 247 | " resp: make(chan bool)}\n", 248 | " writes <- write\n", 249 | " <-write.resp\n", 250 | " atomic.AddInt64(&ops, 1)\n", 251 | " }\n", 252 | " }()\n", 253 | "}\n", 254 | "// let the goroutines work for a second\n", 255 | "time.Sleep(time.Second)" 256 | ] 257 | }, 258 | { 259 | "cell_type": "markdown", 260 | "metadata": {}, 261 | "source": [ 262 | "## Collect the Ops Count" 263 | ] 264 | }, 265 | { 266 | "cell_type": "markdown", 267 | "metadata": {}, 268 | "source": [ 269 | "Let the goroutines work for a second. Finally, capture and report the ops count." 270 | ] 271 | }, 272 | { 273 | "cell_type": "code", 274 | "execution_count": 12, 275 | "metadata": { 276 | "collapsed": false 277 | }, 278 | "outputs": [ 279 | { 280 | "data": { 281 | "text/plain": [ 282 | "\u001b[34m\u001b[1m892297\u001b[0m\n" 283 | ] 284 | }, 285 | "execution_count": 12, 286 | "metadata": {}, 287 | "output_type": "execute_result" 288 | } 289 | ], 290 | "source": [ 291 | "opsFinal := atomic.LoadInt64(&ops)" 292 | ] 293 | }, 294 | { 295 | "cell_type": "markdown", 296 | "metadata": {}, 297 | "source": [ 298 | "Running our program shows that the goroutine-based state management example achieves about 800,000 operations per second." 299 | ] 300 | } 301 | ], 302 | "metadata": { 303 | "kernelspec": { 304 | "display_name": "Golang", 305 | "language": "go", 306 | "name": "gophernotes" 307 | }, 308 | "language_info": { 309 | "name": "go" 310 | } 311 | }, 312 | "nbformat": 4, 313 | "nbformat_minor": 0 314 | } 315 | -------------------------------------------------------------------------------- /examples/Time-Formatting-Parsing.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Time Formatting / Parsing" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "Go supports time formatting and parsing via pattern-based layouts. Comments from [Go by Example](https://gobyexample.com)." 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "## Imports" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 1, 27 | "metadata": { 28 | "collapsed": true 29 | }, 30 | "outputs": [], 31 | "source": [ 32 | "import \"fmt\"" 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": 2, 38 | "metadata": { 39 | "collapsed": true 40 | }, 41 | "outputs": [], 42 | "source": [ 43 | "import \"time\"" 44 | ] 45 | }, 46 | { 47 | "cell_type": "markdown", 48 | "metadata": {}, 49 | "source": [ 50 | "## Basic Time Formatting" 51 | ] 52 | }, 53 | { 54 | "cell_type": "markdown", 55 | "metadata": {}, 56 | "source": [ 57 | "Here’s a basic example of formatting a time according to RFC3339, using the corresponding layout constant." 58 | ] 59 | }, 60 | { 61 | "cell_type": "code", 62 | "execution_count": 3, 63 | "metadata": { 64 | "collapsed": false 65 | }, 66 | "outputs": [ 67 | { 68 | "data": { 69 | "text/plain": [ 70 | "\u001b[34m\u001b[1m2016\u001b[0m-\u001b[34m\u001b[1m01\u001b[0m-\u001b[34m\u001b[1m23\u001b[0m \u001b[34m\u001b[1m20\u001b[0m:\u001b[34m\u001b[1m14\u001b[0m:\u001b[34m\u001b[1m59\u001b[0m \u001b[34m\u001b[1mLocal\u001b[0m\n" 71 | ] 72 | }, 73 | "execution_count": 3, 74 | "metadata": {}, 75 | "output_type": "execute_result" 76 | } 77 | ], 78 | "source": [ 79 | "t := time.Now()" 80 | ] 81 | }, 82 | { 83 | "cell_type": "code", 84 | "execution_count": 4, 85 | "metadata": { 86 | "collapsed": false 87 | }, 88 | "outputs": [ 89 | { 90 | "data": { 91 | "text/plain": [ 92 | "\u001b[31m\u001b[1m\"\u001b[0m\u001b[31m2016-01-23T20:15:00-06:00\u001b[0m\u001b[31m\u001b[1m\"\u001b[0m\n" 93 | ] 94 | }, 95 | "execution_count": 4, 96 | "metadata": {}, 97 | "output_type": "execute_result" 98 | } 99 | ], 100 | "source": [ 101 | "t.Format(time.RFC3339)" 102 | ] 103 | }, 104 | { 105 | "cell_type": "markdown", 106 | "metadata": {}, 107 | "source": [ 108 | "## Time Parsing" 109 | ] 110 | }, 111 | { 112 | "cell_type": "markdown", 113 | "metadata": {}, 114 | "source": [ 115 | "Time parsing uses the same layout values as Format." 116 | ] 117 | }, 118 | { 119 | "cell_type": "code", 120 | "execution_count": 5, 121 | "metadata": { 122 | "collapsed": false 123 | }, 124 | "outputs": [ 125 | { 126 | "data": { 127 | "text/plain": [ 128 | "\u001b[34m\u001b[1m2012\u001b[0m-\u001b[34m\u001b[1m11\u001b[0m-\u001b[34m\u001b[1m01\u001b[0m \u001b[34m\u001b[1m22\u001b[0m:\u001b[34m\u001b[1m08\u001b[0m:\u001b[34m\u001b[1m41\u001b[0m \u001b[34m\u001b[1m\u001b[0m\n" 129 | ] 130 | }, 131 | "execution_count": 5, 132 | "metadata": {}, 133 | "output_type": "execute_result" 134 | } 135 | ], 136 | "source": [ 137 | "t1, _ := time.Parse(\n", 138 | " time.RFC3339,\n", 139 | " \"2012-11-01T22:08:41+00:00\")" 140 | ] 141 | }, 142 | { 143 | "cell_type": "markdown", 144 | "metadata": {}, 145 | "source": [ 146 | "Parse will return an error on malformed input explaining the parsing problem." 147 | ] 148 | }, 149 | { 150 | "cell_type": "code", 151 | "execution_count": 6, 152 | "metadata": { 153 | "collapsed": false 154 | }, 155 | "outputs": [ 156 | { 157 | "data": { 158 | "text/plain": [ 159 | "&time.\u001b[32mParseError\u001b[0m{\n", 160 | " \u001b[33mLayout\u001b[0m: \u001b[31m\u001b[1m\"\u001b[0m\u001b[31mMon Jan _2 15:04:05 2006\u001b[0m\u001b[31m\u001b[1m\"\u001b[0m,\n", 161 | " \u001b[33mValue\u001b[0m: \u001b[31m\u001b[1m\"\u001b[0m\u001b[31m8:41PM\u001b[0m\u001b[31m\u001b[1m\"\u001b[0m,\n", 162 | " \u001b[33mLayoutElem\u001b[0m: \u001b[31m\u001b[1m\"\u001b[0m\u001b[31mMon\u001b[0m\u001b[31m\u001b[1m\"\u001b[0m,\n", 163 | " \u001b[33mValueElem\u001b[0m: \u001b[31m\u001b[1m\"\u001b[0m\u001b[31m8:41PM\u001b[0m\u001b[31m\u001b[1m\"\u001b[0m,\n", 164 | " \u001b[33mMessage\u001b[0m: \u001b[31m\u001b[1m\"\u001b[0m\u001b[31m\u001b[1m\"\u001b[0m,\n", 165 | "}\n" 166 | ] 167 | }, 168 | "execution_count": 6, 169 | "metadata": {}, 170 | "output_type": "execute_result" 171 | } 172 | ], 173 | "source": [ 174 | "ansic := \"Mon Jan _2 15:04:05 2006\"\n", 175 | "_, e := time.Parse(ansic, \"8:41PM\")" 176 | ] 177 | }, 178 | { 179 | "cell_type": "markdown", 180 | "metadata": {}, 181 | "source": [ 182 | "## Custom Layouts" 183 | ] 184 | }, 185 | { 186 | "cell_type": "markdown", 187 | "metadata": {}, 188 | "source": [ 189 | "Format and Parse use example-based layouts. Usually you’ll use a constant from time for these layouts, but you can also supply custom layouts. Layouts must use the reference time Mon Jan 2 15:04:05 MST 2006 to show the pattern with which to format/parse a given time/string. The example time must be exactly as shown: the year 2006, 15 for the hour, Monday for the day of the week, etc." 190 | ] 191 | }, 192 | { 193 | "cell_type": "code", 194 | "execution_count": 7, 195 | "metadata": { 196 | "collapsed": false 197 | }, 198 | "outputs": [ 199 | { 200 | "data": { 201 | "text/plain": [ 202 | "\u001b[31m\u001b[1m\"\u001b[0m\u001b[31m8:15PM\u001b[0m\u001b[31m\u001b[1m\"\u001b[0m\n" 203 | ] 204 | }, 205 | "execution_count": 7, 206 | "metadata": {}, 207 | "output_type": "execute_result" 208 | } 209 | ], 210 | "source": [ 211 | "t.Format(\"3:04PM\")" 212 | ] 213 | }, 214 | { 215 | "cell_type": "code", 216 | "execution_count": 8, 217 | "metadata": { 218 | "collapsed": false 219 | }, 220 | "outputs": [ 221 | { 222 | "data": { 223 | "text/plain": [ 224 | "\u001b[31m\u001b[1m\"\u001b[0m\u001b[31mSat Jan 23 20:15:01 2016\u001b[0m\u001b[31m\u001b[1m\"\u001b[0m\n" 225 | ] 226 | }, 227 | "execution_count": 8, 228 | "metadata": {}, 229 | "output_type": "execute_result" 230 | } 231 | ], 232 | "source": [ 233 | "t.Format(\"Mon Jan _2 15:04:05 2006\")" 234 | ] 235 | }, 236 | { 237 | "cell_type": "code", 238 | "execution_count": 9, 239 | "metadata": { 240 | "collapsed": false 241 | }, 242 | "outputs": [ 243 | { 244 | "data": { 245 | "text/plain": [ 246 | "\u001b[31m\u001b[1m\"\u001b[0m\u001b[31m2016-01-23T20:15:02.006035-06:00\u001b[0m\u001b[31m\u001b[1m\"\u001b[0m\n" 247 | ] 248 | }, 249 | "execution_count": 9, 250 | "metadata": {}, 251 | "output_type": "execute_result" 252 | } 253 | ], 254 | "source": [ 255 | "t.Format(\"2006-01-02T15:04:05.999999-07:00\")" 256 | ] 257 | }, 258 | { 259 | "cell_type": "code", 260 | "execution_count": 10, 261 | "metadata": { 262 | "collapsed": false 263 | }, 264 | "outputs": [ 265 | { 266 | "data": { 267 | "text/plain": [ 268 | "\u001b[34m\u001b[1m0\u001b[0m-\u001b[34m\u001b[1m01\u001b[0m-\u001b[34m\u001b[1m01\u001b[0m \u001b[34m\u001b[1m20\u001b[0m:\u001b[34m\u001b[1m41\u001b[0m:\u001b[34m\u001b[1m00\u001b[0m \u001b[34m\u001b[1mUTC\u001b[0m\n" 269 | ] 270 | }, 271 | "execution_count": 10, 272 | "metadata": {}, 273 | "output_type": "execute_result" 274 | } 275 | ], 276 | "source": [ 277 | "form := \"3 04 PM\"\n", 278 | "t2, _ := time.Parse(form, \"8 41 PM\")" 279 | ] 280 | }, 281 | { 282 | "cell_type": "markdown", 283 | "metadata": {}, 284 | "source": [ 285 | "## String Formatting" 286 | ] 287 | }, 288 | { 289 | "cell_type": "markdown", 290 | "metadata": {}, 291 | "source": [ 292 | "For purely numeric representations you can also use standard string formatting with the extracted components of the time value." 293 | ] 294 | }, 295 | { 296 | "cell_type": "code", 297 | "execution_count": 11, 298 | "metadata": { 299 | "collapsed": false 300 | }, 301 | "outputs": [ 302 | { 303 | "data": { 304 | "text/plain": [ 305 | "2016-01-23T20:15:02-00:00\n", 306 | "\u001b[34m\u001b[1m26\u001b[0m\n", 307 | "\u001b[36m\u001b[1mnil\u001b[0m\n" 308 | ] 309 | }, 310 | "execution_count": 11, 311 | "metadata": {}, 312 | "output_type": "execute_result" 313 | } 314 | ], 315 | "source": [ 316 | "fmt.Printf(\"%d-%02d-%02dT%02d:%02d:%02d-00:00\\n\",\n", 317 | " t.Year(), t.Month(), t.Day(),\n", 318 | " t.Hour(), t.Minute(), t.Second())" 319 | ] 320 | } 321 | ], 322 | "metadata": { 323 | "kernelspec": { 324 | "display_name": "Golang", 325 | "language": "go", 326 | "name": "gophernotes" 327 | }, 328 | "language_info": { 329 | "name": "go" 330 | } 331 | }, 332 | "nbformat": 4, 333 | "nbformat_minor": 0 334 | } 335 | -------------------------------------------------------------------------------- /examples/Worker-Pools.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Worker Pools" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "In this example we’ll look at how to implement a worker pool using goroutines and channels.\n", 15 | "\n", 16 | "Comments from [Go by Example](https://gobyexample.com)." 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": 1, 22 | "metadata": { 23 | "collapsed": true 24 | }, 25 | "outputs": [], 26 | "source": [ 27 | "import \"fmt\"" 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": 2, 33 | "metadata": { 34 | "collapsed": true 35 | }, 36 | "outputs": [], 37 | "source": [ 38 | "import \"time\"" 39 | ] 40 | }, 41 | { 42 | "cell_type": "markdown", 43 | "metadata": {}, 44 | "source": [ 45 | "## Worker Function" 46 | ] 47 | }, 48 | { 49 | "cell_type": "markdown", 50 | "metadata": {}, 51 | "source": [ 52 | "Here’s the worker, of which we’ll run several concurrent instances. These workers will receive work on the jobs channel and send the corresponding results on results. We’ll sleep a second per job to simulate an expensive task." 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "execution_count": 3, 58 | "metadata": { 59 | "collapsed": true 60 | }, 61 | "outputs": [], 62 | "source": [ 63 | "func worker(id int, jobs <-chan int, results chan<- int) {\n", 64 | " for j := range jobs {\n", 65 | " fmt.Println(\"worker\", id, \"processing job\", j)\n", 66 | " time.Sleep(time.Second)\n", 67 | " results <- j * 2\n", 68 | " }\n", 69 | "}" 70 | ] 71 | }, 72 | { 73 | "cell_type": "markdown", 74 | "metadata": {}, 75 | "source": [ 76 | "## Utilize Workers" 77 | ] 78 | }, 79 | { 80 | "cell_type": "markdown", 81 | "metadata": {}, 82 | "source": [ 83 | "In order to use our pool of workers we need to send them work and collect their results. We make 2 channels for this." 84 | ] 85 | }, 86 | { 87 | "cell_type": "code", 88 | "execution_count": 4, 89 | "metadata": { 90 | "collapsed": false 91 | }, 92 | "outputs": [ 93 | { 94 | "data": { 95 | "text/plain": [ 96 | "(\u001b[32mchan int\u001b[0m)(\u001b[34m\u001b[1m0xc820061500\u001b[0m)\n" 97 | ] 98 | }, 99 | "execution_count": 4, 100 | "metadata": {}, 101 | "output_type": "execute_result" 102 | } 103 | ], 104 | "source": [ 105 | "jobs := make(chan int, 100)\n", 106 | "results := make(chan int, 100)" 107 | ] 108 | }, 109 | { 110 | "cell_type": "markdown", 111 | "metadata": {}, 112 | "source": [ 113 | "Next, start up 3 workers, initially blocked because there are no jobs yet:" 114 | ] 115 | }, 116 | { 117 | "cell_type": "code", 118 | "execution_count": 5, 119 | "metadata": { 120 | "collapsed": false 121 | }, 122 | "outputs": [], 123 | "source": [ 124 | "for w := 1; w <= 3; w++ {\n", 125 | " go worker(w, jobs, results)\n", 126 | "}" 127 | ] 128 | }, 129 | { 130 | "cell_type": "markdown", 131 | "metadata": {}, 132 | "source": [ 133 | "Send 9 jobs and then close that channel to indicate that’s all the work we have:" 134 | ] 135 | }, 136 | { 137 | "cell_type": "code", 138 | "execution_count": 6, 139 | "metadata": { 140 | "collapsed": true 141 | }, 142 | "outputs": [], 143 | "source": [ 144 | "for j := 1; j <= 9; j++ {\n", 145 | " jobs <- j\n", 146 | "}\n", 147 | "close(jobs)" 148 | ] 149 | }, 150 | { 151 | "cell_type": "markdown", 152 | "metadata": {}, 153 | "source": [ 154 | "## Collect Results" 155 | ] 156 | }, 157 | { 158 | "cell_type": "markdown", 159 | "metadata": {}, 160 | "source": [ 161 | "Finally we collect all the results of the work:" 162 | ] 163 | }, 164 | { 165 | "cell_type": "code", 166 | "execution_count": 7, 167 | "metadata": { 168 | "collapsed": false 169 | }, 170 | "outputs": [ 171 | { 172 | "data": { 173 | "text/plain": [ 174 | "worker 3 processing job 1\n", 175 | "worker 1 processing job 2\n", 176 | "worker 2 processing job 3\n", 177 | "worker 3 processing job 5\n", 178 | "worker 2 processing job 4\n", 179 | "worker 1 processing job 6\n", 180 | "worker 3 processing job 8\n", 181 | "worker 1 processing job 7\n", 182 | "worker 2 processing job 9\n" 183 | ] 184 | }, 185 | "execution_count": 7, 186 | "metadata": {}, 187 | "output_type": "execute_result" 188 | } 189 | ], 190 | "source": [ 191 | "for a := 1; a <= 9; a++ {\n", 192 | " <-results\n", 193 | "}" 194 | ] 195 | }, 196 | { 197 | "cell_type": "markdown", 198 | "metadata": {}, 199 | "source": [ 200 | "Our running program shows the 9 jobs being executed by various workers. The program only takes about 3 seconds despite doing about 9 seconds of total work because there are 3 workers operating concurrently." 201 | ] 202 | } 203 | ], 204 | "metadata": { 205 | "kernelspec": { 206 | "display_name": "Golang", 207 | "language": "go", 208 | "name": "gophernotes" 209 | }, 210 | "language_info": { 211 | "name": "go" 212 | } 213 | }, 214 | "nbformat": 4, 215 | "nbformat_minor": 0 216 | } 217 | -------------------------------------------------------------------------------- /examples/iris.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gopherdata/mybinder-go/5416b6cd1576b545a8d8c98574b4df55d8cfbd23/examples/iris.jpg -------------------------------------------------------------------------------- /index.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Imports" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": 1, 13 | "metadata": { 14 | "collapsed": true 15 | }, 16 | "outputs": [], 17 | "source": [ 18 | "import \"fmt\"" 19 | ] 20 | }, 21 | { 22 | "cell_type": "markdown", 23 | "metadata": {}, 24 | "source": [ 25 | "# Hello World" 26 | ] 27 | }, 28 | { 29 | "cell_type": "code", 30 | "execution_count": 2, 31 | "metadata": { 32 | "collapsed": false 33 | }, 34 | "outputs": [ 35 | { 36 | "data": { 37 | "text/plain": [ 38 | "\u001b[31m\u001b[1m\"\u001b[0m\u001b[31mworld\u001b[0m\u001b[31m\u001b[1m\"\u001b[0m\n" 39 | ] 40 | }, 41 | "execution_count": 2, 42 | "metadata": {}, 43 | "output_type": "execute_result" 44 | } 45 | ], 46 | "source": [ 47 | "world := \"world\"" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": 3, 53 | "metadata": { 54 | "collapsed": false 55 | }, 56 | "outputs": [ 57 | { 58 | "data": { 59 | "text/plain": [ 60 | "\u001b[31m\u001b[1m\"\u001b[0m\u001b[31mhello world\u001b[0m\u001b[31m\u001b[1m\"\u001b[0m\n" 61 | ] 62 | }, 63 | "execution_count": 3, 64 | "metadata": {}, 65 | "output_type": "execute_result" 66 | } 67 | ], 68 | "source": [ 69 | "fmt.Sprintf(\"hello %s\", world)" 70 | ] 71 | } 72 | ], 73 | "metadata": { 74 | "kernelspec": { 75 | "display_name": "Golang", 76 | "language": "go", 77 | "name": "gophernotes" 78 | }, 79 | "language_info": { 80 | "name": "go" 81 | } 82 | }, 83 | "nbformat": 4, 84 | "nbformat_minor": 0 85 | } 86 | -------------------------------------------------------------------------------- /postBuild: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | GOVERS=1.17.6 6 | 7 | mkdir -p \ 8 | $HOME/.local/go/$GOVERS \ 9 | $HOME/go 10 | 11 | echo "::: install Go ${GOVERS}..." 12 | curl -O -L https://golang.org/dl/go${GOVERS}.linux-amd64.tar.gz 13 | tar -C $HOME/.local/go/$GOVERS -zxf go${GOVERS}.linux-amd64.tar.gz 14 | /bin/rm go${GOVERS}.linux-amd64.tar.gz 15 | 16 | export GOROOT=$HOME/.local/go/$GOVERS/go 17 | export GOPATH=$HOME/go 18 | export GO111MODULE=on 19 | export PATH=$GOPATH/bin:$GOROOT/bin:$PATH 20 | 21 | ## install interesting packages 22 | echo "::: installing gophernotes, gonum..." 23 | go get golang.org/x/tools/cmd/goimports 24 | go install github.com/gopherdata/gophernotes@latest 25 | go get github.com/goml/gobrain 26 | 27 | go get gonum.org/v1/plot/... 28 | go get gonum.org/v1/gonum/... 29 | go get github.com/go-gota/gota/... 30 | go get github.com/sajari/regression 31 | go get github.com/sjwhitworth/golearn/... 32 | go get go-hep.org/x/hep/csvutil/... 33 | go get go-hep.org/x/hep/fit 34 | go get go-hep.org/x/hep/hbook 35 | go get github.com/montanaflynn/stats 36 | go get github.com/boltdb/bolt 37 | go get github.com/patrickmn/go-cache 38 | go get github.com/chewxy/math32 39 | go get github.com/chewxy/hm 40 | go get gorgonia.org/vecf64 41 | go get gorgonia.org/vecf32 42 | go get github.com/awalterschulze/gographviz 43 | go get github.com/leesper/go_rng 44 | go get github.com/pkg/errors 45 | go get github.com/stretchr/testify/assert 46 | 47 | echo "::: installing gophernotes, gonum... [done]" 48 | 49 | ## setup environment for Go 50 | 51 | cat >> $HOME/.setup-go << EOF 52 | ## setup Go 53 | export GOROOT=$GOROOT 54 | export GOPATH=$GOPATH 55 | export GO111MODULE=on 56 | export PATH=\$GOPATH/bin:\$GOROOT/bin:\$PATH 57 | EOF 58 | 59 | cat >> $HOME/.bashrc << EOF 60 | . ~/.setup-go 61 | EOF 62 | 63 | ## install the Go kernel 64 | mkdir -p ./binder/gophernotes 65 | cat >| ./binder/gophernotes/kernel.json << EOF 66 | { 67 | "argv": [ 68 | "$GOPATH/bin/gophernotes", 69 | "{connection_file}" 70 | ], 71 | "display_name": "Go", 72 | "language": "go", 73 | "name": "go", 74 | "env": { 75 | "GOPATH": "$GOPATH", 76 | "GOROOT": "$GOROOT", 77 | "GO111MODULE": "on", 78 | "PATH": "$GOPATH/bin:$GOROOT/bin:$PATH" 79 | } 80 | } 81 | EOF 82 | jupyter kernelspec install ./binder/gophernotes --user 83 | 84 | /bin/rm -rf binder 85 | 86 | echo "::: kernel list" 87 | jupyter kernelspec list 88 | --------------------------------------------------------------------------------