Go言語使ってて気づいたこと。


最近気づいたこと。

配列とスライスの違い

配列は固定長で、スライスは可変長で違う(メモリの扱いも違う)型の扱い。 スライスは別の変数に代入するとき、参照がコピー。 配列は実体がコピーされる。

下記のコードを動かしてみる。

package main

import (
   "fmt"
)

func main() {
   array := [4]byte{1,2,3,4}
   slice := []byte{1,2,3,4}
   array_copy := array
   slice_copy := slice
   array_copy[0] = 8
   slice_copy[0] = 8
   fmt.Printf("%#v, %#v", array, slice)
}
  • また、配列からスライスを取り出すと、参照スライスが作られる。
  • ビルトインのcopyはスライスを対象にコピーできる。配列を対象にするにはスライス参照をすると良い。

配列をスライスに変換して複製する方法。

下記のコードを動かしてみる。

package main

import (
   "fmt"
)

func main() {
   array := [4]byte{1,2,3,4}
   dst := make([]byte, len(array))
   copy(dst, array[:])
   fmt.Printf("%#v", dst)
}

マップのキーについて

マップのキーは比較可能な型のみ。忘れがちなのが構造体の値や配列そのものもキーにできる。

多値返値について

多値返値は可変長引数で受け取ることができる。

下記のコードを動かしてみる。

package main

import "fmt"

func multiple() (x, y int) {
   x = 123
   y = 456
   return
}

func print(val ...int) {
   fmt.Printf("%#v", val)
}

func main() {
   print(multiple())
}

可変長引数への展開渡し

可変長引数にはスライスを展開して渡せる。

下記のコードを動かしてみる。

package main

import (
   "fmt"
)

func sample(args...interface{}){
   fmt.Printf("%#v", args)
}

func main() {
   slice := []interface{}{"127.0.0.1",8024}
   sample(slice...)
}

Setコンテナは無いの?

ユニークなセットを作るにはマップのキーを使う。 バリューはダミーデータを入れておく。

下記のコードを動かしてみる。

package main

import (
   "fmt"
)

type Set map[int]bool

func keys(s Set) (result []int) {
   for k, _ := range s {
      result = append(result, k)
   }
   return
}

func main() {
   set := make(Set, 0)
   for _,i:=range []int{1,3,5,7,6,4,8,6,2,1} {
      set[i] = true
   }
   fmt.Println(keys(set))
}

え?これ一緒じゃないの?

下記のコードを動かしてみる。

package main

import "fmt"

func equal(a, b interface{}) bool {
   return a==b
}

func main() {
   var nilSlice []byte
   fmt.Println(nilSlice==nil, equal(nilSlice, nil))
}

実行結果は「true false」。 nilポインタとnilは比較可能だけど、interface{}型に一旦入れると比較できなくなる。

comments powered by Disqus