LoginSignup
0
0

More than 3 years have passed since last update.

Go言語を試す

Posted at

環境設定

  • Go言語仕様
    https://golang.org/ref/spec

  • goのインストール
    https://golang.org/

  • go getでパッケージを取れるか
    https://pkg.go.dev/
    go get xxxx

  • Goland
    有料のIDE

  • VSCode
    cmd + j でVSCodeのパネル開く
    go run xxxx.go で実行
    go build xxxx.go でバイナリファイルが残る

  • delve デバッガ
    go get github.com/go-delve/delve/cmd/dlv
    launch.jsonを作成 -> vscodeのrunタブにボタンが有る

基本

  • main.goから始まる
  • init() 関数は強制的に最初に実行される
  • 使わない変数を書くとコンパイルできない
  • 先頭は大文字でパブリック、小文字だとプライベートになる
  • fmt.Println()で出力

import

標準パッケージ一覧
https://golang.org/pkg/
パッケージはimportして使う
パッケージとはコードの集まり。ライブラリもほぼ同じ意味。クラスはない。
ディレクトリ名がpackage名となる。その中にgoファイルを配置。

app
L main.go
L package1
  L file1.go
  L file2.go
L package2

変数

var i int = 3
float64, string, bool
var を () でくくればvarを毎回先頭に付ける必要はない
初期値を代入しなかった場合デフォルト値となる。0、空文字、falseなど
fmt.Printf("%T\n", xi)

short variable declaration

xi := 1
xs := "ccc"
代入により自動で型が決まる
関数内でしか使えない

const

書き換えられない
型がない(untype)(実行するまで解釈されない)
通常はグローバルに書く
通常は先頭は大文字

数値

言語仕様
https://golang.org/ref/spec#Numeric_types

i++ 対応

文字列

インデックス指定でアスキーコード取得、stringで文字に変換
string("Hello"[0])
文字の置き換え
var s string = "Namaste"
s = strings.Replace(s, "N", "Z", -1)
strings.Contains(s, "mas")
バッククオートでヒアドキュメント ``

論理値

変わったところはない
&& || !

型変換

int float64
文字 -> 数字はpythonみたいにstringではできない
i, _ := strconv.Atoiで変換

戻り値をアンダースコア(_)で受け取れば、未使用でもコンパイルできる

配列

型部分で宣言したサイズは変更できません
var b [2]int = [2]int{30, 40}

スライス

サイズ変更できる配列
var b []int = []int{30, 40}
b = append(b, 50) で追加

var n []int 初期化しないとnilになる
n := make([]int, 0) だと中身は空だがメモリ上に存在する

map

m := map[string]int{"apple": 100, "banana": 300}
新しいキーに代入すると追加される

var m map[string]int 初期化しないとnil mapになり、追加できない

m := make(map[string]int) はnilじゃない
a, ok := m["grape"]
keyが存在しないと0を返し、2つ目の返り値にfalseが返る

バイト

b := []byte{72,73}
stringで文字列にキャストできる
c := []byte("HI")
文字列を渡すとアスキーコードに変換される

アスキーコード変換表
https://www.ascii-code.com/

関数

引数の型が同じ場合はまとめられる
返り値が複数の場合は()でくくる

func add2(x, y int) (int, int) {
    return x + y, x - y
}

名前付きの戻り値 Named Return Values

func calc(price, item int) (result int) {
  result = price * item
}

返り値として宣言した名前を変数として扱えるので、returnを書く必要なし
返り値が多くなってわかりにくい時など

Inner Function

関数内で変数に関数を代入して使う

f := func()

名前無し関数も作れる

func(x int) {
}()

クロージャー closure

関数を返す関数

