Goの学習記録
このスクラップについて
Goを始めるにあたっての学習記録
Goのメリット・デメリット
メリット
- 記述がシンプル ←読みやすいけど、書けないワロタ
- 高速な処理が可能
- 複雑なシステム構築に最適
- 並列処理が可能
- メモリーの安全性が高い
デメリット
- 継承ができない
- 三項演算子ができない
- Genericsが実装されたばかりで情報がすくない
- 例外処理がない
まずはGoに触れてみる
The Go Playgroundにてどんなコードなのかを体験してみる。
package main
import "fmt"
func main() {
fmt.Println("Hello world! ")
}
>> Hello world!
Goの最新状況を知るための情報源
- standard library:
- go release note:
- effective go:
- the go blog:
Goの学習に使える教材
- a tour of go:
- go by example:
- java to go in-depth tutorial:
- プログラミング言語のGo完全入門:
環境構築
この「Golangの環境設定(Mac編)」を参考に環境構築をした。
- Goのインストール
https://go.dev/ からダウンロード - パスを通す(viエディタ)
// zshrc
vi ~/.zshrc
export GOPATH=$HOME/go
export PATH=$GOPATH/bin:$PATH
// 別ウィンドウで環境変数の反映と確認
source ~/.zshrc
- 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
別の関数を同じソースコード内で呼ぶ場合は、
引数をしていしながら、呼び出す。そうしなければ、エラーが出る。
詳しくはここ↓
構造体との紐付け
class内にメソッドの定義ができないため、構造体(struct)と紐づけることができる。
func(構造体名) 関数名(パラメータ) {
// コードブロック
}
構造体を用いた場合の例:
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について勉強し始めたとき
これまでにreactやvue関連、pythonなどしかしてこなかった自分が仕事でGoを使うことになり勉強し始めた時にめちゃくちゃ役立った記事です。今回は関数周りでどうすればいいんだろう?と疑問に思った時に、大体が解決するようにまとめておいたものをそのまま記事用に落とし込んだものです。
誰かしらの何かしらの役に立てば嬉しく。
(あと自分用)
目次
↑この分類は適当です(笑)😋😋😋😋😋😋😋😋
Goの関数の基本
関数の引数や戻り値
関数同士の呼び方は、ファイルが別であるか、package名が別であるかによって変化する。
別ファイルの関数呼び出し
構造体との紐付け
- Go言語:文法基礎まとめ の構造体の部分
エラーハンドリング
※謝罪とお詫び
作者の方々、読んで参考にさせていただきました。ありがとうございました。
また、勝手に載せてしまい、申し訳ありません。削除依頼や何かしらの問題がある場合、ご連絡ください。
構造体まとめ
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)
}
アプリ作成
asdfで管理
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"))
}
【Goのやさしい記事】goroutineと排他制御を10分で入門しよう!
ロギングとかを含めた排他制御の基礎としてめっちゃ参考になる
aaa
クリーンアーキテクチャ