So-net無料ブログ作成

Golangの分からないところ。 [プログラミング]

Golang tourより
https://go-tour-jp.appspot.com/moretypes/16

package main

import "fmt"
import "math"

var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}

func main() {
    for i, v := range pow {
        fmt.Print(math.Exp2(float64(i)))
        fmt.Print(2 ** i)
//        fmt.Print(2 ** float64(i))
        fmt.Printf(" 2**%d = %d\n", i, v)
    }
}

fmt.Print(2 ** i)
でやると

invalid indirect of i (type int)
というエラーが出てしまう。そもそも**演算子が機能していないのではないかと思ってしまう。

float64にキャストしてもダメだし、書き方自体存在する意味があるのか。
そもそも**演算子がないのかも。なかった…。まぁC言語にもないしな、演算子では。
しかし、Golangの動作側としては何を意図していると仮定されているのだろうか。
そもそもない演算子だから、そこでエラーを出して欲しいんだけど。



package main

import "fmt"

func main() {
	pow := make([]int, 10)
	for i := range pow {
		pow[i] = 1 << uint(i) // == 2**i
	}
	for _, value := range pow {
		fmt.Printf("%d\n", value)
	}
	fmt.Print(pow)
}


あぁ2の累乗だったらシフト演算で足りるか…。


別の話。Goで再帰関数を使ってたらしばらくしたら破綻した。Webをクロールして二日間ぐらいだったから、そりゃスタックも尽きるよというところで。
別にスタックオーバーフローの実験をしたわけではありません。
コード的に面倒なので手を抜いただけですw。


こんなん出ました。ahrefというのが再帰した関数です。こうやって落ちる。

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x40 pc=0x627afc]
                                                              
goroutine 1 [running]:                                        
main.getfile(0xc4274aa900, 0x60, 0xc4204b2900, 0x16)          
        /home/hogehoge/rwget.go:66 +0x4c                      
main.ahref(0xc426354000, 0x36fd6, 0x3b2aa, 0xc420120f50, 0x6e)
        /home/hogehoge/rwget.go:118 +0x469                    
main.ahref(0xc426354000, 0x36fce, 0x3b2aa, 0xc4205dcc00, 0x38)
        /home/hogehoge/rwget.go:130 +0x8a5                    
main.ahref(0xc426354000, 0x36fcd, 0x3b2aa, 0xc4205dc980, 0x40)
        /home/hogehoge/rwget.go:130 +0x8a5                    
main.ahref(0xc426354000, 0x36fcc, 0x3b2aa, 0xc4205dc800, 0x3e)
        /home/hogehoge/rwget.go:130 +0x8a5                    
main.ahref(0xc426354000, 0x36fca, 0x3b2aa, 0xc4205dc740, 0x3f)
        /home/hogehoge/rwget.go:130 +0x8a5                    
main.ahref(0xc426354000, 0x36fc8, 0x3b2aa, 0xc4205dc680, 0x3b)
        /home/hogehoge/rwget.go:130 +0x8a5                    
main.ahref(0xc426354000, 0x36fc7, 0x3b2aa, 0xc4202b05f0, 0x4a)
        /home/hogehoge/rwget.go:130 +0x8a5                    
main.ahref(0xc426354000, 0x36fc3, 0x3b2aa, 0xc4205dc180, 0x39)
        /home/hogehoge/rwget.go:130 +0x8a5                    
main.ahref(0xc426354000, 0x36fc2, 0x3b2aa, 0xc4205cc1c0, 0x36)
        /home/hogehoge/rwget.go:130 +0x8a5                    
main.ahref(0xc426354000, 0x36fc1, 0x3b2aa, 0xc420ca23c0, 0x4f)
        /home/hogehoge/rwget.go:130 +0x8a5                    
main.ahref(0xc426354000, 0x36fbf, 0x3b2aa, 0xc4201e4460, 0x67)
        /home/hogehoge/rwget.go:130 +0x8a5                    
main.ahref(0xc426354000, 0x36fbd, 0x3b2aa, 0xc420138690, 0x46)
        /home/hogehoge/rwget.go:130 +0x8a5                    
main.ahref(0xc426354000, 0x36fbc, 0x3b2aa, 0xc420c77650, 0x67)

以下続く。


そもそもGoは再帰関数が得意ではないという話です。
http://ymotongpoo.hatenablog.com/entry/2015/02/23/165341
何回も動作させたい時には関数内で再帰させずに、ループとかで一回関数を終わらせてまた動作させるなり制御しましょうねということなんだろう。

まぁ別に再帰を使わなくていいところで面倒がってやったので、帰り値で戻して再度パラメーターに入れればいいだけの話だったりするわけですが、思いのほか再帰が使いにくいということに気づきました。小さい遅いではメリットないですよね。

今回のサイズとかは良く分からんのだけれど1200回以上再帰した所で死んでいる模様。
どのくらいの大きさのものをどれくらい積めるのかは良くわかんないんだけど、戻るポインタの値だけを記憶していたとしてもやっぱ1000以上は多いのか。Goルーチンをポコポコ作れるようにスタックは小さめに作ってあるらしいが一般的にスタックってどうやってどれだけ確保されてるんだろうね。Golangのメモリ操作がどうなっているかいまいち分かっていない。

最後にいっぺんにログを吐くように作ってあるのだけれど、途中で止まってるので中途半端なものすらない状態だったり。でも、いちいちログに一行ずつ書くのもパフォーマンス的にはなぁ。ファイルを開けっ放しでちまちま書き込むのも、開けたり閉じたりするのも嫌な感じなんだけど。Goのファイルの操作を調べて、ちょっと考えてみよう。


Goのチュートリアルの問題ってググると正解が結構出てくるのね。というか、あまり初心者向けの問題じゃない気がするんだけど、他の言語を知っている人にとってはGolangを知るにはいい機会なのかもしれないけど、ちょっと深掘りしないとわからない問題が多くて困る。なのでチートして終わりにしておく。

タグ:Golang
コメント(0) 
共通テーマ:パソコン・インターネット

コメント 0