Go

Go言語の基本文法1(変数, 定数, ポインタ, 演算子)

こんにちは、イサムです!

本記事では、Go言語の基本文法についてまとめます。

対象読者
  • Go言語の基本文法について知りたい!
この記事でやること
  • Go言語の基本文法についてのまとめ

基礎知識

キーワード

Go言語の予約語一覧です。
関数名や変数名などに使用することができません。

breakdefaultfuncinterfaceselect
casedefergomapstruct
chanelsegotopackageswitch
constfallthroughifrangetype
continueforimportreturnvar

行末

基本的に改行またはセミコロンを行末として扱います。

コメント

// 行コメント

/*
ブロックコメント
*/

パッケージ

Go言語のプログラムは、パッケージの組み合わせによって成り立っています。

package main

import "fmt"

func main() {
  fmt.Println("Hello, World")
}

import

importキーワードを使用することで、他のパッケージの機能をインポートし、使用することができるようになります。

importの方法

  1. 別々にインポート
  2. まとめてインポート
// ①別々にインポート
import "fmt"
import "math"

// ②まとめてインポート
import (
  "fmt"
  "math"
)

パッケージに別名を付与する方法

importしたパッケージに別名を付与することができます。

// fmtパッケージに「f」という別名を付与
import f "fmt"

func main() {
  f.Println("Hello")
}

パッケージ名を使用しない方法

importしたパッケージ名を使用せず、パッケージの関数や変数などを使用することができます。

// fmtパッケージに「.」という別名を付与
import ."fmt"

func main() {
  Println("Hello")
}

export

exportキーワードは存在せず、外部パッケージから参照できるようにするためには、関数や変数などの識別子の頭文字を大文字にする必要があります。
識別子が大文字の場合、外部参照可のpublic、小文字の場合、外部参照不可のprivateとなります。

例えば、以下のmathパッケージのPiは、外部から参照できるようにしたデータになります。

package main

import (
  "fmt"
  "math"
)

func main() {
   fmt.Println(math.Pi) // 3.141592653589793
}

変数

変数に代入した値は、コンピュータのメモリ上に一時的に保存されるため、コンピュータの停止やプログラムの実行が終了すると消えます。
そのため、データを残したい場合は、外部記憶装置に保存する必要があります。
また、値を識別するのに変数名を使用します。

変数の宣言方法

基本的な変数の宣言方法

  1. var 変数名 型
  2. var 変数名 型 = 値
  3. var 変数名 = 値
  4. 変数名 := 値

宣言したデータ型とは異なる値を入れることはできません。
④のvarを省略した宣言方法は、関数内でしか使用できません。

// ①変数宣言のみ
var country string

// ②変数宣言と値代入での初期化
var name string = "Osamu"

// ③(型省略)変数宣言と値代入での初期化(型推論によりint型になる)
var age = 20

// ④varを省略した変数宣言と値代入での初期化(関数内でしか使用できない)
func main() {
  bloodType: = "A"
}

同じデータ型の変数を同時に複数宣言する方法

カンマ区切りで宣言します。

var name, bloodType  string = "Osamu", "A"

異なるデータ型の変数を同時に複数宣言する方法

()で括ってひとまとめに宣言します。

var (
  name string = "Osamu"
  age int = 20
  bloodType string =  "A"
)

データがどういう種類の値かを表すものです。

組み込み型(基礎の型)

Go言語が用意しているデータ型一覧になります。
変数宣言時、初期値を指定しない場合、ゼロ値が設定されます。

サイズ
(byte)
符号ゼロ値説明値の範囲
int4/
8
0符号付き整数int32 または int64
int810-128 ~ 127
int1620-32768 ~ 32767
int3240-2147483648 ~ 2147483647
int6480-9223372036854775808 ~ 9223372036854775807
uint4/
8
0符号無し整数uint32 または uint64
uint8100 ~ 255
uint1620
0 ~ 65535
uint32400 ~ 4294967295
uint64800 ~ 18446744073709551615
float3240単精度浮動小数有効桁数6桁の実数
float6480倍精度浮動小数有効桁数14桁の実数
complex6480+0i複素数float32の実数部と虚数部を持つ複素数
complex128160+0ifloat64の実数部と虚数部を持つ複素数
string16“”文字列型
bool1false論理値型true / false
error16nilエラー型
uintptr80アドレスを格納できる整数
rune40int32のエイリアス
byte10uint8のエイリアス0 ~ 255

