はじめに
golangを学ぶにあたって、基本的な文法をまとめてみました。
超基本的な内容です。随時、アップデートします。
環境構築(Mac)
brew update
brew install go
go version
実行
package main
import ("fmt")
func main(){
fmt.Println("おはよう")
fmt.Println("こんにちは")
fmt.Println("こんばんは")
}
・Goのプログラムは、何らかのパッケージに属している必要がある
・Goのプログラムは、そのうち1つは、必ずmainパッケージに属している必要がある
・ここでは、プログラム内で使う「fmt」というパッケージをインポートしている
・fmtパッケージをインポートすることで、fmtパッケージの中にある関数などを使えるようになる
・fmtパッケージには、文字列を表示させる関数が入っている
・Goでは、fmtパッケージのようなよく使う関数をひとまとめにして、「パッケージ」という形で提供している
・ここでは、mainという名前の関数を定義している
・Goのプログラムは、mainパッケージの中にあるmain関数からプログラムがスタートする
・プログラムがスタートする場所のことを、エントリーポイントと呼ぶ
go build hello.go
./hello
おはよう
こんにちは
こんばんは
変数
変数とは
・変数は例えるなら箱のこと
・変数があることで、文字や数字などのデータを変数に入れておくことができる
・また、変数を必要な時に取り出すことができる
・変数にデータを入れることを「代入」といい、取り出すことを「参照」という
・変数には名前をつけることができ、変数名という
・変数を作ることを「変数を宣言する」という
・初めて変数にデータを入れることを「変数の初期化」という
変数の宣言
package main
import ("fmt")
func main(){
var num int
num = 1
fmt.Println(num)
}
・ここでは整数などの値を代入するnumという変数を宣言している
・変数を宣言するときは、まずvarと書く
・varの次に変数名を記述
・変数名のあとに、変数に代入するデータの種類を記述
・このデータの種類のことを「データ型」という
・ここでは、1という値を代入するので、値型の「int型」使用する
・ここでは、変数numに1という整数を代入している
・変数へ代入するときは、イコールを使う
文字列や変数の中を参照するには、Println(プリントライン)関数を使う
・前項目ではダブルクォテーションで文字列を囲んだが、今回は変数の中を表示したいので、変数をそのまま記述する
1
var num = 1
fmt.Println(num)
・変数の宣言と同時に代入することもできる
・また、データ型は省略することもできる
・Goが自動的にデータ型を判断するから
num := 1
fmt.Println(num)
・変数の宣言と同時に代入する際は、さらにシンプルに書くことができる
・変数名、コロン、イコール、代入したい値の順に記載する
・このコロンイコールの書き方が、Goでよく使われる変数の宣言方法
・この記述は関数外では使用できない
変数名のルール
package main
import ("fmt")
func main(){
num := 1
num01 := 2
num_01 := 3
fmt.Println(num)
fmt.Println(num01)
fmt.Println(num_01)
}
・変数名に使える文字には、ルールがある
・変数名には、アルファベット、数字、アンダースコア( _ )が使える
・変数名は、数字から始めることが出来ない
・アンダースコア以外に記号を使うことができない
・大文字と小文字は区別される
・予約語は変数名にすることができない
・予約語とは、「return」「import」「for 」「package」など、プログラミング言語ですでに役割が決まっている単語のこと
1
2
3
データ型
データ型とは
・データ型とは、変数に入れるデータの種類のこと
・Goでは、変数にデータを入れるときに、データ型を指定する必要がある
・このようなプログラミング言語のことを静的型付け言語という
・静的型付け言語には、Go、Java、Kotlin、C言語などがある
・Goのデータ型は数値型、文字列型、ブール型がある
・一方、変数にデータを入れるときに、データ型を指定する必要がなく、自動的にデータ型を判断してくれる言語がある
・このような言語のことを動的型付け言語という
・動的型付け言語には、Ruby、Python、JavaScript、PHPなどがある
Goの数値型
・数値型には、整数型と小数点型がある
・整数型には「Int8」「Int16」「Int32」「Int64」がある
・「Int8」が扱える桁数が小さく、「Int64」が扱える桁数が一番大きい
・後ろの数字を省略してIntとすることもできる
・これは、実装するOSやCPUに依存した整数型
・通常はこのInt型で問題ない
・小数点型には、「float32」「float64」
・「float32」より「float64」の方が、小数点以下の扱える桁数が大きい
・通常は、「float64」で問題ない
package main
import (
"fmt"
)
func main(){
num01 := 1
var num02 int = 1234567890
num03 := 1.234
var num04 float64 = 1.23456789
fmt.Println(num01)
fmt.Println(num02)
fmt.Println(num03)
fmt.Println(num04)
}
1
1234567890
1.234
1.23456789
package main
import (
"fmt"
"reflect"
)
func main() {
num01 := 123
var num02 int = 1234567890
num03 := 1.23
var num04 float64 = 1.23456789
fmt.Println(reflect.TypeOf(num01))
fmt.Println(reflect.TypeOf(num02))
fmt.Println(reflect.TypeOf(num03))
fmt.Println(reflect.TypeOf(num04))
}
・Goのデータ型は、「reflect(リフレクト)」のパッケージの「TypeOf(タイプオフ)」を使用して確認する事ができる
・importに「reflect」を追加する
int
int
float64
float64
Goの文字列型
・文字列型は「string型」ともいう
・文字列はダブルクォーテーションでくくる
package main
import (
"fmt"
"reflect"
)
func main(){
var string_a string = "Hello,World!"
string_b := "Hello,World!"
fmt.Println(string_a)
fmt.Println(reflect.TypeOf(string_a))
fmt.Println(string_b)
fmt.Println(reflect.TypeOf(string_b))
}
Hello,World!
string
Hello,World!
string
Goのブール型
・ブール型は、Boolean型(ブーリアン型)ともいう
・ブール型は、TrueまたFalseの2つのうち、どちらか1つを持つ型のこと
package main
import (
"fmt"
"reflect"
)
func main(){
a := 10
b := 1
var num_bool bool = a > b
fmt.Println(num_bool)
fmt.Println(reflect.TypeOf(num_bool))
}
true
bool
package main
import (
"fmt"
"reflect"
)
func main(){
a := 10
b := 1
num_bool := a < b
fmt.Println(num_bool)
fmt.Println(reflect.TypeOf(num_bool))
}
false
bool
配列
配列とは
・配列とは、複数のデータを格納することができるデータ型
・変数は「箱」と説明なのに対して、配列は複数のデータを入れることができる「ロッカー」のイメージ
・1列の配列のことを1次元配列といい、2列以上ある配列は多次元配列という
・配列の1つ1つの箱のことを要素といい、箱の数を要素数という
・配列のそれぞれの要素には、インデックス(添字)という場所の情報が割り当てられている
配列の宣言
変数 := [要素数]データ型{データ1,データ2,…}
package main
import "fmt"
func main() {
a := [3] string {"sato", "suzuki", "takahashi" }
fmt.Println(a[0])
fmt.Println(a[1])
fmt.Println(a[2])
}
sato
suzuki
takahashi
配列の要素の変更方法
package main
import "fmt"
func main() {
a := [3] string {"sato", "suzuki", "takahashi" }
a[1] = "tanaka"
fmt.Println(a[0])
fmt.Println(a[1])
fmt.Println(a[2])
}
sato
tanaka
takahashi
要素数を省略した記述方法
配列変数 := […]データ型{データ1,データ2,….}
package main
import "fmt"
func main() {
a := [...] string {"sato", "suzuki", "takahashi" }
a[1] = "tanaka"
fmt.Println(a[0])
fmt.Println(a[1])
fmt.Println(a[2])
}
sato
tanaka
takahashi
多次元配列
package main
import "fmt"
func main() {
a := [2] [2] string{{"sato", "suzuki"}, {"takahashi", "tanaka"}}
fmt.Println(a[0][0])
fmt.Println(a[0][1])
fmt.Println(a[1][0])
fmt.Println(a[1][1])
}
sato
suzuki
takahashi
tanaka
演算子
演算子とは
・足し算、引き算などの四則演算や2つの値の大小を比較するときに使う記号のこと
算術演算子
・算術演算子とは、足し算、引き算、掛け算、割り算などをするための演算子のこと
package main
import "fmt"
func main(){
x := 10
y := 2
fmt.Println(x + y)
fmt.Println(x - y)
fmt.Println(x * y)
fmt.Println(x / y)
fmt.Println(x % y)
}
12
8
20
5
0
関係演算子
・2つの値の関係が正しいか正しくないか判断させる演算子のこと
package main
import "fmt"
func main(){
x := 10
y := 2
fmt.Println(x > y)
}
true
package main
import "fmt"
func main(){
x := 10
y := 2
fmt.Println(x < y)
}
false
・ 以上、以下の場合は「>=」「<=」を使用する
package main
import "fmt"
func main(){
x := 10
y := 2
fmt.Println(x == y)
fmt.Println(x != y)
}
false
true
論理演算子
・複数の条件を判断させる演算子のこと
・日本語でいうと「かつ」とか「または」のこと
・英語でいうとandとorのこと
・and条件は&&が2つ、or条件は縦線の||(パイプライン)が2つ
package main
import "fmt"
func main(){
x := 8
y := 3
fmt.Println(x >= 5 && x <= 10)
fmt.Println(y >= 5 && y <= 10)
}
true
false
package main
import "fmt"
func main(){
x := 8
y := 3
fmt.Println(x == 3 || y == 3)
fmt.Println(x == 1 || y == 1)
}
true
false
代入演算子
・今まで変数に代入するときに使っていた「=」は代入演算子という
・代入する時に、足し算や引き算を同時にすることができる
・足し算、引き算などと組み合わせて代入する演算子のことを複合代入演算子という
package main
import "fmt"
func main(){
// 代入演算子
x := 8
y := 12
z := 20
// 複合代入演算子
x += 10
z += y
fmt.Println(x)
fmt.Println(z)
}
18
32
インクリメントとデクリメント
・インクリメントは値を「1」増やす演算子
・インクリメントは「変数名++」と書く
・デクリメントは、値を「1」減らす演算子
・デクリメントは「変数名--」と書く
package main
import "fmt"
func main(){
x := 8
y := 8
x ++
y --
fmt.Println(x)
fmt.Println(y)
}
9
7
条件分岐
分岐処理とは
・条件分岐とは、条件に合致する場合は「処理A」、そうじゃないときは「処理B」を実行するようなことができる
if文
if 条件 {
条件を満たしたときの処理
}
・波括弧の中に条件を満たしたときの処理を記述する
・この部分はインデントを空ける
package main
import "fmt"
func main(){
age := 22
if age >= 20 {
fmt.Println("adult")
}
}
adult
package main
import "fmt"
func main(){
age := 18
if age >= 20 {
fmt.Println("adult")
}
}
//何も表示されない
if ~ else文
if 条件A {
条件Aを満たしたときの処理
} else {
条件を満たさないときの処理
}
package main
import "fmt"
func main() {
age := 18
if age >= 20 {
fmt.Println("adult")
} else {
fmt.Println("child")
}
}
child
###if ~ else if ~ else文
if 条件A {
条件Aを満たしたときの処理
} else if 条件B {
条件Bを満たしたときの処理
} else {
条件を満たさないときの処理
}
package main
import "fmt"
func main() {
age := 0
if age >= 20 {
fmt.Println("adult")
} else if age == 0 {
fmt.Println("baby")
} else {
fmt.Println("child")
}
}
baby
簡易文付きif文
・if文の中に、変数を宣言したり、変数に代入したり、四則演算の計算など簡易的な文を記述することができる
if 簡易文 ; 条件A {
条件Aを満たしたときの処理
} else if 条件B {
条件Bを満たさないときの処理
} else {
条件を満たさないときの処理
}
package main
import "fmt"
func main() {
if age := 0 ; age >= 20 {
fmt.Println("adult")
} else if age == 0 {
fmt.Println("baby")
} else {
fmt.Println("child")
}
}
baby
package main
import "fmt"
func main(){
x := 10
y := 12
if age := x+y ; age >= 20 {
fmt.Println("adult")
} else if age == 0 {
fmt.Println("baby")
} else {
fmt.Println("child")
}
}
adult
・簡易文は、if文の中でなければ使うことができない
繰り返し
繰り返しとは
・プログラムの基本的な動きは「順次」「分岐」「繰り返し」の3つ
・繰り返しとは、決まった回数や条件を満たしてれば、同じ処理を実行するプログラム構造のこと
・Go言語の繰り返し処理はfor文だけで、while文はない
for文
for スタート値; 継続条件; 増減式{
繰り返し中に実行する処理
}
package main
import "fmt"
func main(){
for i := 0; i <= 4; i ++ {
fmt.Println(i);
}
}
0
1
2
3
4
break
・break文は、ある条件にあてはまったとき、繰り返し処理を終了させることができる
package main
import "fmt"
func main(){
for i := 0; i <= 4; i ++ {
if i == 3 {
break;
}
fmt.Println(i);
}
}
0
1
2
continue
・continue文は、繰り返し処理をしているときに、ある条件にあてはまったときにその処理をスキップさせることができる
package main
import "fmt"
func main(){
for i := 0; i <= 4; i ++ {
if i == 3 {
continue;
}
fmt.Println(i);
}
}
0
1
2
4
for文のネスト
・for文の中にfor文を入れることもできる
・for文の中にfor文が入っている構造のことをfor文のネストという
package main
import "fmt"
func main(){
for i := 0; i <= 2; i ++ {
for j := 0; j <= 2; j ++ {
fmt.Println(i, "-", j);
}
}
}
0 - 0
0 - 1
0 - 2
1 - 0
1 - 1
1 - 2
2 - 0
2 - 1
2 - 2
配列とfor文
package main
import "fmt"
func main(){
arr := [...]int{2,4,6,8,10}
for i := 0; i < len(arr); i++ {
fmt.Println(arr[i])
}
}
2
4
6
8
10
package main
import "fmt"
func main() {
arr := [...]int{2, 4, 6, 8, 10}
sum := 0
for i := 0; i <= 4; i++ {
sum += arr[i]
}
fmt.Println(sum)
}
30
2つめのfor文の書き方
・スタート値、継続条件、増減式がなくてもfor文を書くことができる
package main
import "fmt"
func main() {
i := 0
for {
fmt.Println(i)
}
}
0
0
0
0
0
・
・
・
無限に0が表示される
package main
import "fmt"
func main() {
i := 0
for i <= 4 {
fmt.Println(i)
i++
}
}
0
1
2
3
4
3つめのfor文の書き方
・条件を満たしたら、breakするように記述できる
package main
import "fmt"
func main() {
i := 0
for {
fmt.Println(i)
if i == 4 {
break
}
i++
}
}
0
1
2
3
4
関数
関数の定義方法
func 関数名( ) {
実行する処理
}
package main
import "fmt"
func sayHello() {
fmt.Println("Hello World!")
}
func main() {
sayHello()
}
Hello World!
package main
import "fmt"
func sayHello() {
fmt.Println("Hello World!")
}
func main() {
sayHello()
sayHello()
sayHello()
}
Hello World!
Hello World!
Hello World!
package main
import "fmt"
func sayHello(greeting string) {
fmt.Println(greeting)
}
func main() {
sayHello("Good morning")
}
Good morning
package main
import "fmt"
func sayHello(greeting string) {
fmt.Println(greeting)
}
func main() {
sayHello("Good evening")
}
Good evening
package main
import "fmt"
func cal(x int) {
fmt.Println(x * 3)
}
func main() {
cal(6)
}
18
package main
import "fmt"
func cal(x int, y int) {
fmt.Println(x / y)
}
func main() {
cal(6, 3)
}
2
package main
import "fmt"
func cal(x, y int) {
fmt.Println(x / y)
}
func main() {
cal(6, 3)
}
・同じデータ型の場合、上記のように省略することができる
2
package main
import "fmt"
func cal(x, y int) int {
return (x / y)
}
func main() {
result := cal(6, 3)
fmt.Println(result)
}
2
package main
import "fmt"
func cal(x, y int) (int, int) {
return (x / y), (x * y)
}
func main() {
result01, result02 := cal(6, 3)
fmt.Println(result01, result02)
}
2 18
package main
import "fmt"
func cal(x, y int) (int, int) {
a := x / y
b := x * y
return a, b
}
func main() {
result01, result02 := cal(10, 5)
fmt.Println(result01, result02)
}
2 50
package main
import "fmt"
func cal(x, y int) (a int,b int) {
a = x / y
b = x * y
return a, b
}
func main() {
result01, result02 := cal(10, 5)
fmt.Println(result01, result02)
}
・関数の戻り値は、cal関数の波括弧の外で宣言することができる
・そのため、宣言と同時に代入する「:=」ではなく、単純に「=」だけでよくなる
2 50
package main
import "fmt"
func cal(x, y int) (a int,b int) {
a = x / y
b = x * y
return
}
func main() {
result01, result02 := cal(10, 5)
fmt.Println(result01, result02)
}
・関数の戻り値は、cal関数の波括弧の外で宣言しているため、returnのあとの変数の記述も省略できる
2 50
関数式
・関数を変数に代入することができる
package main
import "fmt"
func main() {
hello := func (greeting string) {
fmt.Println(greeting)
}
hello("Good morning")
}
・helloという変数に関数を代入できる
・funcのあとの関数名は省略できる
・その後の記述は、通常の関数の定義方法と同じ
・実行方法は、関数のあとに丸括弧
・丸括弧の中に引数を記述
・funcのあとに関数名がない関数を無名関数という
Good morning
package main
import "fmt"
func main() {
func (greeting string) {
fmt.Println(greeting)
}("Good morning")
}
・無名関数は、そのまま引数を渡して実行することができる
・無名関数のあとに、すぐに丸括弧で引数を与える
Good morning
init()
・特殊な関数で、一番はじめ(mainより先)に実行される関数
package main
import "fmt"
func init() {
fmt.Println("init()はmain()より先に実行する")
}
func main() {
fmt.Println("Hello world!")
}
init()はmain()より先に実行する
Hello world!
ポインタ
Go言語のポインタとは
・変数が存在するメモリ上の場所を「アドレス」といい、そのアドレスを格納可能な変数を「ポインタ」と呼ぶ
・例えば、「int型」変数のアドレスを格納できるポインタの型は、「* int」型というように、型の前に「* 」を付ける
・変数からアドレスを取得するときは「&(アドレス演算子)」を使う
・反対にアドレスが指し示す変数にアクセスするときは「*(間接参照演算子)」を使う
package main
import "fmt"
func main() {
// int型のポインタ変数を宣言
var ptr *int
// int型の変数を宣言
var i int = 12345
// アドレス演算子を使い、iのアドレスをptrに代入
ptr = &i
//出力
fmt.Println("iのアドレス", &i)
fmt.Println("ptrの値(変数iのアドレス)", &i)
fmt.Println("iの値", i)
fmt.Println("ポインタ経由のi値", *ptr)
// ポインタ経由でiの値を変更
*ptr = 999
//出力
fmt.Println("ポインタ経由で変更したiの値", i)
}
iのアドレス 0xc000018050
ptrの値(変数iのアドレス) 0xc000018050
iの値 12345
ポインタ経由のi値 12345
ポインタ経由で変更したiの値 999
ポインタ渡しと値渡し
・ある変数を関数に渡すと実際の値のコピーが渡されるので、呼び出された関数内で値を変更しても関数の呼び出し元には一切、影響しない
・一方で、値のポインタを関数に渡した時は、値の実体(ポインタの指し示す値)は関数の呼び出し元も同じであるため、呼び出した関数内で呼び出し元の値を変更することができる
・このように、ポインタを使って値を渡すことを一般的に「ポインタ渡し」と呼ぶ
・反対に値のコピーを受け渡すことを「値渡し」と呼ぶ
package main
import "fmt"
func main() {
// int型の変数を2つ宣言
a, b := 1, 1
// 関数に変数を渡す
// aは値をそのまま渡す。値渡し。
// bはアドレス演算子を使ってポインタとして渡す。ポインタ渡し。
double(a, &b)
//出力
fmt.Println("値渡し", a)
fmt.Println("ポインタ渡し", b)
}
// この関数のパラメータxは値のコピーを受け取り、
// yはポインタ(正確にはポインタのコピー)を受け取る
func double(x int, y *int) {
// 変数の値を変更
x = x * 2
//間接参照演算子を使用し、ポインタyが指し示す変数の値を変更
*y = *y * 2
}
値渡し 1
ポインタ渡し 2
構造体
構造体とは
・異なるデータ型の変数を1つにまとめたもの
・構造体を作ることを「構造体を定義する」という
フィールド
・構造体の中に定義した変数のことをフィールドという
・構造体にフィールドを追加することを「フィールドを定義する」という
・フィールドは、変数と同じように、数値や文字列を代入したり、参照したりすることができる
構造体の定義方法
package main
import "fmt"
type Student struct {
}
func main() {
}
フィールドを定義
package main
import "fmt"
type Student struct {
name string
math float64
english float64
}
func main() {
}
package main
import "fmt"
type Student struct {
name string
math,english float64
}
func main() {
}
・上記のようにフィールドは変数と同じように、カンマで区切って一括して定義することができる
構造体の使い方
package main
import "fmt"
type Student struct {
name string
math,english float64
}
func main() {
var s Student
s.name = "sato"
s.math = 80
s.english = 70
fmt.Println(s)
}
・構造体も変数と同じで、予約語のvarを書いて、次に構造体を代入する変数を記載する
・上記の場合、変数名は「s」で、変数のあとに構造体名を記載する
・このように構造体を使えるようにすることを「構造体の初期化する」という
{sato 80 70}
package main
import "fmt"
type Student struct {
name string
math,english float64
}
func main() {
s := Student{"sato", 80, 70}
fmt.Println(s)
}
・上記の記述はフィールドの上からの順番通りに値を代入しなければエラーになる
{sato 80 70}
package main
import "fmt"
type Student struct {
name string
math,english float64
}
func main() {
s := Student{english: 70, math: 80, name: "sato"}
fmt.Println(s)
}
・順番を入れ替えたい、一部のフィールドにのみ値を代入するには、フィールド名を指定して代入する方法を使えばよい
{sato 80 70}
メソッド
メソッドとは
・構造体などの特定の型に関連づけられた関数のこと
メソッドの定義方法
package main
import "fmt"
type Student struct {
name string
math, english float64
}
func (s Student) avg() {
fmt.Println(s.name, (s.math+s.english)/2)
}
func main() {
a001 := Student{"sato", 80, 70}
a001.avg()
}
・構造体Studentを定義する
・avgメソッドを定義する
・funcとメソッドの間に丸括弧。丸括弧の中に、変数名、半角スペース、関連づける構造体名と記述することで、メソッドの中で、フィールドの値を使うなどができるようになる(この部分をレシーバと呼ぶ)
・a001に構造体を初期化をして代入する
・メソッドの使い方は、構造体を代入した変数(a001)、ドット、メソッド名
sato 75
package main
import "fmt"
type Student struct {
name string
}
func (s Student) avg(math, english float64) {
fmt.Println((math + english) / 2)
}
func main() {
a001 := Student{"sato"}
a001.avg(80, 70)
}
・avgのあとの丸括弧に、渡す引数を記述する
75
package main
import "fmt"
type Student struct {
name string
}
func (s Student) avg(math, english float64) (avgResult float64) {
avgResult = (math + english) / 2
return
}
func main() {
a001 := Student{"sato"}
fmt.Println(a001.avg(80, 70))
}
・avgのあとの丸括弧に、渡す引数を記述する
75
終わりに
貴重なお時間を使って最後まで読んで下さり、誠にありがとうございます!!
enjoy golang!!
この記事は以下の情報を参考にしてします。
https://kino-code.com/category/super-introductory-course-golang/