apeescape2.com
  • メイン
  • 製品ライフサイクル
  • バックエンド
  • 収益性と効率性
  • ツールとチュートリアル
バックエンド

Go言語に対する4つの批判

Go(別名Golang)は、人々が最も興味を持っている言語の1つです。 2018年4月現在 TIOBEインデックスで19位 。ますます多くの人々がPHP、Node.js、その他の言語からGoに切り替えて、本番環境で使用しています。多くのクールなソフトウェア(Kubernetes、Docker、Heroku CLIなど)はGoを使用して作成されています。

では、成功へのGoの鍵は何ですか?言語には、それを本当にクールにするものがたくさんあります。しかし、その作成者の1人が指摘したように、「私はそのシンプルさに行きました」というように人気を博した主な理由の1つは、 ロブパイク 。

シンプルさは素晴らしいです-あなたは多くのキーワードを学ぶ必要はありません。それは言語学習を非常に簡単かつ迅速にします。ただし、一方で、開発者が他の言語で持っているいくつかの機能を欠いているため、回避策をコーディングするか、より長期的なコードを書く必要がある場合があります。残念ながら、Goには設計上多くの機能が欠けており、時には本当に煩わしいものです。



Golangは開発を高速化することを目的としていましたが、多くの場合、他のプログラミング言語を使用するよりも多くのコードを記述しています。これらのケースのいくつかについては、以下のGoレビューで説明します。

囲碁言語に対する4つの批判

1.引数の関数のオーバーロードとデフォルト値の欠如

ここに実際のコード例を投稿します。 Golang Seleniumバインディングに取り組んでいたとき、3つのパラメーターを持つ関数を作成する必要がありました。それらのうちの2つはオプションでした。展開後は次のようになります。