func increment() func() int {

関数を戻す前に投入したパラメータを、戻した関数の処理に引き継ぐ事ができる

func circle(pi float64) func(radius float64) float64 {
    return func(radius float64) float64 {
        return pi * radius * radius
    }
}

可変長引数 Variadic Function Parameter

任意の個数の引数を受け取れる

func foo(params ...int) {

関数の中ではスライスで受け取れる

スライスを可変長引数の関数に渡すには

// スライスが展開される
foo(s...) 

コードスタイル

イコールの位置をそろえるのがgoの慣習
列挙する場合は演算子は詰めて書く

var a    = 100
var bbbb = 200
var cc   = 300

fmt.Println(1+1, 2*2)

ステートメント

if

()はなくて良い
;で一文でかける

// if / else if / else
if result == "ok" {

for

continue
break
//初期化とインクリメントを省略できる ;も省略できる
for sum < 10 { 
} 

for { } だけだと無限ループできる

range

リストやマップをかんたんに表示できる

for i, v := range list {

インデックスを使わない場合は _ で置き換える
マップのバリューのみ使わない場合は書かない
マップのキーのみ使わない場合は _ で置き換える

switch

switchの判定のみ使うのなら、;の前で取得して一文でかける
変数を書かなくても分岐に使える

switch {}

defer

前につけることで関数が終わったあとに実行する指示
close処理忘れ防止など

func defaTest() {
    defer fmt.Println("defer") // 関数が終わったら実行されます
    fmt.Println("end")   
}

deferはスタッキングされるので、複数あると最後から表示される

log

go logging package

log.Println()
log.Fatalln() // Fatalはそこでプログラムが終了する
log.SetOutput //設定

エラー

goは戻り値のerrを使って処理する(トライキャッチじゃなく)
:= はどれか一つを初期化してたらエラーにならないが一つもなければアウト

count, err := file.Read(data) 

panic、recover

deferでrecover()してpanic()が起きても正常終了させる
recoverはpanicの前に書く
基本panicをあえて書くのではなく、エラーハンドリングをするべき

ポインタ

ポインタ

var p *int = &n //intのポインタ型、アドレスを格納
p //アドレス
*p //ポインタが指す値

new make

指定の型のメモリ確保する

var p *int = new(int)

*p は0になる
スライスやマップはmakeでメモリ確保(ポインタを返さない)

struct 構造体

先頭は大文字でパブリック、小文字だとプライベートになる

type Vertex struct {
    X int
    Y int
    S string
}
v := Vertex{X: 1, Y: 2}

初期化しなければデフォルトが入る
名前を指定しなければ順番どおりはいる

アドレスを取る場合、newよりも&を先頭につける事が多い
(マップやスライスなどはmakeを使うほうが多い)

structの場合は、参照渡しでも*つけずに値にアクセスできる!!

struct

メソッド

定義済みstructに関連付けてドットで呼び出せる関数(値レシーバ)

func (v Vertex) Area() int {

structを参照渡しして、メソッド内で中身を書き換えるもの(ポインタレシーバ)

func (v *Vertex) Scale(i int) {

コンストラクタ

structをプライベートにすると他のパッケージからアクセスできないので
Newメソッドで初期化する

func New(x, y int) *Vertex {
    return &Vertex{x, y}
}

packageName.Newすることでstructを返す

embeded

structの中にstructを定義すると、クラス継承みたいな感じで拡張できる

type Vertex3D struct {
    Vertex //名前を書くだけ
    z int
}

func New(x, y, z int) *Vertex3D {
    return &Vertex3D{Vertex{x, y}, z}
}

non-struct

structではないカスタム型もメソッドをつけられる

type MyInt int
func (i MyInt) Double() int {

interface

メソッド名だけ書かれている型
structがメソッドを実装してないとエラーになる

type Human interface {
    Say()
}

使うにはstructを作るときに変数の後ろにつける

var mike Human = Person{"Mike"}

引数をinterfaceで宣言して、メソッドを実装済みのstructのみ受け付けるようにできる(ダックタイピング)

タイプアサーション

引数の型を interface{} にすれば何でも渡せる
その場合、i.(int) などで型を変換することをタイプアサーションという
インターフェースでない通常の型の変換(タイプコンバージョン、キャスト)とは違う

switch type文で複数の型に対応

Stringer

string()メソッドを実装するとそれが標準出力になる

func (p Person2) String() string {

カスタムエラー

自分なりのエラーを出したい場合はString()同様、Error()を実装すればよい

func (e *UserNotFound) Error() string {

Error()はポインタ型推奨

エラーを比較するときはポインタで比較しないと同じエラーになっちゃう

まとめ

C言語みたいだと感じた

参考

現役シリコンバレーエンジニアが教えるGo入門 + 応用でビットコインのシストレFintechアプリの開発

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0