はじめに、、、
プログラミングをはじめて10ヶ月間railsしかやってこなかったのですが、、、
Goを実務で使うことになり大まかにですが基礎文法を軽く1周したのでそのまとめをしたいと思います。
Hello World
import "fmt"
func main() {
fmt.Println("Hello World")
}
//〜出力〜
//Hello World
golangは出力は基本的に fmt.Println
を使うそうです。
またそのために "fmt"
をimportしなければいけません
関数(func) ※Rubyだとdef
引数なし
import "fmt"
func hello() {
fmt.Println("Hello World")
}
func main() {
hello()
}
//〜出力〜
//Hello World
引数有り
import "fmt"
func square(x int, y int) {
fmt.Println(x*y)
}
func main() {
square(5, 10)
}
//〜出力〜
//50
引数の型名を宣言する必要がある。
また上のように引数の型が同じ場合下のようにも書ける
func square(x, y int) {
fmt.Println(x*y)
}
返り値あり
import "fmt"
func hello() string{
return "Hello world"
}
func main() {
fmt.Println(hello())
}
//〜出力〜
//Hello World
返り値を返す場合は func 関数名() 返す値の型
というように書く必要がある
jsの即時関数的な感じ
import "fmt"
func main() {
func (msg string) {
fmt.Println(msg)
}("Hello World")
}
//〜出力〜
//Hello World
変数に関数を入れる
import "fmt"
func main() {
h := func() {
fmt.Println("Hello World")
}
h()
}
//〜出力〜
//Hello World
条件文
if文
import "fmt"
func main() {
score := 70
if 80 < score {
fmt.Println("Great!")
} else if 50 < score {
fmt.Println("Good!")
} else {
fmt.Println("Bad")
}
}
//〜出力〜
//Good!
そのif文の中だけで評価する変数をつかう
import "fmt"
func main() {
if score := 70; 80 < score {
fmt.Println("Great!")
} else if 50 < score {
fmt.Println("Good!")
} else {
fmt.Println("Bad")
}
fmt.Println(score)//⬅︎「score」っていう変数ないよ!っていうエラーがでる。
}
//〜出力〜
//Good!
switch文
import "fmt"
func main() {
score := 70
switch {
case 80 < score:
fmt.Println("Great!")
case 50 < score:
fmt.Println("Good!")
default:
fmt.Println("Bad")
}
}
//〜出力〜
//Good!
map※rubyだとハッシュ
import "fmt"
func main() {
m := map[int]string{1: "田中", 2: "鈴木", 3: "佐藤", 4: "渡辺"}
fmt.Println(m)
fmt.Println(m[1])
}
//〜出力〜
//map[1:田中 2:鈴木 3:佐藤 4:渡辺]
//田中
//4
mapの作り方としては map[キーの型]バリューの型
と宣言して後はハッシュ(他の言語だと連想配列)と同じように宣言する。
スライス※rubyだと配列
注意!!! Goにもスライスとは別に配列そのものは存在しますがGoでは配列とほぼ同じ使い方が出来てなおかつ使い勝手もいいスライスが使われることが多いみたいです(間違ってたら指摘お願いします。)なので最初はスライス==配列ということにします
import "fmt"
func main() {
c := []int{1, 3, 7}
fmt.Println(c)
}
//〜出力〜
//[1 3 7]
スライスの作り方としては []配列の型{}
として後はコロンで要素を区切って作る
range※rubyだとeach文
import "fmt"
func main() {
s := []int{1, 3, 7}//スライスを作成
for i, v := range s {
fmt.Println(i, v)
}
}
//〜出力〜
//0 1
//1 3
//2 7
rangeは返り値としてインデックス番号と値を返します。今回はiでインデックス番号、vで要素の値を受け取っています。
また仮に配列の要素のみ使いたい場合は for _, v := range c {
とする事でインデックス番号を無視してくれます
for文
import "fmt"
func main() {
for i := 1; i < 100; i++ {
fmt.Println(i)
}
}
//〜出力〜
//1
//2
//3
//・
//・
//・
//99
//条件をいれないと無限ループする
for {
fmt.Println("Hello world")
}
//〜出力〜
//Hello world
//Hello world
//Hello world
//Hello world
//・
//・
//・
while文っぽくもかける
でも、GOにwhile文は存在しない
import "fmt"
func main() {
sum := 1
for sum < 30 {
sum += sum
fmt.Println(sum)
}
}
//〜出力〜
//2
//4
//8
//16
//32
構造体(struct)
イメージとしてはrailsのmodelみたいな感じ
import "fmt"
//railsのmigration fileのように[カラム名 データ型]という形で定義
type User struct {
Name string
Age int
}
func main() {
//railsでデータをcreateするときのparamsと同じような形で定義
user1 := User{Name: "kosuke", Age: 21}
fmt.Println(user1)
//そのデータに紐づく値を持ってくるときに 「.」区切りで値を参照できる
fmt.Println(user1.Name)
fmt.Println(user1.Age)
}
//〜出力〜
//{kosuke 21}
//kosuke
//21
ただ、↑でいっていることはあくまでイメージの話でgoの構造体はあくまでデータ型の1つであるのでその点は忘れないこと!
構造体の値をメソッドを使って変える
import "fmt"
type User struct {
Name string
Age int
}
func (u *User) changeName(string){
u.Name = "Yamada"
}
func main() {
user1 := User{Name: "kosuke", Age: 21}
fmt.Println(user1.Name)
user1.changeName(user1.Name)
fmt.Println(user1.Name)
}
//〜出力〜
//kosuke
//Yamada
メソッドの定義方法は
func (メソッド内での変数名 *構造体名) メソッド名(このメソッド内の引数の変数 引数のデータ型)
となっています。
また、重要なのは構造体名の前についている「*」でこれを書くことでポインタを渡すことができます。
ポインタってなんぞ?って人は下の記事が個人的にはわかりやすかったのでこちらを参照してください。
ざっくりとした認識としては
「とりあえず生成した構造体をメソッド使って値を変更させたいときは「*」つければいいんだな」
って思っておけばいいと思います。
インターフェース
import "fmt"
//メソッド名(引数の型, ...) (返り値の型, ...)
type Human interface{
Say() string
}
type Person struct {
Name string
}
func (u *Person) Say() string{
u.Name = "Mr." + u.Name
return u.Name
}
func main() {
var user1 Human = &Person{Name: "kosuke"}
fmt.Println(user1.Say())
}
//〜出力〜
//Mr.kosuke
インターフェイスとはメソッドの型です。
詳しくは↓
【Golang】Golangのinterfaceで知っておくとお得なTips
並行処理
import (
"fmt"
"time"
)
func hello() {
fmt.Println("hello")
}
func world() {
fmt.Println("world")
}
func main() {
go hello()
go world()
time.Sleep(3 * time.Second)//3秒間動きを止める処理
}
//〜出力〜
//hello
//world
//または
//world
//hello
プログラムのコードは普通上から順番に読まれていきますが、Goでは
go hogehoge
とすることで同時に処理を行うことができます。
しかし、並行処理をしている間にプログラムそのものが終了してしまう可能性もあります。
それを回避するためには以下のように"sync"
をimportして使用することで回避することができる
import (
"fmt"
"sync"
)
func hello(wg *sync.WaitGroup) {
defer wg.Done()//deferはその関数内で一番最後に呼ばれるようにするメソッド
fmt.Println("hello")
}
func world() {
fmt.Println("world")
}
func main() {
var wg sync.WaitGroup
wg.Add(1)
go hello(&wg)
go world()
wg.Wait()//「wg.Done()」が呼ばれるまで処理をストップ
}