コンポジット型

複数の型が集まって一つのデータ型になっている型になります。

ゼロ値説明
配列全要素が型のゼロ値同じ型のデータを集めたデータ型(固定長)
スライスnil配列の一部を切り出したデータ型(可変長)
マップnilキーと値をマッピングさせたデータ型
構造体全データがデータ型のゼロ値型の異なるデータ型を集めたデータ型

type

type 型名 基礎の型で独自の型(ユーザー型)を作成できます。
構造体やインターフェースを定義するときにも使用します。

type MyInt int

func main() {
  var mi MyInt = 1
  println(mi)		
}

型リテラル

型リテラルとは、他の型を使って構成される型のことです。
型リテラルの種類としては、以下のようなものです。

  • 配列型
  • スライス型
  • マップ型
  • 構造体型
  • ポインタ型
  • 関数型
  • チャネル型

型キャスト

変数v、型Tがあった場合、T(v)は、ある型の変数vから別の型Tに変換することができます。

  1. 独自の型を基礎の型に変換
  2. 整数型を浮動小数点型に変換
  3. 浮動小数点型を整数型に変換
  4. string型をbyte型に変換
  5. byte型をstring型に変換
  6. int型をstring型に変換(strconvパッケージのAtoi()関数を使用)
  7. string型をint型に変換(strconvパッケージのItoa()関数を使用)
package main 

import (
  "fmt"
  "strconv"
)

// 独自の型を定義
type MyInt int

func main() {

  // ①独自の型を基礎の型に変換
  var mi MyInt = 1
  fmt.Printf("%T\n", int(mi)) // int

  // ②整数型を浮動小数点型に変換
  var i int = 10
  fmt.Printf("%T\n", float64(i)) // float64

  // ③浮動小数点型を整数型に変換
  var f float64 = 12.5
  fmt.Printf("%T\n", int(f)) // int

  //④string型をbyte型に変換
  var str string = "hoge"
  fmt.Printf("%T\n", []byte(str)) // uint8([]byte)

  // ⑤byte型をstring型に変換
  var byts []byte= []byte(str)
  fmt.Printf("%T\n", string(byts)) // string

  hoge := 100
  fmt.Printf("%T\n", hoge) // int

  boo := "200"
  fmt.Printf("%T\n", boo) // string

  // ⑥int型をstring型に変換
  s := strconv.Itoa(hoge)
  fmt.Printf("%T\n", s) // string

  // ⑦string型をint型に変換
  i := strconv.Atoi(boo)
  fmt.Printf("%T\n", i) // int
}

定数

コンパイル時から値が変わらないデータのことで、再代入ができません。
型を明示しない場合、デフォルト型になります。

種類デフォルトの型
整数10int
浮動小数点数12.5float64
複素数1+2icomplex128
文字列“abc”string
真偽値falsebool

定数の宣言方法

基本的な定数の宣言方法

  1. const 変数名 型 = 値
  2. const 変数名 = 値


宣言したデータ型とは異なる値を入れることはできません。

// ①定数宣言と値代入での初期化
const name string = "Osamu"

// ②(型省略)定数宣言と値代入での初期化(型推論によりint型になる)
const age = 20

同じデータ型の定数を同時に複数宣言する方法

変数と同様にカンマ区切りで宣言します。

const name, bloodType  string = "Osamu", "A"

異なるデータ型の定数を同時に複数宣言する方法

変数と同様に()で括ってひとまとめに宣言します。

const (
  name string = "Osamu"
  age int = 20
  bloodType string =  "A"
)

リテラル

リテラルとは、数値や文字列を直接記述した定数のことになります。

// 数値のリテラル
a := 100

// 文字列のリテラル
b := "Hello"

ポインタ

ポインタは変数に代入されている値ではなく、変数のために確保されているメモリアドレスを格納する変数のことです。

