Go言語を使う上で重要だと思うところをピックアップしてまとめました。
これを読めばGo未経験者の方でも、Goの基本的な内容は理解できると思います。
Goとは
静的型付け言語。つまり、型やメモリの管理がとても厳しい。
また、オブジェクト指向ではなく、オブジェクト指向におけるクラスとオブジェクトは、構造体とインタフェースで実装可能。
他にも、Goの主な特徴としては、
・並行処理が簡単
・仮想マシンを使わず直接機械語へとコンパイルするので、処理速度が速くメモリリソースの使用量も減る。
などが挙げられる。
型
一部の型をピックアップして紹介する。
配列型
要素数まで型名に含める厳密なデータ型である。それゆえ、配列の拡張は不可能。
可変長配列のような柔軟なデータ型は、GoではSliceが相当する。
a := [3]int{1,2,3}
interface型
interface{}型はGoにおけるあらゆる型と互換性のある特殊な型。
それゆえ、様々な型を引数として捉えることができるので、動的に変数の型をチェックすることができる。これを型アサーションという。x.(T)のように書く。
var x interface{}
x = 1
x = "hello"
x = [3]int{1,2,3}
var y interface{} = 3
i := y.(int)
f := y.(float64)
関数
関数はfunc 関数名(引数の定義) 戻り値型 {関数本体}で書く。
func hoge(x int) int {
return x
}
hoge(1)
無名関数は、関数というものを「値」として表現できる。
そうすることで、ある関数が関数を引数に取ることも、関数を返す関数を書くこともできる。
f := func(x, y, int) int { return x+y }
f(2,3) // == 5
参照型(スライス)
可変長配列を表現する型。
a := []int{1,2,3}
b = append(a,4)
要素数と容量
make([]int, 5, 10)
の場合、要素数は5なので、[n]によるインデックスで参照・代入できる範囲は0から4に制限される。しかし、容量としては10個分のint型を格納できる領域がある。そのため、拡張していく際、メモリ上の新たな領域を確保する必要がない。
参照型(マップ)
Rubyのハッシュに該当する。
var m map[int]string
m := make(map[int]string)
m[1] = "hoge"
参照型(チャネル)
ゴルーチンとゴルーチンの間でデータの受け渡しをするデータ構造。
<-chanは受信専用チャネル、chan<-は送信専用チャネル、chanは双方向のチャネルとして機能する。
var ch1 chan int
var ch2 <-chan int
var ch3 chan<- int
構造体(Struct)
複数の任意の型の値を1つにまとめたもの。
structで定義された構造体に、typeを使って新しい型名を設定する。
type Point struct {
X, Y int
}
var pt Point
pt.X = 10
pt2 := Point{1,2}
a := Animal{
Name: 'Cat',
Feed: Feed{
Name: 'Food',
Amount: 10
}
}
a.Name
a.Feed.Amount
メソッド
任意の型に特化した関数を定義することができる。
オブジェクト指向でいうインスタンス変数である。
メソッド定義では、func レシーバー 関数名のように書く。
type Point struct {
X, Y int
}
func (p *Point) Distance(dp *Point) float64{
}
p := &Point{X:0, Y:0}
p.Distance(&Point{X: 1, Y: 2})
また、コンストラクターは慣例的に型のコンストラクタというパターンを利用して、New[型名]と命名する。
type User struct {
Id int
Name string
}
func NewUser(id int, name string) *User {
u := new(User)
u.id = id
u.Name = name
return u
}
user := NewUser(1, 'Taro')
並行処理
go文で並行処理を実装でき、スレッドよりも小さい処理単位であるゴルーチンが並行して動作するように実装されている。
func sub(){
for {
fmt.Println("sub loop")
}
}
func main(){
go sub()
for {
fmt.Println("main loop")
}
}
GORMとは
まず、ORMとはオブジェクト指向プログラムとリレーショナルデータベースをつなぐ役割をする。
GORMとはGo言語におけるORMのこと。
実装
RDBとの接続
import (
"github.com/jinzhu/gorm"
"github.com/jinzhu/gorm/dialects/mysql"
)
func gormConnect() *gorm.DB {
DBMS := "mysql"
USER :=
// 設定を記述
return db
}
func main(){
db := gormConnect()
defer db.Close()
}
SELECT文
eventsテーブルがあると仮定。
このテーブルを元にモデルを定義する。
単一レコードのselectを実行できるように、単数形の名前で構造体を定義する必要がある。
type event struct {
Id int `gorm:"primary_key"`
UserId int
Summary string
}
func main(){
db := gormConnect()
defer db.Close()
eventEx := event{}
eventEx.Id = 12
db.FIrst(&eventExt)
}
複数レコードのselect文は
func main(){
db := gormConnect()
defer db.Close()
// 構造体のインスタンス化
eventsEx := []event{}
// 指定した条件を元に複数のレコードを引っ張ってくる
db.Find(&eventsEx, "user_id=?", 2)
}
INSERT文
func main(){
db := gormConnect()
defer db.Close()
// 構造体のインスタンス化
eventEx := event{}
// 挿入したい情報を構造体に与える
eventEx.Id = 0
// ・
db.Create(&eventEx)
}
DELETE文
func main(){
db := gormConnect()
defer db.Close()
// 構造体のインスタンス化
eventEx := event{}
// 削除したいレコードのIDを指定
eventEx.Id = 2
db.First(&eventEx)
db.Delete(&eventEx)
}
UPDATE文
更新前と更新後のレコード情報が必要。
func main(){
db := gormConnect()
defer db.Close()
// 構造体のインスタンス化
eventExBefore := event{}
eventExBefore.Id = 2
eventExAfter := eventExBefore
db.First(&eventExAfter)
eventExAfter.year = 2015
db.Model(&eventExBefore).Update(&eventExAfter)
}
マイグレーション
func main(){
db := gormConnect()
defer db.Close()
db.CreateTable(&event)
}
参考資料
https://qiita.com/HiromuMasuda0228/items/65b9a593275f769f6b69
https://qiita.com/chan-p/items/cf3e007b82cc7fce2d81