始めに

この記事はGO言語を自分が勉強していくにあたって使うメモ記事です。なので内容が整理されていなかったり、間違っていたりする可能性があります。

本題

実行について

  • mainパッケージのmain関数から実行されていく
  • 基本上から実行
  • go build ファイル名  => ./ファイル名(.goは除く)
  • go run ファイル名 でも実行できる

変数

データ型

  • 基本データ型  =>  string, int, float64, bool, nil
  • 初期値  => string="", int=0, bool=false
  • 種類 : var => 変数名 := 値 で宣言もできる
  • Printf内の変数参照 => string: %s, int: %d, float: %f, bool: %t
    %vはいい感じに帳尻を合わせる
  • 定数 => const, 変数 => var
  • キャスト : 変換先の型(変換したい型)
  • iota :数値を変数の宣言順に0から1+して作ってくれる
    const (
        a = iota //0
        b //1
        c //2
        d //3
    )
  • and => &&, or => ||
  • +=, *=, a++, b-- 等も可。ただし++a, --aは不可

特徴

  • 宣言の型推論がきるので、自明な時は型を省略できる
  • 変数名一文字目が大文字 =>ほかのパッケージでも見える
  • 変数名一文字目が大文字 =>同じパッケージのみ見える

ポインタ

  • 演算は不可
  • アドレスを格納する変数宣言:
    var 変数名 *型
  • 宣言されている変数のアドレスを参照するとき
    &変数名
  • アドレスがさす場所に格納された値を参照するとき
    *アドレス(アドレスを格納した変数)

配列

  • var 変数名 [配列の大きさ]型
  • 変数名[添え字] = 代入値
  • 配列名 := [配列の大きさ]型{@,@,@}
    配列名 := [...]型{@,@,@}でも可
  • 3番目が45、45番目が67で他が0の要素数67の配列slの作り方
    sl := [...]int{3: 45, 45: 67}
  • 配列の大きさlen(配列名)

スライス

  • スライス => s := a[最初, 最後]   (*最後の要素は含まない)
  • スライスは配列の指定したアドレスと値を記録したものなので、スライスの値を書き換えると対応する配列の値も書き換わる
  • cap(スライス名) : スライスを作るときに指定した最初の位置か最後の最後の位置までの大きさを調べる
  • make([]型, 要素数, 容量) //要素数のみの記述で要素数=容量とできる
  • 3番目が45、45番目が67で他が0の要素数67のスライスslの作り方
    sl := []int{3: 45, 45: 67}
  • append(スライス名[要素指定], 追加要素, .......)
    要素数<容量の時 : アドレスの参照値は変わらない
    要素数=容量の時 : アドレスの参照値が変わる // b = append()したとき
  • copy(コピー先, コピー元) //返り値としてコピーした要素数を返す

map

  • 変数名 := make(map[キーの型]値の型)
    変数名[キー] = 値

    m := map[キーの型]値の型{キー:値}でも可
  • len(map名) : ペアの個数を返す
  • delete(map名, キー) //キーがない場合は何も行われない
  • v , tf := 変数名[キー] //キーが存在すればvに値が、tfに true or false が入る

range

  • range : forEachのようなもの //配列、スライス、mapで可
    s := []string{@,@,@}
    for i, v:= range s { //i(キー), v(値)
      // for _, v := range s {}でインデックス省略できる *ブランク修飾子
        fmt.Println()
    }

関数

  • 関数宣言
    func 関数名(引数 型) 返り値の型(必要なら) {
        処理
    }
    or
    func 関数名(引数 型) (返り値変数 返り値の型) {
        処理
        return
    }
    でも指定した返り値が返される
  • 関数から複数の値を返す
    func swap(a, b int) (int, int){
        return b,a
    }
  • 関数はデータ型
    変数名 := func(引数) (返り値){処理}
    と書け
    変数名(引数)
    で呼び出せる
  • 即時関数の書き方もできる
    func(引数) {処理}(使う変数) //一番後ろの()でその場で利用することが明示される。