ポインタの定義方法

  1. var 変数名 *型
  2. var 変数名 = new(型)
  3. 変数名 := &変数

変数定義時、型の前に「*」をつけることで、ポインタ型になり、ゼロ値は、nilです。

// ①ポインタの宣言とnilでの初期化
var p1 *int

// ②ポインタの宣言とメモリの確保
var p2 = new(int)

// ③ポインタの宣言と変数の代入
a := 10
p3 := &a


*intとint型は別物になりますので、int型の値の代入はできません。
コンパイルエラーになります。

var a *int = 1

ポインタの扱い方

変数からポインタを取得

変数からポインタを取得するためには、「&」を使います。

a := 1
var b *int

b = &a
println(b) // 0xc000068f58

ポインタ変数から値を取得

ポインタ変数から値を取得するためには、「*」を使います。

a := 1
var b *int

b = &a
println(*b) // 1

ポインタのイメージ

// aのメモリに1を格納
a := 1

// bのメモリにaのアドレスを格納
var b *int = &a

// aのアドレスが格納されたbのデータにアクセス
println(*b) // 1

値渡しと参照渡し

値渡し

定義した変数aを別の変数bへ代入した際、変数bに定義した変数aの値がコピーされるだけなので、変数bの値を変更しても、変数aの値は変更されません。

a := 1

// aを代入(コピー)
b := a

// 代入先の値を変更
b = 2

println(a, b) // 1, 2

参照渡し

定義した変数aのポインタ(メモリアドレス)を別の変数bへ代入した際、変数bが変数aのポインタ(メモリアドレス)を参照することになるので、変数bの値を変更した場合、変数aの値までも変更されます。

a := 1

// aのポインタを代入
var b *int = &a

// aのポインタを参照するbの値を変更することで、aの値も変更される
*b = 2

println(a, *b) // 2, 2

ポインタが使用される場面

  • 変数を定義した関数とは別の関数で変数の値を更新するときは、関数にポインタ型を引数で渡して変更
  • 構造体の値を更新するとき、メソッドでポインタレシーバを定義またはポインタ型を関数の引数に渡して変更

演算子

算術演算子

文字列結合、数値の計算に使用します。

演算子説明
+文字列結合
加算
“a”+”b”
1+1
減算2-1
*乗算2*2
/除算3/1
%除算の余り3/2

代入演算子

変数に値を代入するときに使用します。

演算子説明
=変数への代入a = 1
:=変数の初期化と代入a := 1
+=
-=
*=
/=
演算と代入a += 1(a += a + b)
a -= 1(a -= a – b)
a *= 1(a *= a * b)
a /= 1(a /= a / b)
++
インクリメント
ディクリメント
i++(i += 1)
i–(i -= 1)

論理演算子

bool値の演算で使用します。

演算子説明
&&またはa || b
||かつa && b
!否定!a

比較演算子

値を比較するときに使用します。

演算子説明
==等しいかどうかa == b
!=等しくないかa != b
<aはbより小さいa < b
<=aはb以下a <= b
>aはbより大きいa > b
>=aはb以上a >= b

間接演算子とアドレス演算子

ポインタを扱うときに使用します。

演算子説明
<-ポインタから値を取得*a
&ポインタを取得&a

チャネル演算子

チャネルを使用するときに使用します。

演算子説明
<-チャネルからの受信
チャネルへの送信
<- ch
ch <- “Hello”

まとめ

この記事では、Go言語の基本文法をまとめました。

少しGo言語をいじってみたいと思ったら、ブラウザ上で実行できる公式チュートリアルでコードを実際に書いてみると雰囲気がつかめるかもしれません。
今後、さらにGo言語のことについて記事にしていきたいと思います。

もし「記事の内容が間違えている!」等ありましたら、Twitterまたはお問い合わせフォームからご連絡いただければと思います。

最後までご覧いただきありがとうございました。

参考サイト

【Go言語】byte型ってなんだ

Go言語: ポインターとそれに関する型

【Go】runeについて理解する(サンプルあり)

The Go Programming Language Specification

Tour of Go