私はタシケントに住んでいて、大学にいたとき、ボットを書くためにPythonを学び始めました。ボットはウズベキスタンのパンであり、すべてがそれらの上に構築されています。たとえば、誰も食べ物を注文するためのアプリケーションを作成しません。すべてはインスタントメッセンジャーにのみあります。
私はインターネットの記事から言語を学びました-私はフレームワークを取り、さらに追加し、物事がどこに落ちているかを調べ、常にリートコードの問題を解決しました。その時はひどい書きましたが、何だったのでしょうか。私はそれが好きでしたが、深く行くほど、実行速度、並行性の制限、動的型付けが煩わしくなりました。
それから私はGoを試してみることにしました。
Goはシンプルでクール、そして需要があります
私は彼らの軽量競争のアイデアに魅了され、Pythonにあった非同期動物園を理解する必要がないという事実が好きでした。最初、私は自分でGoで何かを書き、言語がどのように動作するかを見ました。それから仕事で、私たちは1つの簡単なプロジェクトを試すことにしました。開発速度と実行速度の両方の点で、良い結果が得られました。
, Go , , — , , , , . , Go , , , .
: « — ». , . - , .
- . , — .
, . , , , .
, . , Go , — , .
, , — . , , . , , .
. ,
leetcode .
, , . .
( , ) — . , . , .
package main
import (
"fmt"
)
// .
// ,
func intersection(a, b []int) []int {
counter := make(map[int]int)
var result []int
for _, elem := range a {
if _, ok := counter[elem]; !ok {
counter[elem] = 1
} else {
counter[elem] += 1
}
}
for _, elem := range b {
if count, ok := counter[elem]; ok && count > 0 {
counter[elem] -= 1
result = append(result, elem)
}
}
return result
}
func main() {
a := []int{23, 3, 1, 2}
b := []int{6, 2, 4, 23}
// [2, 23]
fmt.Printf("%v\n", intersection(a, b))
a = []int{1, 1, 1}
b = []int{1, 1, 1, 1}
// [1, 1, 1]
fmt.Printf("%v\n", intersection(a, b))
}
, , Go. . , .
N .
package main
import (
"fmt"
"math/rand"
"time"
)
func randNumsGenerator(n int) <-chan int {
r := rand.New(rand.NewSource(time.Now().UnixNano()))
out := make(chan int)
go func() {
for i := 0; i < n; i++ {
out <- r.Intn(n)
}
close(out)
}()
return out
}
func main() {
for num := range randNumsGenerator(10) {
fmt.Println(num)
}
}
N
n chan int. , .
, :
for num := range joinChannels(a, b, c) {
fmt.Println(num)
}
, , , , .
, . , , .
, . , wait group.
package main
import (
"fmt"
"sync"
)
func joinChannels(chs ...<-chan int) <-chan int {
mergedCh := make(chan int)
go func() {
wg := &sync.WaitGroup{}
wg.Add(len(chs))
for _, ch := range chs {
go func(ch <-chan int, wg *sync.WaitGroup) {
defer wg.Done()
for id := range ch {
mergedCh <- id
}
}(ch, wg)
}
wg.Wait()
close(mergedCh)
}()
return mergedCh
}
func main() {
a := make(chan int)
b := make(chan int)
c := make(chan int)
go func() {
for _, num := range []int{1, 2, 3} {
a <- num
}
close(a)
}()
go func() {
for _, num := range []int{20, 10, 30} {
b <- num
}
close(b)
}()
go func() {
for _, num := range []int{300, 200, 100} {
c <- num
}
close(c)
}()
for num := range joinChannels(a, b, c) {
fmt.Println(num)
}
}
. . , , - (, ) .
, https://blog.golang.org/pipelines.
— . . . — , .
package main
import (
"fmt"
)
func main() {
naturals := make(chan int)
squares := make(chan int)
go func() {
for x := 0; x <= 10; x++ {
naturals <- x
}
close(naturals)
}()
go func() {
for x := range naturals {
squares <- x * x
}
close(squares)
}()
for x := range squares {
fmt.Println(x)
}
}
WorkerPool
, .
— , . . , , .
package main
import (
"fmt"
)
func worker(id int, f func(int) int, jobs <-chan int, results chan<- int) {
for j := range jobs {
results <- f(j)
}
}
func main() {
const numJobs = 5
jobs := make(chan int, numJobs)
results := make(chan int, numJobs)
multiplier := func(x int) int {
return x * 10
}
for w := 1; w <= 3; w++ {
go worker(w, multiplier, jobs, results)
}
for j := 1; j <= numJobs; j++ {
jobs <- j
}
close(jobs)
for i := 1; i <= numJobs; i++ {
fmt.Println(<-results)
}
}
waitGroup
. , .
, . . . , — .
package main
import (
"fmt"
)
type sema chan struct{}
func New(n int) sema {
return make(sema, n)
}
func (s sema) Inc(k int) {
for i := 0; i < k; i++ {
s <- struct{}{}
}
}
func (s sema) Dec(k int) {
for i := 0; i < k; i++ {
<-s
}
}
func main() {
numbers := []int{1, 2, 3, 4, 5}
n := len(numbers)
sem := New(n)
for _, num := range numbers {
go func(n int) {
fmt.Println(n)
sem.Inc(1)
}(num)
}
sem.Dec(n)
}
, — Rebrain — Go. , .
Go
, , Go . — , . — , , .
, , .
Go — , , , .
Go . ( «» — Go), , , , , . — Java C#. , , , , , .
++. , , ++ . , — .
Go . — , , . - - , .
— @alisher_m, Rebrain. , . , , .