Closed10
golang再入門
初めに
2022年にGo言語で業務をしていたのですが、暫く離れてしまってブランクがあるので再入門した際のメモです。
いい感じにまとまったら後で記事にするかも。
他のユーザーの投稿を許可しておくので、もしも今はこれがデファクトだよ〜みたいなご指摘があればコメント頂けますと幸いです。
今回のゴール
- Go言語を使用してWebアプリケーションの開発ができるようになる
- 開発環境(特にパッケージ管理まわり)を復習する
- 基本構文からやり直す
具体的にやること
- 開発環境・パッケージ管理について学ぶ
- 基本構文を
A Tour of Go
で学ぶ - Webアプリケーション開発に必要なパッケージを調査し、実際にTODOアプリを構築する
開発環境構築
サクッと作成したいのでDockerを使用して開発環境を構築します。
golangのバージョンは現時点での最新 1.20.3
を使用
作業リポジトリ
モジュール管理(パッケージ管理)
Goのパッケージ管理は Go Module
を使うのが現時点でのデファクトらしいので
それについて使用方法を記載します。
公式
基本構文の復習
変数
A Tour of Go
から拝借
基本データ型
bool
string
int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr
byte // alias for uint8
rune // alias for int32
// represents a Unicode code point
float32 float64
complex64 complex128
変数定義
// varで明示的に宣言する
var i int
i = 1
// 暗黙的に宣言する(関数の中でのみ宣言可能)
i := 1
// まとめて
var (
a int
b int
c string
)
定数
const
で定義する。省略形は存在しない
const TEST = "TEST"
関数
func
で宣言する
func hoge() {
fmt.Println("hoge!!")
}
// 引数
func add(x int, y int) int {
return x + y
}
// 引数(省略形)
func add(x, y int) int {
return x + y
}
// 複数return
func swap(x, y string) (string, string) {
return y, x
}
// 名前付きreturn
func named(a, b string) (x, y string) {
x = "x: " + a
y = "y: " + b
return
}
基本構文の復習 Part 2
For
for i := 0; i < 10; i++ {
fmt.Println(i)
}
// whileみたいな書き方
for ; sum < 1000; {
sum += sum
}
// これでもOK
for sum < 1000 {
sum += sum
}
// 条件を設定しないと無限ループ(内部でbreakすれば抜けられる)
for {
}
If
if a < 100 {
fmt.Println("a is less than 100")
}
// その場で変数宣言も可能
if i := 100; i < 100 {
fmt.Println("i is less than 100")
} else if i == 100 {
fmt.Println("i equal 100")
} else {
fmt.Println("i is more than 100")
}
Switch
break
を設定しなくても一致した時点でbreakする
str := "ccc"
switch str {
case "aaa":
fmt.Println("str is aaa")
case "bbb":
fmt.Println("str is bbb")
case "ccc":
fmt.Println("str is ccc")
default:
fmt.Println("undefined pattern")
}
Defer
関数が戻るまで遅延させる
func main() {
// 最後のhelloが出力されてから実行される
defer fmt.Println("world")
fmt.Println("hello")
}
deferは LIFO(last in first out)
なので、最後に実行されたものから順番に出力される
func main() {
// 9 ,8, 7, 6...と出力される
for i := 0; i < 10; i++ {
defer fmt.Println(i)
}
}
ポインタ
ポインタは値のメモリアドレスを指します。
概念はC言語と同様でメモリアドレスの位置を示す
// 宣言
var p *int
// 以下の場合、pはiのアドレスを示す
i := 42
p = &i
// ポインタを通して元の変数の値を取り出す
fmt.Println(*p)
// 値に対して再代入も可能(iの内容が書き変わる)
*p = 1
fmt.Println(i) // 1になる
実際にどんな時にポインタを使うのか?
個人的な理解だとポインタを関数に渡し、参照元の変数を書き換えたい時に使う(参照渡し)
構造体
type Vertex struct {
X, Y float64
}
// クラスみたいにメソッドを生やすことができる
func (v Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
// ポインタレシーバで宣言
// こうすることでプロパティの内容を書き換えできる
func (v *Vertex) Scale(f float64) {
v.X = v.X * f
v.Y = v.Y * f
}
func main() {
v := Vertex{3, 4}
fmt.Println(v.X)
fmt.Println(v.Abs())
v.Scale(10)
fmt.Println(v.X, v.Y)
}
配列
// 宣言
var a [2]string
// 代入
a[0] = "a"
a[1] = "b"
// 一括代入
numbers := [3]int{1, 2, 3}
// スライス
var s []int = numbers[1:2] // 2, 3だけ取れる
// rangeを利用することでforeachみたいなことができる
for i, n := range numbers {
fmt.Println(i, n)
}
TODO
ゴルーチンは必要になった時に復習する
このスクラップは2024/01/23にクローズされました