1
+ <!DOCTYPE html>
2
+ < html >
3
+
4
+ < head >
5
+ < meta charset ="utf-8 ">
6
+ < meta http-equiv ="X-UA-Compatible " content ="IE=edge,chrome=1 ">
7
+ < title > go-linq: LINQ query functions over slices for Golang</ title >
8
+ < meta name ="viewport " content ="width=device-width ">
9
+ < link href ="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css " rel ="stylesheet ">
10
+ < link rel ="stylesheet " href ="css/main.css ">
11
+ < link href ='//fonts.googleapis.com/css?family=Roboto:300 ' rel ='stylesheet ' type ='text/css '>
12
+ < meta name ="author " content ="Ahmet Alp Balkan ">
13
+
14
+ < script type ="text/javascript " src ="//use.typekit.net/wnk8juw.js "> </ script >
15
+ < script type ="text/javascript "> try { Typekit . load ( ) ; } catch ( e ) { } </ script >
16
+ </ head >
17
+
18
+ < body >
19
+ < header >
20
+ < h1 > go-linq</ h1 >
21
+
22
+ < h2 > .NET's Language Integrated Query (LINQ) library for Go</ h2 >
23
+
24
+ < p >
25
+ Query and manipulate Go slices and collections using SQL-like methods.
26
+ < br /> Written in pure Go with no dependencies, tested with 100% code coverage.
27
+ </ p >
28
+
29
+ < div class ='promo '>
30
+ < p >
31
+ < iframe src ="http://ghbtns.com/github-btn.html?user=ahmetalpbalkan&repo=go-linq&type=watch&count=true&size=large " allowtransparency ="true "
32
+ frameborder ="0 " scrolling ="0 " width ="142px " height ="30px " style ='margin-left:30px '> </ iframe >
33
+ </ p >
34
+
35
+ < p >
36
+ < a class ='btn btn-default btn-lg ' href ='https://github.com/ahmetalpbalkan/go-linq '> Fork it!</ a >
37
+ < a class ='btn btn-default btn-lg ' href ='http://godoc.org/github.com/ahmetalpbalkan/go-linq '> GoDoc</ a >
38
+ </ p >
39
+
40
+ </ header >
41
+
42
+ < section class ='features '>
43
+ < div class ='inner row '>
44
+ < aside class ='col-md-4 '>
45
+ < h3 > Bring your type</ h3 >
46
+ < p >
47
+ There are no generics in Go, but
48
+ < nobr > go-linq</ nobr > supports arrays, slices, maps, strings and channels out-of-the-box, or any collection
49
+ that implements < code > .Comparable</ code > .
50
+ </ p >
51
+ </ aside >
52
+
53
+ < aside class ='col-md-4 '>
54
+ < h3 > Method syntax</ h3 >
55
+ < p style ='text-align: center; '>
56
+ < code > From(slice)</ code > < code > .Where(predicate)</ code > < code > .Select(selector)</ code > < code > .ToSlice(&result)</ code >
57
+ < br /> Easy as that. Just keep writing your queries.
58
+ </ p >
59
+ </ aside >
60
+
61
+ < aside class ='col-md-4 '>
62
+ < h3 > Concurrency</ h3 >
63
+ < p >
64
+ Your queries can share data between goroutines by calling < code > .FromChannel()</ code > and < code > .ToChannel()</ code > methods.
65
+ </ p >
66
+ </ aside >
67
+ </ div >
68
+ </ section >
69
+
70
+ < section class ='demo hidden-xs '>
71
+ < h2 > Basic</ h2 >
72
+ < p > Find average age of students over 20.</ p >
73
+ < div class ='inner row '>
74
+ < table >
75
+ < tr >
76
+ < td class ='docs '>
77
+ Import your < code > []Student</ code > .
78
+ </ td >
79
+
80
+ < td class ='code '> < code >
81
+ results := From(students).
82
+ </ code > </ td >
83
+ </ tr >
84
+
85
+ < tr >
86
+ < td class ='docs '>
87
+ Find those over 20.< br /> So we make type assertion to our input type.
88
+ </ td >
89
+
90
+ < td class ='code '> < code >
91
+ Where(func (s interface{}) bool {< br />
92
+ return s.(Student).age > = 20< br />
93
+ }).
94
+ </ code > </ td >
95
+ </ tr >
96
+
97
+ < tr >
98
+ < td class ='docs '>
99
+ Select their ages.
100
+ </ td >
101
+
102
+ < td class ='code '> < code >
103
+ Select(func (s interface{}) interface{} {< br />
104
+ return s.(Student).age< br />
105
+ }).
106
+ </ code > </ td >
107
+ </ tr >
108
+ < tr >
109
+ < td class ='docs '>
110
+ Find the average.
111
+ </ td >
112
+
113
+ < td class ='code '> < code >
114
+ Average()
115
+ </ code > </ td >
116
+ </ tr >
117
+ </ table >
118
+ </ div >
119
+
120
+ < h2 > Concurrent</ h2 >
121
+ < div class ='inner row '>
122
+ < p > Count websites that have a favicon.ico.</ p >
123
+ < table >
124
+ < tr >
125
+ < td class ='docs '>
126
+
127
+ </ td >
128
+
129
+ < td class ='code '> < code >
130
+ urls := make(chan interface{})< br />
131
+ results := make(chan interface{})
132
+ </ code > </ td >
133
+ </ tr >
134
+
135
+ < tr >
136
+ < td class ='docs '>
137
+ Convert domain names to full URLs.
138
+ </ td >
139
+
140
+ < td class ='code '> < code >
141
+ go func(domains []string) {< br />
142
+ From(domains).Select(func(d interface{}) interface{} {</ br >
143
+ return fmt.Sprintf("http://%s/favicon.ico", d)</ br >
144
+ }).ToChannel(urls)</ br >
145
+ }(domains)
146
+ </ code > </ td >
147
+ </ tr >
148
+
149
+ < tr >
150
+ < td class ='docs '>
151
+ Let's run the following in parallel.< br /> Request favicon for each domain.
152
+ </ td >
153
+
154
+ < td class ='code '> < code >
155
+ go func() {< br />
156
+ defer close(results)</ br >
157
+ var wg sync.WaitGroup</ br >
158
+ for url := range urls {</ br >
159
+ wg.Add(1)</ br >
160
+ go func(url string) {</ br >
161
+ defer wg.Done()</ br >
162
+ resp, _ := http.Get(url)</ br >
163
+ results < - resp.StatusCode </ br >
164
+ }(url.(string))</ br >
165
+ }</ br >
166
+ wg.Wait()</ br >
167
+ }()
168
+ </ code > </ td >
169
+ </ tr >
170
+
171
+ < tr >
172
+ < td class ='docs '>
173
+ Count websites.
174
+ </ td >
175
+
176
+ < td class ='code '> < code >
177
+ FromChannel(results).CountWith(func(r interface{}) bool {< br />
178
+ return r.(int) == 200< br />
179
+ })
180
+ </ code > </ td >
181
+ </ tr >
182
+ </ table >
183
+ </ section >
184
+
185
+ < section class ='about '>
186
+
187
+ < h2 > About</ h2 >
188
+ < div class ='inner '>
189
+ < p >
190
+ If you have suggestions or improvements, feel free to contact or submit a pull request. All contributions are welcomed.
191
+ </ p >
192
+
193
+ < p >
194
+ This library is brought you by < a href ='http://kalan.rocks/ '> Alexander (kalan) Kalankhodzhaev</ a >
195
+ and < a href ='https://twitter.com/ahmetalpbalkan '> @ahmetalpbalkan</ a > .
196
+ </ p >
197
+ < p >
198
+ < a href ='http://kalan.rocks/ '> < img src ='img/kalan.png ' width ='150 ' height ='150 ' alt ="Alexander (kalan) Kalankhodzhaev, 2016 " /> </ a >
199
+ < a href ='http://ahmetalpbalkan.com '> < img src ='img/ahmet.png ' width ='150 ' height ='150 ' alt ="Ahmet Alp Balkan, 2013 " /> </ a >
200
+ </ p >
201
+
202
+ </ div >
203
+ </ section >
204
+
205
+ < footer >
206
+ Lovingly made in Moscow and Seattle.
207
+ </ footer >
208
+
209
+ < script >
210
+ ( function ( i , s , o , g , r , a , m ) { i [ 'GoogleAnalyticsObject' ] = r ; i [ r ] = i [ r ] || function ( ) {
211
+ ( i [ r ] . q = i [ r ] . q || [ ] ) . push ( arguments ) } , i [ r ] . l = 1 * new Date ( ) ; a = s . createElement ( o ) ,
212
+ m = s . getElementsByTagName ( o ) [ 0 ] ; a . async = 1 ; a . src = g ; m . parentNode . insertBefore ( a , m )
213
+ } ) ( window , document , 'script' , '//www.google-analytics.com/analytics.js' , 'ga' ) ;
214
+ ga ( 'create' , 'UA-45321252-3' , 'ahmetalpbalkan.github.io' ) ;
215
+ ga ( 'send' , 'pageview' ) ;
216
+ </ script >
217
+ </ body >
218
+
219
+ </ html >
0 commit comments