多重代入
var a, b, c int
a, b, c = 10, 20, 30
または
a, b, c := 10, 20, 30
同じ型の複数宣言
- 初期化した値はゼロ値と呼ばれる。
※数値の場合は0
func main() {
var (
x int = 100
y int = 300
z int
)
// zは初期化されているだけなので、0になる
fmt.Println("x + y + z =", x+y+z)
}
// -> 400
iota識別子
- 連続した整数型整数を表現することができる
※変数でやったらエラーでた。←定数宣言でしか使えないから、そりゃそう。
func main() {
const (
x = iota
y
z
)
fmt.Println(x, y, z)
}
// -> 0 1 2
func main() {
const (
x = 1
y = iota
z
)
fmt.Println(x, y, z)
}
// -> 1 1 2
func main() {
const (
x = 10
y = iota + 10
z
)
fmt.Println(x, y, z)
}
// -> 10 11 12
func main() {
const (
x = iota * iota
y
z
zz
)
fmt.Println(x, y, z, zz)
}
// -> 0 1 4 9
条件分岐(switch-case)
- fallthroughを使用すれば、直下の処理が実行される
└必ずcase文の最後に記述。 - 論理値、文字列を使用することができる
func main() {
value := 1
switch value {
case 1:
fmt.Println("value = 1")
fallthrough
case 2:
fmt.Println("value = 2 or 3")
default:
fmt.Println("value = other")
}
}
//-> value = 1
// value = 2 or 3
func main() {
value := 15
switch {
case value > 0 && value <= 10:
fmt.Println("1 ~ 10")
case value > 10 && value <= 20:
fmt.Println("11 ~ 20")
case value > 20 && value <= 30:
fmt.Println("21 ~ 30")
default:
fmt.Println("other")
}
}
// -> 11 ~ 20
func main() {
value := "XYZ"
switch value {
case "ABC":
fmt.Println("ABC")
case "LMN":
fmt.Println("LMN")
case "XYZ":
fmt.Println("XYZ")
default:
fmt.Println("other")
}
}
// -> "XYZ"
繰り返し(for)
- break
└ループ処理を強制的に抜ける - continue
└ループブロックの処理をスキップする
func main() {
i := 0
for {
if i == 20 {
break
}
fmt.Println(i)
i++
}
}
// -> 1.....19
func main() {
value := 0
for {
if value%2 == 0 {
fmt.Println(value)
value++
} else {
value++
continue
}
if value > 10 {
fmt.Println("")
break
}
}
}
//-> 0
// 2
// 4
// 6
// 8
// 10
データ型
文字列型
- インデックスに保存されるバイト数は文字によって異なる。
└漢字はものによって4バイト使用するものがある。
func main() {
str := "abcあいうえお"
for index, codepoint := range str {
result := fmt.Sprintf("index=%d, rune=%d, string=%s", index, codepoint, string(codepoint))
fmt.Println(result)
}
}
// -> index=0, rune=97, string=a
// index=1, rune=98, string=b
// index=2, rune=99, string=c
// index=3, rune=12354, string=あ
// index=6, rune=12356, string=い
// index=9, rune=12358, string=う
// index=12, rune=12360, string=え
// index=15, rune=12362, string=お
len()関数
- 文字列や配列のバイト数を取得する時に使用する
func main() {
str1 := "ABC"
str2 := "あいう"
fmt.Println(len(str1), len(str2))
}
// -> 3 9
RuneCountInString()関数
- 文字数を取得する時に使用する
- unicode/utf8パッケージを読み込む必要がある
import (
"fmt"
"unicode/utf8"
)
func main() {
str1 := "ABC"
str2 := "あいう"
fmt.Println(utf8.RuneCountInString(str1), utf8.RuneCountInString(str2))
}
// -> 3 3
strconvパッケージ
Itoa()関数
- int型整数を文字列に変換する
func main() {
x := 12345
fmt.Println(strconv.Itoa(x))
}
// -> 12345 ※文字列
配列
- デフォルトではゼロ値で初期化される。
-
[...]
で指定すると、初期化の際に設定されて要素数が自動的に配列の長さになる。
func main() {
var array [3]int
for _,value := range array {
fmt.Println(value)
}
fmt.Println("-----")
array[0] = 100
array[1] = 200
array[2] = 300
for _, value := range array {
fmt.Println(value)
}
}
// -> 0
// 0
// 0
// -----
// 100
// 200
// 300
スライス
- ポインタ(ptr)、長さ(len)、容量(cap)からデータ構造を保持している
- 長さをlen()関数、容量をcap()関数で取得できる
- 配列からスライスを作成するだけでなく、スライスからスライスを作成することができる
※スライスは参照型
// スライス構造体
type SliceHeader struct {
Data unitptr //配列の参照
Len int //長さ
Cap int //容量
}
配列からの取得
スライス := 配列またはスライス[下限:上限]
※個人的にいいと思った考え方は:
をスライスと捉える。
└x:
だとx以降のスライス。:x
だとxまでのスライス。
※下限は含み、上限は含まない
func main() {
array := [...]string{"A", "B", "C", "D", "E"}
slice1 := array[:]
slice2 := array[1:3]
slice3 := array[:3]
fmt.Println("参照(Data) ", slice1, slice2, slice3)
fmt.Println("長さ(Len) ", len(slice1), len(slice2), len(slice3))
fmt.Println("容量(Cap) ", cap(slice1), cap(slice2), cap(slice3))
}
// -> 参照(Data) [A B C D E] [B C] [A B C]
// 長さ(Len) 5 2 3
// 容量(Cap) 5 4 5
容量(capacity)
- スライス全体の容量を表す。
- append()で参照元の容量を越すと、倍の容量になる
make()関数
- 配列とスライスを同時に作成することができる
- マップやチャネルを作成する時にも利用される
make([]配列の型, 長さ [,容量])
func main() {
slice1 := make([]int, 3)
slice2 := make([]int, 3, 5)
fmt.Println(slice1, slice2)
fmt.Println(len(slice1), len(slice2))
fmt.Println(cap(slice1), cap(slice2))
}
// -> [0 0 0] [0 0 0]
// 3 3
// 3 5
append()関数
- スライスに値を追加する時に使用する
- 追加することはできるが、削除することはできない。
func main() {
slice1 := make([]int, 3, 5)
slice1 = append(slice1, 100, 200)
fmt.Println(slice1, len(slice1), cap(slice1))
slice2 := make([]int, 2)
slice2[0] = 1000
slice2[1] = 2000
fmt.Println(slice2, len(slice2), cap(slice2))
slice3 := append(slice1, slice2...)
// slice1の方にslice2を追加するイメージ
// 容量もslice1に合わせた形になるため、5*2の10になる
fmt.Println(slice3, len(slice3), cap(slice3))
}
// -> [0 0 0 100 200] 5 5
// [1000 2000] 2 2
// [0 0 0 100 200 1000 2000] 7 10
copy()関数
- スライスの値をコピーすることができる
※下限や上限を設定すれば、コピーする部分を指定することができる
func main() {
slice1 := []int{100, 200}
slice2 := []int{201, 202, 203, 204}
fmt.Println(slice1, slice2)
copyCount := copy(slice2, slice1)
// slice2にslice1をコピーするイメージ
// copyCountはコピーした要素を入れた変数のみ。変数を宣言しなくてもコピーはできる
fmt.Printf("%v コピーした要素の数=%d \n", slice2, copyCount)
}
// -> [100 200] [201 202 203 204]
// [100 200 203 204] コピーした要素の数=2
func main() {
slice1 := []int{100, 200}
slice2 := []int{201, 202, 203, 204}
fmt.Println(slice1, slice2)
copyCount := copy(slice2[3:], slice1)
fmt.Printf("%v コピーした要素数=%d \n", slice2, copyCount)
}
// -> [100 200] [201 202 203 204]
// [201 202 203 100] コピーした要素数=1
func main() {
slice1 := []int{100, 200}
slice2 := []int{201, 202, 203, 204}
fmt.Println(slice1, slice2)
copyCount := copy(slice2[:1], slice1)
fmt.Printf("%v コピーした要素数=%d \n", slice2, copyCount)
}
// -> [100 200] [201 202 203 204]
// [100 202 203 204] コピーした要素数=1
func main() {
slice1 := []int{100, 200}
slice2 := []int{201, 202, 203, 204}
fmt.Println(slice1, slice2)
copyCount := copy(slice2[1:3], slice1)
fmt.Printf("%v コピーした要素数=%d \n", slice2, copyCount)
}
// -> [100 200] [201 202 203 204]
// [201 100 200 204] コピーした要素数=2
値の削除を行う関数はサポートされていないので、関数を自作する必要がある。
func DeleteSlice(slice []int, i int) []int {
slice = append(slice[:i], slice[i+1:]...)
newSlice := make([]int, len(slice))
copy(newSlice, slice)
return newSlice
}
func main() {
slice := []int{1, 2, 3, 4, 5}
fmt.Println(slice, len(slice), cap(slice))
slice = DeleteSlice(slice, 1)
//1番目の値を削除する
fmt.Println(slice, len(slice), cap(slice))
}
// -> [1 2 3 4 5] 5 5
// [1 3 4 5] 4 4