func (wd *remoteWD) WaitWithTimeoutAndInterval(condition Condition, timeout, interval time.Duration) error { // the actual implementation was here } func (wd *remoteWD) WaitWithTimeout(condition Condition, timeout time.Duration) error { return wd.WaitWithTimeoutAndInterval(condition, timeout, DefaultWaitInterval) } func (wd *remoteWD) Wait(condition Condition) error { return wd.WaitWithTimeoutAndInterval(condition, DefaultWaitTimeout, DefaultWaitInterval) }

関数をオーバーロードしたり、デフォルト値を渡すことができなかったため、3つの異なる関数を実装する必要がありました-Goは設計上それを提供していません。誤って間違った電話をかけた場合にどうなるか想像してみてください。次に例を示します。

それは私にたくさんの「未定義」を与えるでしょう

関数のオーバーロードによってコードが乱雑になることがあることを認めなければなりません。一方、このため、プログラマーはより多くのコードを書く必要があります。

どうすれば改善できますか?

これはJavaScriptの同じ(まあ、ほぼ同じ)例です:

function Wait (condition, timeout = DefaultWaitTimeout, interval = DefaultWaitInterval) { // actual implementation here }

ご覧のとおり、はるかに明確に見えます。

その上でのエリクサーのアプローチも好きです。 Elixirでは次のようになります(上記の例のように、デフォルトを使用できることはわかっています。これを行う方法として示しています)。

defmodule Waiter do @default_interval 1 @default_timeout 10 def wait(condition, timeout, interval) do // implementation here end def wait(condition, timeout), do: wait(condition, timeout, @default_interval) def wait(condition), do: wait(condition, @default_timeout, @default_interval) end Waiter.wait('condition', 2, 20) Waiter.wait('condition', 2) Waiter.wait('condition')

2.ジェネリック医薬品の欠如

これは間違いなく、Goユーザーが最も求めている機能です。

整数の配列とそのすべての要素に適用される関数を渡すマップ関数を作成するとします。簡単そうですね。

整数に対してそれをやってみましょう:

package main import 'fmt' func mapArray(arr []int, callback func (int) (int)) []int { newArray := make([]int, len(arr)) for index, value := range arr { newArray[index] = callback(value) } return newArray; } func main() { square := func(x int) int { return x * x } fmt.Println(mapArray([]int{1,2,3,4,5}, square)) // prints [1 4 9 16 25] }

よさそうだよね?

さて、あなたもそれを弦で行う必要があると想像してください。別の実装を作成する必要があります。これは、署名以外はまったく同じです。 Golangは関数のオーバーロードをサポートしていないため、この関数には別の名前が必要です。その結果、異なる名前の類似した関数が多数あり、次のようになります。

func mapArrayOfInts(arr []int, callback func (int) (int)) []int { // implementation } func mapArrayOfFloats(arr []float64, callback func (float64) (float64)) []float64 { // implementation } func mapArrayOfStrings(arr []string, callback func (string) (string)) []string { // implementation }

これは、コピー/貼り付けコードをできるだけ少なくし、代わりに関数に移動して再度使用する必要があるというDRYの原則に間違いなく反します。

ジェネリックスの欠如は、何百ものバリアント関数を意味します

銀行の財務管理とは

別のアプローチは、interface {}で単一の実装を使用することです。パラメータとして使用しますが、実行時型チェックはエラーが発生しやすいため、実行時エラーが発生する可能性があります。また、速度も遅くなるため、これらの関数を1つとして実装する簡単な方法はありません。

どうすれば改善できますか?

一般的なサポートを含む多くの優れた言語があります。たとえば、Rustの同じコードを次に示します(簡単にするために、vecの代わりに arrayを使用しました):

fn map(vec:Vec, callback:fn(T) -> T) -> Vec { let mut new_vec = vec![]; for value in vec { new_vec.push(callback(value)); } return new_vec; } fn square (val:i32) -> i32 { return val * val; } fn underscorify(val:String) -> String { return format!('_{}_', val); } fn main() { let int_vec = vec![1, 2, 3, 4, 5]; println!('{:?}', map::(int_vec, square)); // prints [1, 4, 9, 16, 25] let string_vec = vec![ 'hello'.to_string(), 'this'.to_string(), 'is'.to_string(), 'a'.to_string(), 'vec'.to_string() ]; println!('{:?}', map::(string_vec, underscorify)); // prints ['_hello_', '_this_', '_is_', '_a_', '_vec_'] }

map関数の実装は1つだけであり、カスタムのものも含め、必要なすべてのタイプに使用できることに注意してください。

3.依存関係の管理

Goの経験がある人なら誰でも、依存関係の管理が本当に難しいと言うことができます。 Goツールを使用すると、ユーザーはgo get を実行してさまざまなライブラリをインストールできます。ここでの問題はバージョン管理です。ライブラリメンテナが後方互換性のない変更を加えてGitHubにアップロードすると、その後プログラムを使用しようとするとエラーが発生します。go get git clone以外の何もしませんリポジトリ内のライブラリフォルダにあります。また、ライブラリがインストールされていない場合、そのためプログラムはコンパイルされません。

Depを使用して依存関係を管理することで、もう少しうまくいくことができます( https://github.com/golang/dep )、しかしここでの問題は、すべての依存関係をリポジトリに保存していることです(リポジトリにはコードだけでなく、数千行の依存関係コードが含まれているため、これは良くありません)、または単にリストを保存しますパッケージの(ただし、依存関係メンテナが逆の互換性のない変更を行うと、すべてがクラッシュします)。

どうすれば改善できますか?

ここでの完璧な例は、Node.js(そして一般的にはJavaScriptだと思います)とNPMだと思います。 NPMはパッケージリポジトリです。さまざまなバージョンのパッケージが保存されるため、特定のバージョンのパッケージが必要な場合は、問題なく、そこから入手できます。また、Node.js / JavaScriptアプリケーションに含まれるものの1つは、package.jsonファイルです。ここでは、すべての依存関係とそのバージョンが一覧表示されているため、npm installを使用してすべてをインストールできます(そして、コードで確実に機能するバージョンを取得できます)。

また、優れたパッケージ管理の例は、RubyGems / Bundler(Rubyパッケージの場合)およびCrates.io/Cargo(Rustライブラリーの場合)です。

4.エラー処理

Goでのエラー処理は完全に簡単です。 Goでは、基本的に複数の関数値を返すことができ、関数はエラーを返すことができます。このようなもの:

err, value := someFunction(); if err != nil { // handle it somehow }

ここで、エラーを返す3つのアクションを実行する関数を作成する必要があると想像してください。次のようになります。

func doSomething() (err, int) { err, value1 := someFunction(); if err != nil { return err, nil } err, value2 := someFunction2(value1); if err != nil { return err, nil } err, value3 := someFunction3(value2); if err != nil { return err, nil } return value3; }

ここには繰り返し可能なコードがたくさんありますが、これは良くありません。そして素晴らしい機能で、 それはさらに悪化する可能性があります 。これには、おそらくキーボードのキーが必要です。

キーボードのエラー処理コードの漫画画像

どうすれば改善できますか?

私はそれに対するJavaScriptのアプローチが好きです。関数はエラーをスローする可能性があり、それをキャッチすることができます。例を考えてみましょう。

function doStuff() { const value1 = someFunction(); const value2 = someFunction2(value1); const value3 = someFunction3(value2); return value3; } try { const value = doStuff(); // do something with it } catch (err) { // handle the error }

これははるかに明確であり、エラー処理のための繰り返し可能なコードは含まれていません。

囲碁の良いところ

Goには設計上多くの欠陥がありますが、いくつかの非常に優れた機能もあります。

1.ゴルーチン

非同期プログラミングは、Goで非常に簡単になりました。マルチスレッドプログラミングは他の言語では難しいことがよくありますが、新しいスレッドを生成し、現在のスレッドをブロックしないようにそのスレッドで関数を実行するのは非常に簡単です。

func doSomeCalculations() { // do some CPU intensive/long running tasks } func main() { go doSomeCalculations(); // This will run in another thread; }

2.Goに含まれているツール

他のプログラミング言語では、さまざまなタスク(テスト、静的コードのフォーマットなど)に応じてさまざまなライブラリ/ツールをインストールする必要がありますが、Goには、次のような多くの優れたツールがデフォルトで含まれています。

  • gofmt -静的コード分析のためのツール。 eslintのような追加の依存関係をインストールする必要があるJavaScriptとの比較または jshint、ここではデフォルトで含まれています。また、Goスタイルのコードを記述しないと(宣言された変数を使用したり、未使用のパッケージをインポートしたりすることなく)、プログラムはコンパイルされません。
  • go test -テストフレーム。繰り返しますが、JavaScriptと比較する場合は、テスト用に追加の依存関係(Jest、Mocha、AVAなど)をインストールする必要があります。ここでは、デフォルトで含まれています。また、ベンチマーク、ドキュメント内のコードのテストへの変換など、デフォルトで多くの優れた処理を実行できます。
  • godoc -ドキュメントツール。デフォルトのツールに含まれているのは素晴らしいことです。
  • コンパイラ自体。他のコンパイル言語と比較して、信じられないほど高速です。

3.延期する

これはこの言語で最高の機能の1つだと思います。 3つのファイルを開く関数を作成する必要があるとします。また、何かが失敗した場合は、既存の開いているファイルを閉じる必要があります。このような建物がたくさんあると、災害のように見えます。この擬似コードの例を考えてみましょう。

function openManyFiles() { let file1, file2, file3; try { file1 = open(‘path-to-file1’); } catch (err) { return; } try { file2 = open(‘path-to-file2’); } catch (err) { // we need to close first file, remember? close(file1); return; } try { file3 = open(‘path-to-file3’); } catch (err) { // and now we need to close both first and second file close(file1); close(file2); return; } // do some stuff with files // closing files after successfully processing them close(file1); close(file2); close(file3); return; }

複雑そうです。そこがGo defer代わりに入力します:

package main import ( 'fmt' ) func openFiles() { // Pretending we’re opening files fmt.Printf('Opening file 1 '); defer fmt.Printf('Closing file 1 '); fmt.Printf('Opening file 2 '); defer fmt.Printf('Closing file 2 '); fmt.Printf('Opening file 3 '); // Pretend we've got an error on file opening // In real products, an error will be returned here. return; } func main() { openFiles() /* Prints: Opening file 1 Opening file 2 Opening file 3 Closing file 2 Closing file 1 */ }

ご覧のとおり、ファイル番号3を開くときにエラーが発生した場合、ステートメントdeferにより、他のファイルは自動的に閉じられます。それらは逆の順序で戻る前に実行されます。また、関数の異なる部分ではなく、同じ場所でファイルを開いたり閉じたりするのも便利です。

結論

Goの良い点と悪い点のすべてについては触れませんでしたが、私が最良と最悪と考えるものだけを取り上げました。

Goは、今日使用されている興味深いプログラミング言語の1つであり、実際に可能性を秘めています。それは私たちに本当にクールなツールと機能を提供します。ただし、そこで改善できることがたくさんあります。

私たちが好きなら 開発者に行く これらの変更を行うと、Goを使用したプログラミングがはるかに楽しくなるため、コミュニティに大きなメリットがあります。

それまでの間、Goでテストを改善しようとしている場合は、 Goアプリをテストする-正しく始めましょう ApeeScapeの同僚であるGabrielAssalasによる。

シニアフロントエンドエンジニア、スタッフポータルキャッシュチーム

その他

シニアフロントエンドエンジニア、スタッフポータルキャッシュチーム
「ハートブリード」OpenSSLバグの修正:システム管理者向けのチュートリアル

「ハートブリード」OpenSSLバグの修正:システム管理者向けのチュートリアル

データサイエンスとデータベース

人気の投稿
破壊的時代におけるデジタルバンキングのイノベーション
破壊的時代におけるデジタルバンキングのイノベーション
SQLウィンドウ関数の概要
SQLウィンドウ関数の概要
AWSでのTerraformによるダウンタイムゼロのJenkins継続的デプロイ
AWSでのTerraformによるダウンタイムゼロのJenkins継続的デプロイ
これらのPhotoshopチュートリアルでこれらの人気のあるトレンドをマスターする
これらのPhotoshopチュートリアルでこれらの人気のあるトレンドをマスターする
デザインニュース-世界中からのイノベーション
デザインニュース-世界中からのイノベーション
 
WebVRパート4:キャンバスデータの視覚化
WebVRパート4:キャンバスデータの視覚化
ファミリーオフィス投資ガイド:ベンチャーキャピタルの代替案
ファミリーオフィス投資ガイド:ベンチャーキャピタルの代替案
初心者のための暗号通貨:ビットコインとそれ以降
初心者のための暗号通貨:ビットコインとそれ以降
知恵の真珠-誰も読まない最高の株主の手紙
知恵の真珠-誰も読まない最高の株主の手紙
VanillaJSでのReactとJSXのエミュレート
VanillaJSでのReactとJSXのエミュレート
人気の投稿
  • ギリシャが債務を抱えているのはなぜですか
  • llc scorpまたはccorp
  • アマゾンウェブサービス認定ソリューションアーキテクト
  • レール上とはどういう意味ですか
  • C ++を学ぶのに最適なウェブサイト
  • デビットカードビザをハックする方法
  • node js restapiの例
カテゴリー
エンジニアリング管理 収益と成長 プロジェクト管理 リモートの台頭 Uiデザイン 収益性と効率性 技術 ヒントとツール バックエンド プロセスとツール

© 2021 | 全著作権所有

apeescape2.com