条件分岐

  • 等価は == で、不等価は!=
  • for の利用可
    for i :=0; iの条件; i++{}  // ()はいらない
    for i条件 {} //iの宣言を外に置くことでwhile文もどきも作れる
  • if s>100{ }else if s<200{} else{}と書ける。()が無くてもよい。
  • if専用のローカル変数を使いたい場合は
    if s := 20; s>200{}と書ける
  • switchもある
    switch 変数 {
        case 変数条件:
    	処理
        default:
    	処理
    }
    or
    switch {
        case 条件:
    	処理
        default:
    	処理
    }

標準関数

  • fmt.Scanf("%@", &変数)  =>C言語みたいにアドレスでやっているっぽい
    fmt.Printf("%@", &変数)  =>変数を表示させるときはPrintf
  • rand.Intn(数値)  =>0から入力した数値いの一つ前まで,ただし乱数生成の種値は固定なので指定しなおす必要あり。rand.Seed(値)
  • time.Now()  =>現在時刻の取得

構造体

    • 宣言方法 :
      Stype user struct { //フィールド
      	name string
      	score int
      }
      
      u := new(user)
      //fmt.Println(u) => &{ 0} で空文字と0がポインタで返却される
      u.name = "mary"
      //(*u).name = "mary"も可
      (*u).score = 20
      fmt.Println(u) //&{mary 20}
      m := user{"kary", 50}
      // m := user{name: "kary",score: 50}も可
      fmt.Println(m) //{kary 50} <=ポインタはかえって来ない
    • 構造体に紐づいたメソッド :
      func (u user) show(){ //値渡し、コピーのみ渡す
         //func (u *user) show()で参照渡し(アドレスで渡し変更が本体にも適用される
      )もできる
      	fmt.Printf("name: %s, score: %d\n", u.name, u.score)
      }

インターフェース

  • 実装例 : こっちはインターフェースという仕組み
    type greeter interface { //インターフェース部分
    	greet() //ここの記述によりgreet()メソッドを実装した構造体はgreeterインターフェースに自動的になる
    }
    
    type japanese struct {}
    type american struct {}
    //japanese, aamericanがgreeter interfaceの実装部分
    func (j japanese) greet(){
    	fmt.Println("こんにちは")
    }
    func (a american) greet(){
    	fmt.Println("Hello")
    }
    // greet()メソッドが実装されたのでjapanese, aamericanはgreeter interfacになる
    
    func interfaceF(){
    	greeters := []greeter{japanese{}, american{}}
               //greeter interfaceとしてjapanesse, americannを一つのスライスに格納可能
    
    	for _, greeter := range greeters {
    		greeter.greet()
    	}
    }
  • Generics的な例 : こっちはインターフェース
    func show(i interface{}){ //どんな型でも受け入れられる。Genericsみたい
    	//型アサーション
    	_, tf := i.(japanese) // 値, japaneseかどうか
    	if tf {
    		fmt.Println("私は日本人")
    	} else {
    		fmt.Println("I'm American.")
    	}
    
    	//型switch
    	switch i.(type) {
    	case japanese:
    		fmt.Println("よろしゅう")
    	case american:
    		fmt.Println("Have a nice day!")
    	default:
    		fmt.Println("???")
    	}
    }
    

goroutine

  • 平行処理させる(非同期とか?) :
    func longTask(){
    }
    
    func shortTask(){
    }
    
    func gorutineF(){
    	go longTask() //goを前につけることで同時実行
    	go shortTask()
    
    	time.Sleep(time.Second * 4) //勝手にタスク終了することを防ぐ
    }

channel

たぶん非同期的に値を取得する方法。goroutineは値を返すようになっていないのでgoを使う関数に引数としてチャネルの変数を渡してあげる。

func f1(result chan string){
	time.Sleep(time.Second * 2)
	fmt.Println("Long task was finished!")
    result<- "result is this"
}

func f2(){
	fmt.Println("Easy task was finished!")
}

func channelf(){
	result := make(chan string) //chanがチャネルだよっていう合図
	fmt.Println("task start") 
	go f1(result)
	go f2()

	fmt.Println("run and wating")
	fmt.Println(<-result) //読み込まれた時点でresultの中身がない場合f1でresultに代入があるまで出力されない
	time.Sleep(time.Second * 4)
}

実行結果

task start
run and wating
Easy task was finished!
Long task was finished!
result is this

非同期

defer : 遅延実行する
defer r.Body.Close()  // ファイルを閉じる作業を一番最後に実行する。


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です