Open15

Goの学習記録

じん@酒酔いエンジニアじん@酒酔いエンジニア

Goを始めるにあたっての学習記録

Goのメリット・デメリット

メリット

  • 記述がシンプル ←読みやすいけど、書けないワロタ
  • 高速な処理が可能
  • 複雑なシステム構築に最適
  • 並列処理が可能
  • メモリーの安全性が高い

デメリット

  • 継承ができない
  • 三項演算子ができない
  • Genericsが実装されたばかりで情報がすくない
  • 例外処理がない

まずはGoに触れてみる

The Go Playgroundにてどんなコードなのかを体験してみる。

package main

import "fmt"

func main() {
	fmt.Println("Hello world! ")
}

>> Hello world!
じん@酒酔いエンジニアじん@酒酔いエンジニア

環境構築

この「Golangの環境設定(Mac編)」を参考に環境構築をした。

  1. Goのインストール
    https://go.dev/ からダウンロード
  2. パスを通す(viエディタ)
terminal
// zshrc
vi ~/.zshrc 

export GOPATH=$HOME/go 
export PATH=$GOPATH/bin:$PATH

// 別ウィンドウで環境変数の反映と確認
source ~/.zshrc
  1. vscodeでの環境構築
  • Goの拡張機能のインストール
  • コマンドパレット(command+shift+p)でinstall/update toolsと検索して、出てきた7つのものを全てアップデートする。
  • Users/<username>/Library/Application Support/Code/User/setting.json"go.gopath": "Users/<username>/go"を記述(goのpathを記述)

以上!

setting.jsonに書かずとも動くが、path通さないと今後困ることが多発しそうなので、一応。

じん@酒酔いエンジニアじん@酒酔いエンジニア

変数

型について

  • その文字や記号はどんな種類かを表したもの
    • 整数(int)、浮動小数点数(float)、真偽値(true/false)、文字列(string) etc.
    • “ユーザ定義型”という自分で型を作ることができる
  • goの場合は静的型付けの言語
    • コンパイル時に型を検証する
    • 変数に型がある、型が違うと代入できない

変数定義

var <変数名> <型>  で記述する。

各変数の書き方
var pen int = 10  // 初期値あり
var book int  //初期値なし( =0 になる)

 // 初期値なしの後に定義できる
var book int 
num = 100

// 型推論により、型の宣言を省略
var num = 100 

// varの省略(下は本来の書き方)
text := "酒酔いエンジニア" 
var text string = "酒酔いエンジニア"

// 複数の宣言
// 1行で複数の宣言
var text1, text2, text3 string = "text1", "text2", "text3"

// まとめて変数宣言
var (
        text1 string = "text1"
        text2 string
        text3 = "text3"
        num1, num2 int = 100, 200
        num3, num4 int32
        num5, num6 = 500, 600
    )
一覧チートシート
// 文字列
var name string = "John Smith"

// 整数
var age int = 30

// 浮動小数点数
var height float64 = 5.9

// ブーリアン
var isMarried bool = false

// 配列
var colors [3]string = [3]string{"red", "green", "blue"}

// スライス
numbers := []int{1, 2, 3, 4, 5}

// マップ
person := map[string]string{"name": "John Smith", "age": "30"}

// 構造体
type Person struct {
    Name string
    Age int
}

var john Person = Person{Name: "John Smith", Age: 30}

参考文献

じん@酒酔いエンジニアじん@酒酔いエンジニア

変数名について

基本的にMixedCapsとすることがある。ただ、公開/非公開によって異なる。

  • 公開の場合: MaxLength
  • 非公開の場合: maxLength
    のように、頭文字が大文字か小文字かで意味合いが変わってくる。

また、長い名前より短い名前が好まれる。


変数は短縮形式 := とvarどちらを使うべきか

結論: "使えるところではどんどん短縮記法を使うべき" である。
ただし、明示的に別の形にしたい場合はどちらでもいい。

じん@酒酔いエンジニアじん@酒酔いエンジニア

関数について

基本的な構文はfunc 関数名(パラメータ){}である。

func 関数名(パラメータ) {
  // コードブロック
}

関数同士の紐付け

