6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[ポエム]Goでモヤモヤするところ

6
Last updated at Posted at 2017-02-23

Go最近の一番のお気に入り言語なのですが、モヤモヤするところも出てきてるので備忘録的にポエムを書いてみました。

汎用的に書こうとすると遅くなる

ちょっと柔軟に書こうとするとReflection, Interfaceが必要になってきて遅くなる[1]。
Reflectionは色々コード生成ライブラリがあるからいいけど[2][3], InterfaceをつかないとGoっぽいコードにならない。
まぁ Interfaceによる性能劣化が実際に実務で問題になることは当面なさそうだし、
部分的に使わなければいいだけなのだけど、少しモヤモヤ
Rustだとこの辺オーバーヘッドなしに実現してるらしいので気になってる。実務で使うにはもっとエコシステムが育つ必要があるけど、、

package benchmark

import (
	"testing"
)

type CalcInterface interface {
	Add(a, b int) int
}

type CalcImpl struct {
}

func (m *CalcImpl) Add(a, b int) int {
	return a + b
}

type CalcStructWithPointer struct {
	impl *CalcImpl
}

type CalcSturctWithInterface struct {
	impl CalcInterface
}

type CalcStructWithFunctionPointer struct {
	impl func(a, b int) int
}

func BenchmarkCalcStructWithPointer(b *testing.B) {
	c := &CalcStructWithPointer{
		impl: &CalcImpl{},
	}
	for i := 0; i < b.N; i++ {
		c.impl.Add(10, 20)
	}
}

func BenchmarkCalcSturctWithInterface(b *testing.B) {
	c := &CalcSturctWithInterface{
		impl: &CalcImpl{},
	}
	for i := 0; i < b.N; i++ {
		c.impl.Add(10, 20)
	}
}

func BenchmarkCalcStructWithFunctionPointer(b *testing.B) {
	c := &CalcStructWithFunctionPointer{
		impl: func(a, b int) int {
			return a + b
		},
	}
	for i := 0; i < b.N; i++ {
		c.impl(10, 20)
	}
}
BenchmarkCalcStructWithPointer-8           	2000000000	         0.30 ns/op
BenchmarkCalcSturctWithInterface-8         	1000000000	         2.71 ns/op
BenchmarkCalcStructWithFunctionPointer-8   	1000000000	         2.42 ns/op

net/rpcのフリーズはgRPCのゴリ押しではないか?

去年、net/rpcモジュールがフリーズされた。

net/rpcモジュールはGoからしか使えないものの、IDL不要でgRPCより高速。
上記のissueでは、構造的に問題があるとかバグが多いとか書いていたけど、説得力がなかった、、フリーズはgRPCのゴリ押しではないかと邪推してしまう。言語と特定の技術をセット売りされているようでモヤモヤ

Null Safe欲しい

Nullチェックめんどくさい

シンタックスシュガー欲しい

if err != nil とか、、
関連して、Error モナドが使えるといいのに
無理やりモナドやるならこうかな? 遅いけど

func taskA(context map[string]interface{}) error {
	fmt.Println("taskA done")
	return nil
}

func taskB(context map[string]interface{}) error {
	return fmt.Errorf("I don't want to do task B!")
}

func taskC(context map[string]interface{}) error {
	fmt.Println("taskC done")
	return nil
}

func do(context map[string]interface{}, tasks ...func(context map[string]interface{}) error) error {
	for _, task := range tasks {
		if err := task(context); err != nil {
			return err
		}
	}
	return nil
}

func main() {
	err := do(nil,
		taskA,
		taskB,
		taskC)
	fmt.Println(err)
}

参考文献

[1] http://inforno.net/articles/2015/12/11/go-interface-performance-penalty
[2] Genny https://github.com/cheekybits/genny
[3] Who needs generics? Use ... instead! https://appliedgo.net/generics/

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?