Go言語 : 配列 と スライス の違い

この記事は約5分で読めます。

Go言語において、配列 と スライス について、調べました。

実は、

Goにおいて、スライスと配列は似たような見た目なのですが、全く違うのです。

package main

import(
  "fmt"
)

func main() {
	list := [3]string{"a", "b", "c"} //配列
	slice := []string{"a", "b", "c"} //スライス
	fmt.Println(list)
	fmt.Println(slice)
}
//結果
//[a b c]
//[a b c]

 

結果は同じで、見た目は似ていますが、全然違います。

それでは、見ていきます。

 

Go言語 : IPアドレス から位置情報を取得してみる
今回は、Go言語を使って、IPアドレスから位置を取得してみます。ライブラリを使うと簡単に取得できます!IPアドレスから、日本だと、市や緯度経度まで分かってしまいます!ネットワーク勉強の最初にとてもぴったりです。ぜひ使ってみてください!

TL;DR

  • 配列・・・値を保持
  • スライス・・・配列の参照データを保持

配列

配列はそのまま、箱を用意して保存しています。

つまり、上の例だと、

string型の箱を3つ用意し、順番に、a,b,cを入れています。

配列

配列では、値を変数に入れています。

変数をまた別の変数に入れる場合、値がコピーされます。

そのため、以下のようなコードの場合、list2を変更しても、listには変更されません。

package main

import(
  "fmt"
)

func main() {
  list := [3]string{"a","b","c"}
  list2 := list //値はコピーされて、新しく配列ができます
  list2[0] = "change"

  fmt.Printf("list:%v\n",list)
  fmt.Printf("list2:%v\n",list2)
}
 /*結果
list:[a b c]
list2:[change b c]
*/

 

スライス

スライスでは、配列への参照データを保持しています。

つまり、以下のような図です。

スライス

細かく言うと、

  • 配列への場所データ(アドレス)
  • 配列の長さ(length)
  • 配列の容量(capacity)

を保持しています。

このため、長さや容量を変えることができるので

あたかも、

可変長配列のように見えます(実際は、上のデータしか保持していませんが)

 

変数をまた別の変数に入れる場合、上の3データがコピーされるので、配列はそのままです。

package main

import(
  "fmt"
)

func main() {
  list := []string{"a","b","c"}
  list2 := list //値はコピーされて、新しく配列ができます
  list2[0] = "change"

  fmt.Printf("list:%v\n",list)
  fmt.Printf("list2:%v\n",list2)
}
 /*結果
list:[change b c]
list2:[change b c]
*/

配列からスライスへの変換

list := [3]int{1,2,3}
slice := list[:]

[:]でsliceに変わります。

[x:y]のように配列を切り取って、取得することもできます。

スライスから配列への変換

slice := list[:]
  var list3 [3]string
  copy(list3[:],slice)
  fmt.Printf("list3:%v\n",list3)

Goでは

Goでは、配列をほとんど使いません。

基本的には、スライスを用います。

スライスの追加

スライスの初期容量は10です

スライスで、値を追加する際は

appendを用います。

slice := []string{"a"}
slice = append(slice,"b")

 

しかし、

appendが容量(capacity)を超える場合、

別途,容量を2倍した新しい配列を作成し、今までの配列のデータをコピーします。

コピーはかなり処理コストが大きいので、

大容量のスライスでappendするのは良くありません。

もし、追加容量がわかっているなら、

make

を使って、あらかじめ、容量を作成し

  • appendを使う
  • 添字で追加する
    方が良いです。
list4 := make([]string, 20)
	for i := 0; i < 20; i++ {
		list4[i] = strconv.Itoa(i)
                //or list4 = append(list4,strconv.Itoa(i))
	}
	fmt.Println(list4)

 

ちなみに

構造体の参照渡しをしたいときは

func Test(user *User){}

のように渡します。

スライスの場合は

func Test(user []User){}

です。

たまに

func Test(user *[]User){}

このように書いている人がいますが、参照データを参照しているので、無駄なことになるので気をつけてくださいね!

まとめ

今回は配列とスライスについてまとめました。

基本的には

スライスを使うことをオススメします。

それでは。

 

Go言語 :logとfmtの違いはなんなの?

タイトルとURLをコピーしました