関数同士の呼び方は、ファイルが別であるか、package名が別であるかによって変化する。

同じソースコード内の関数の呼び方

package main

import (
    "fmt"
)

func calc(fn func(int, int) int, x int, y int) (res int) {
    fmt.Println("(A)")
    res = fn(x, y) // 関数:add を実行
    return
}

func add(x int, y int) int {
    fmt.Println("(B)")
    return x + y
}

func main() {
    fmt.Println(calc(add, 1, 2))
}

出力内容

// 結果
(A)
(B)
3

別の関数を同じソースコード内で呼ぶ場合は、
引数をしていしながら、呼び出す。そうしなければ、エラーが出る。

詳しくはここ↓
https://qiita.com/tsurumiii/items/0294feebc0216b185765

構造体との紐付け

class内にメソッドの定義ができないため、構造体(struct)と紐づけることができる。

func(構造体名) 関数名(パラメータ) {
  // コードブロック
}

構造体を用いた場合の例:

structがある場合
package main

import "fmt"

type Human struct {
    Name   string
    Age    int
}

func (h Human) addAge(i int) int {
    return h.Age + i
}

func main() {
    // インスタンス生成
    hoge := Human{
        Name:   "hoge",
        Age:    20,
    }

    fmt.Printf("%#v \n", hoge)
    hoge.Age = hoge.addAge(1)
    fmt.Printf("%#v \n", hoge)
}

【Go】入門(構造体と関数を紐付ける) より。

じん@酒酔いエンジニアじん@酒酔いエンジニア

https://qiita.com/jin237/items/e38a728744394ef56176

Goについて勉強し始めたとき

これまでにreactやvue関連、pythonなどしかしてこなかった自分が仕事でGoを使うことになり勉強し始めた時にめちゃくちゃ役立った記事です。今回は関数周りでどうすればいいんだろう?と疑問に思った時に、大体が解決するようにまとめておいたものをそのまま記事用に落とし込んだものです。

誰かしらの何かしらの役に立てば嬉しく。
(あと自分用)

目次

  1. Goの関数の基本
  2. 関数の引数や戻り値
  3. 構造体との紐付け
  4. エラーハンドリング

↑この分類は適当です(笑)😋😋😋😋😋😋😋😋

Goの関数の基本

https://qiita.com/gorilla0513/items/7e734c4e0680b5ea341d

https://qiita.com/mackiso/items/e435e154e3376a68dcca

関数の引数や戻り値

関数同士の呼び方は、ファイルが別であるか、package名が別であるかによって変化する。

https://qiita.com/tsurumiii/items/0294feebc0216b185765

別ファイルの関数呼び出し

https://qiita.com/suin/items/f4ad02e4123c8a3c75eb

構造体との紐付け

-【Go】入門(構造体と関数を紐づける)

https://qiita.com/Kazuhiro_Mimaki/items/700f2910fa4e5f5c1512

https://qiita.com/ruiu/items/85b72bc94e08d192d90b

https://qiita.com/HiromuMasuda0228/items/65b9a593275f769f6b69#構造体struct

https://qiita.com/zurazurataicho/items/4a95e0daf0d960cfc2f7

エラーハンドリング

https://qiita.com/immrshc/items/13199f420ebaf0f0c37c

https://qiita.com/kwbt/items/241b574cc8493de030ae







※謝罪とお詫び

作者の方々、読んで参考にさせていただきました。ありがとうございました。
また、勝手に載せてしまい、申し訳ありません。削除依頼や何かしらの問題がある場合、ご連絡ください。

じん@酒酔いエンジニアじん@酒酔いエンジニア

構造体まとめ

Goの構造体の特徴

構造体の書き方

基本的な書き方↓

type Book struct {
	Tilte       string
	Author      string
	Publisher   string
	ReleasedAt  time.Time
	ISBN        string
}

構造体の中に構造体を定義できる↓

type Book struct {
	Tilte       string
	Author      struct {
		FirstName   string
		LastName    string
	}
	Publisher   string
	...
}

でも,別々の構造体にするのがおすすめ↓

type Book struct {
	Tilte           string
	Author       Author
	Publisher   string
	...
}

type Author struct {
	FirstName   string
	LastName    string
}

