mattn 1 week ago 気にしたくないのであれば、container/list というのはあります。 list package - container/list - Go PackagesPackage list implements a doubly linked list.
mattn 1 week ago まぁこのあたりは言語の設計者の意図があるでしょうね。 JS の設計者は arr.unshift(s) が実は O(n) である事を隠そうとした。いっぽうで Go の設計者は隠したくなかった。
mattn 1 week ago js では意識する必要なかった事が Go だと意識する必要があったりしますね。 例えば js でリストの先頭に足すのは arr.unshift(s) なんてやりますが、あれ実際には内部でリストを伸長して、全項目を1つずつ積みなおしてるんですよね。Go はそれを意識する必要があります。
mattn 1 week ago fmt.Println(s) の後に 1, 1 になったのは fmt.Println を呼び出した事で、スライスの中身 (ptr, len, cap) がコピーされたからですね。まぁここは意識しなくて良いです。
mattn 1 week ago なんでそんなにメモリの伸長にこだわるのかというと、コンピュータでメモリの伸長ってめちゃめちゃ遅いからです。 [a][b][c] に [d] を足そうとしても、[c] の後ろに既にほかのメモリが占有しちゃってるかもしれないので、[a][b][c][d] が収まるメモリの空きを探して、見つかったら元の位置から全メモリを転送する、みたいな事をしてるんですよね。なので遅い。
mattn 1 week ago 例えば、append していくけど、必ず100個以内で収まると分かってるならスライスを s := make([]string, 0, 100) と作っておくと s = append(s, "foo") を何回やってもメモリの伸長が行われないんです。(最初から作っちゃってるので)
mattn 1 week ago var s []string fmt.Printf("len=%d cap=%d\n", len(s), cap(s)) // len=0 cap=0 s = append(s, "hello") fmt.Printf("len=%d cap=%d\n", len(s), cap(s)) // len=1 cap=2 こうです。cap が出てうるのは append か make を使う時だけです。