Golang入門編〜基礎文法/配列まで〜

前書き

今回はGolangの基礎文法についてまとめていきます。Golangとは静的型付け言語であり、C言語の伝統に基づいたコンパイラ言語です。その為PythonJavaScriptなどのインタプリタ言語に加えると実行速度自体は速いとされています。JavaC++のような静的型付けによるセキュリティの堅牢性やRubyPythonのような可読性をいいどこ取りした言語のように感じます。一方で、Golang自体はモダンな言語とされていますが、一般的にシステムへの使用度は低く、JavaRubyの方が国内では使用されています。Golangの由来自体はGoogleエンジニア により開発されたことが起因とされています。

Golangではオブジェクト指向型言語ではない為クラスの概念は存在しませんが、構造体・インターフェースで代用できます。

文法基礎

まずはGolangに関する基礎文法をざっくり勉強していきます。今回はUdemyをベースにQiitaでおさらいしながら学習を進めました。

変数定義

ローカル変数とパッケージ変数(関数外部で定義された変数)の定義は以下のような感じです。

package main
import  "fmt"

// パッケージ変数
var (
    n int = 100
    t float64 = 3.64
    u8 uint8 = 255
    i8 int8 = 127
    f32 float32 = 0.2
    c64 complex64 = -15+100i
)

func main() {
    var a int = 50 // ローカル変数
    k := 3.2 // 簡略化したローカル変数定義
    n = n + a  // パッケージ変数は参照可能
    fmt.Printf("n=%d\n", n)
    fmt.Printf("%f\n", k)
}

表示

const (
    team_name = "buffaloes"   
    co_name = "ORIX"
)

func main(){
    var k int8 = 4
    fmt.Println("num------------")
    fmt.Printf("type=%T : value=%v\n", k, k)
    
    fmt.Println("const----------")
    fmt.Println(team_name, co_name)
}
num------------
type=int8 : value=4
const----------
buffaloes ORIX

シフト

func main(){
    fmt.Println("shift----------")
    fmt.Println(1 << 0)
    fmt.Println(1 << 1)
    fmt.Println(1 << 2)
}
shift----------
1
2
4

文字列変換

import (
    "fmt"
    "strings"
)

func main(){
    fmt.Println("replace----------")
    var ss string = "Hello World"
    fmt.Println(strings.Replace(ss, "H", "O", 1))
}

Boolean

func main(){
    fmt.Println("boolean----------")
    t, f := true, false
    fmt.Println(t || f)
    fmt.Println(t && f)
    fmt.Println(!f)
}
boolean----------
true
false
true

Type(型)変換

func main(){
    fmt.Println("retype----------")
    var x int = 1
    xx := float32(x)
    fmt.Printf("%T\n", xx)
}
retype----------
float32

文字列→数値変換

import (
    "fmt"
    "strconv"
    )

func main(){
    fmt.Println("strconv----------")
    var s string = "999"
    // i, _ := stconv.Atoi(s)
    i, err := strconv.Atoi(s)
    if err != nil {
        fmt.Println("Error")
    }
    fmt.Printf("%v %T\n", i, i)
}
strconv----------
999 int

配列の定義

ここでは長さ2の配列を定義した為、可変ではないことに注意。

func main(){
    fmt.Println("list----------")
    var aa [2]int
    aa[0] = 1
    aa[1] = 2
    fmt.Println(aa)
}
list----------
[1 2]

可変配列の定義

可変配列を定義したい場合は、長さを指定しません。
加えて、スライスは以下のように定義します。

func main(){
    fmt.Println("list----------")
    var bb []int = []int{200, 300}
    bb = append(bb, 300, 400, 500)
    fmt.Println(bb)
 fmt.Println(bb[2])
    fmt.Println(bb[2:5])
    fmt.Println(bb[:])
}
list----------
[200 300 300 400 500]
300
[300 400 500]
[200 300 300 400 500]

二重配列

func main(){
    var board = [][]int{
        []int{0,1,2},
        []int{0,1,2},
        []int{0,1,2},
    }
    fmt.Println("list----------")
    fmt.Println(board)
}
list----------
[[0 1 2] [0 1 2] [0 1 2]]

make

後に2つの組み込み関数(make vs new)の比較で頭がこんがらがります。
makeに割り当てられるのは、スライス、マップ、チャネルのみです。
makeでは初期化された、すなわちゼロ値でないT型(Type)を返します。
スライスはデータ(配列内)へのポインタ、長さ、キャパシティで成り立っていて、
初期化されるまでは要素の値はNilとなっています。

func main(){
    fmt.Println("make capacity----------")
    naa := make([]int, 3, 5)
    naa = append(naa, 2, 3)
    naa = append(naa, 2, 3)
    fmt
make capacity----------
len=7 cap=10 value=[0 0 0 2 3 2 3]

makeで空配列作成

func main(){
    fmt.Println("make capacity----------")
    aa := make([]int, 0)
    var bb []int
    fmt.Printf("len=%d cap=%d value=%x\n", len(aa), cap(aa), aa)
    fmt.Printf("len=%d cap=%d value=%x\n", len(bb), cap(bb), bb)
}
make capacity----------
len=0 cap=0 value=[]
len=0 cap=0 value=[]

連想配列

連想配列では存在しないキーの追加も行うことも可能だが、初期時点で連想配列が空の場合はエラー。
空配列はNilとして判定されるので注意が必要。

func main(){
    fmt.Println("map--------------------")
    m := map[string]float32{"yoshida": 0.350, "yanagita": 0.342, "kondo": 0.341}
    fmt.Println(m)
    m["yoshida"] = 0.389
    fmt.Println(m)

    value, _ := m["yamamoto"]
    fmt.Println(value)

    // var lis[]int -> 空(Nil)
}
map--------------------
map[kondo:0.341 yanagita:0.342 yoshida:0.35]
map[kondo:0.341 yanagita:0.342 yoshida:0.389]
0

関数の使い方

func add(x int, y int) (int, int) {
    return x + y, x-y
}

func main(){
    fmt.Println("function--------------------")
    nadd, adelta := add(10, 20)
    fmt.Printf("add: %d , delta: %d", nadd, adelta)
}
function--------------------
add: 30 , delta: -10

関数の使い方(返り値を指定)

返り値の変数と型を指定することも可能です。

func cal(block, number int)(all int){
    all = block * number
    return
}

func main(){
    all := cal(100, 2000)
    fmt.Printf("ブロックの総数が%d個です", all)
}
ブロックの総数が200000個です

即時関数・無名関数

func main(){
    function1 := func(x int){
        fmt.Println("function1 : ", x)
    }
    function1(100)
    
    func(x int){
        fmt.Println("function2 : ", x)
    }(100)
}
function1 :  100
function2 :  100