ポインターと構造体のメンバーアクセス

type Book struct {
	Title  string
}

func main() {
	// bはBookインスタンスへのポインタ
	b := &Book {
		Title: "本のタイトル",
	}
	
	fmt.Println(b.Title)         // "本のタイトル"
	fmt.Println((*b).Title)     // "本のタイトル"
	
	b2 := b   
	fmt.Println(*b2)             // "{本のタイトル}"
	fmt.Println(b2.Title)       // "本のタイトル"
}
type Book struct {
	titleName  string 
	amount      int
}

func newBook(titleName string, amount int) *Book{
	b := new(Book)
    b.titleName = titleName
    b.amount = amount
    return b
}

func main(){
   var store *Book = newBook("本のタイトル", 10)
	fmt.Println(store.titleName, store.amount)
}

じん@酒酔いエンジニアじん@酒酔いエンジニア

Golang入門(関数)

https://qiita.com/gorilla0513/items/7e734c4e0680b5ea341d

Golangの変数とか関数とか[基礎]

https://qiita.com/mackiso/items/e435e154e3376a68dcca

golang 関数(func)の引数や戻り値で関数を指定したときの動作

https://qiita.com/tsurumiii/items/0294feebc0216b185765

Go言語のpackageの作り方: 長くなったコードを別ファイルに切り出す方法

https://qiita.com/suin/items/f4ad02e4123c8a3c75eb

【Go】入門(構造体と関数を紐づける)

https://qiita.com/Kazuhiro_Mimaki/items/700f2910fa4e5f5c1512

Goのメソッドは構造体以外にでも定義できるしそれが便利なこともよくある

https://qiita.com/ruiu/items/85b72bc94e08d192d90b

Go言語:文法基礎まとめ の構造体の部分

https://qiita.com/HiromuMasuda0228/items/65b9a593275f769f6b69#構造体struct

Goの構造体をpackageに外出ししてハマッたこと

https://qiita.com/zurazurataicho/items/4a95e0daf0d960cfc2f7

Golangのエラーハンドリングの基本

https://qiita.com/immrshc/items/13199f420ebaf0f0c37c

Go言語でハマったことメモ(インターフェース)

https://qiita.com/kwbt/items/241b574cc8493de030ae

Golangのtestify/assert 使えそうな関数まとめ
https://qiita.com/JpnLavender/items/21b4574a7513472903ea

ログ設計指針

https://qiita.com/nanasess/items/350e59b29cceb2f122b3

Goのfor rangeでのポインタでハマったこと

https://qiita.com/uchiko/items/1c611f0db618ce9dc0a9

Goのdeferの仕組みをきちんと理解する

https://qiita.com/kohekohe1221/items/fb11a3572251f31c5ae5

じん@酒酔いエンジニアじん@酒酔いエンジニア
goroutineの実験
package main

import (
	"fmt"
	"sync"
	"time"
)

func main() {

	fmt.Println("はじまり〜")
	var wg sync.WaitGroup

	// WaitGroupのカウンタを2つ増やす
	wg.Add(2)

	// process1をgoroutineとして実行
	go func() {
		heyko1() 
		defer wg.Done() // 処理が完了したらWaitGroupのカウンタを減らす
	}()

	// process2をgoroutineとして実行
	go func() {
		heyko2()
		defer wg.Done() // 処理が完了したらWaitGroupのカウンタを減らす
	}()

	// すべてのgoroutineが終了するのを待つ
	wg.Wait()

	fmt.Println("おわり〜")
}

func heyko1() {
	start := time.Now()
	time.Sleep(10 * time.Second)
	end := time.Now()
	fmt.Println("heyko1: ", (end.Sub(start)).Seconds())
	fmt.Println("heyko1: ", start.Format("2006-01-02T15:04:05Z07:00"), "~~", end.Format("2006-01-02T15:04:05Z07:00"))
}

func heyko2() {
	start := time.Now()
	end := time.Now()
	fmt.Println("heyko2: ", (end.Sub(start)).Seconds())
	fmt.Println("heyko2: ", start.Format("2006-01-02T15:04:05Z07:00"), "~~", end.Format("2006-01-02T15:04:05Z07:00"))
}