学習ノート 名前: Dozi0116

プログラムのことか、ゲームのことか、サイト作ったらそっちに移転したい

Go言語の違うところ #3

はじめに

dozi0116.hatenablog.jp

これの続き。

CやPythonをかじったことある人が、『基礎からわかるGo言語』を読んで順番に思ったことを書き連ねていくノート的なやつ

今日は眠いし遅いので短め

ポインタ

Cのポインタを理解していれば全く同じものなのでOK。 ただし、ポインタの演算は安全性を考慮して禁止されている。

package main

import "fmt"

func main() {
    var a, b int = 1, 1

    f(a, &b)

    fmt.Println(a, b); // 1, 3
}

func f(a int, b *int) {
    a += 2
    *b += 2
}

ポインタでメモリだけ先に確保しておきたい場合は、mallockではなく、 new(<type>) を使う。

ゼロ値

変数宣言時に値を入れない場合、Goはゼロ値で自動的に初期化してくれる。(すごく便利)

数値型→0 bool→false string→'' 配列(notスライス)→各要素をゼロ値にしたもの 構造体→各要素をゼロ値にしたもの その他→nil, NULLでもNoneでもない

ラベル

(break|continue)のあとにラベルを指定すると、任意の位置へジャンプできる。

func main() {
    for {
        for i := 0;i < 5;i++ {
            if i == 3 {
                break INNER_BREAK_DEST
            }
        }
    }

INNER_BREAK_DEST:
    // ここに飛べる
}

goto

Go言語の違うところ #2

はじめに

dozi0116.hatenablog.jp

これの続き。

CやPythonをかじったことある人が、『基礎からわかるGo言語』を読んで順番に思ったことを書き連ねていくノート的なやつ


パッケージ

ソースが複数ファイルからなる場合、「パッケージ」という単位でソースを扱う。 同一パッケージなら、別ソースで宣言された変数や関数にアクセスすることができるのが特徴。

そして、外部のパッケージのものを扱いたい場合は import する。 独自パッケージを作る場合、GOPATHを通してあるディレクトリ以下に置かないと認識されないので注意!!

GitHubとかを用いてちゃんとしたプロジェクトコードレベルで管理したいなら以下のサイト様が参考になりそう。

qiita.com

package main

import "fmt"
import "my/sample" // $GOPATH/src/my/sample 以下にあるソースを読む
import rename "my/sample2" // python の as 的なこともできる

for文

Goのforは (Cのwhile + for + pythonのfor) というイメージ。 紛らわしくないようにwhileキーワードがない。 break, continue どちらも完備。

// 基本パターン
for var i int = 0; i < 5;i++ {
    // () がないのはpythonっぽいよね
    // もちろん条件式を省略してもOK
}

// whileっぽいパターン
i := 0
for i < 5 {
     i++
}

// 無限ループは条件節を省略する
for {
    // infinity!
}

// python for パターン
arr := [...]string["hoge", "fuga", "piyo"]
for element := range arr {
    // 順番に取り出せる
}

// enumrate for みたいなこともできる
arr := [...]string["hoge", "fuga", "piyo"]
for index, element := range arr {
    // 便利
}

if文

ほぼほぼ同じ。 Cとの違いは条件節の()がないこと、pythonとの違いは、ブロックをちゃんと{}で囲み、elif じゃなくて else if なところ。 そして共通で違うところは、初期化節があるところ。

if x < y {
    // ほぼ同じ
} else if y < 100 {
    // 感覚で
} else {
    // 使える
}

if a := add(3, 5);a < 10 {
    // 余計な変数宣言が減ってちょっと便利
}

switch文

switch - case - dafault の流れはCと一緒だけど、breakが必要なくなった。 代わりに、下の文まで続けて行いたい場合は fallthrough キーワードを記述する。

そして、待望の(?)switchの条件節に式がかけるようになった

switch number {
    case 3:
        // 3
    case 4, case 5:
        // 4, 5
    case 6:
        // 6
        failthrough
    case 7:
        // 6, 7
    default:
        // それ以外
}

// 条件節に式を用いる
switch {
    case num < 3:
        // 3未満
    default:
        // 3以上
}

Go言語の違うところ

目的

c言語Pythonはわかっているから、その知識を流用しながらGo言語に入門したい! ということで、「超基本的な部分はxxxと同じ、ここだけ違うから注意!」のような感じで『改訂2版 基礎からわかるGo言語』をかいつまんでみる

という名目の11/07勉強ログ


はじめのコード

package main

import "fmt"

func main() {
    var a, b, c int = 123, 456
    var d = true | false
    fmt.Println("Hello, World!")
    fmt.Println(a+b, c, d)
}
  • 実行時に呼び出される関数はmainパッケージのmain関数
  • 必要なモジュールは import する
  • 関数宣言は func name() {}
    • このとき、開カッコは func name() と同じ行にないとCE
  • セミコロンはなし
  • 変数宣言は var name[, name2, ...] type [= initalize] で行う。
    • ない場合は勝手にゼロ値(空文字とか0とかfalseとか)で初期化
    • 初期化する場合は型を省略可能
  • 真偽値はtrue, false

実行するには

コンパイル

go build source.go

gccと同じように書くことができる、 -o オプションも同じ。

コンパイルファイルいらないよって場合は、

go run source.go

コンパイル+実行してくれ、コンパイルファイルは残らない。

string型の文字数取得

pythonのようにlen関数が用意されているが、バイト文字列として認識するため、日本語は正常にカウントできない。 → unicode/utf8 パッケージにあるRuneCountInStringを使えばOK

型を宣言する

cでいうtypedefと同じようなもの。

type ll int64

type point2D struct {
    x float64
    y float64
}

型変換

Pythonのような型推論はほぼないし、Cのような暗黙な型変換もない。 ちゃんと

var a int = 1
var b float64 = float64(a)

のように明示的に行ってあげる。

Cのように、string = string(int) のようになる場合、文字列になるのではなく、数値が指し示すUnicode文字になる

演算子

算術演算子

ほぼほぼC準拠。

var a int = 10
var b int = 20
b /= a         /* 2 */

var c int = 7 &^ 3      // 111 &^ 011 = 100

var c string = "abc"
var d string = "def"
d += c       // "defabc

ビットクリア演算子(`&^ = and not)だけ目新しい感じ。 演算は文字列の足し算などもできるが、文字列の掛け算はできない、リストに対しては演算ができないなどPythonにはかなわない

比較演算子

C言語と形は同じ、文字(文字列)の辞書順比較もOK。 配列や構造体は比較できない。

インクリメント&デクリメント

var i int = 10
i++ // OK
var j int = i++ // CE
++i // CE

インクリメント・デクリメントと同じ行に他の演算を書くことができない 後置インクリメント・デクリメントのみできる

代入

Pythonのように,で区切った複数代入が可能。

変数宣言

Cっぽくも、Pythonっぽくもかける

package main
import "fmt"

func main() {
    var num1 int // 一番基本的
    var num2 int = 123 // 初期化できる
    var num3 = 123 // 初期化するなら型省略可能
    var num4, num5 int // まとめて宣言もできる
    num6 := 123 // はじめに入れる型に応じて型をキメてくれる
    const num7 = 123 // 定数
}

リテラル

2進数以外何でもかけるようなイメージ

a := true | false // 全部小文字
b := 0123 & 0xabc
c := 1 + 2i // Pythonと違って虚数はiを使う
d := 'A' // バイトコードが入る(型はint? byte?)
e := "A" // 文字列になる(型はstring)
f := `複数行・非エスケープ文字列`

iota列挙子

Cのenumっぽいもの、0オリジン(変更可能)で1ずつ増えて(変更可能)いく列挙体

const(
    hoge = iota // 0
    fuga  // 1
    foo // 2
    bar // 3
)

const(
    a = 1 + iota // 1から始まる
    b  // 2
)

Webコンテンツを作りたい! 0. 環境選定

背景

自分のWebページを作りたい けど、HTML,CSS,JS,Perlの知識はあっても、サーバーの構築するあたりの知識がまったくないので、せっかくだからここらへんの知識を手を動かしながら覚えたい。

やってみること

GCPをベースに、素朴なWebサーバーからコンテンツを配信するものと、サーバーレス構造を作って環境の構築を体験する。

目標

NoPaste のようなものを構築する。

ページ仕様

/ - 登録フォームと、登録したものの一覧を取得して表示するページ
L api
| L posts - POST 新たなメッセージを追加するapi。
|   L :id - GET idに対応したメッセージを返すapi。
|   L :id - PUT idに対応したメッセージを更新するapi。
L :id - idに対応したページを表示、ページからは更新もできる。ないなら404

技術選定

Webサーバーを作る方

GCE1インスタンスで構築する。 Client <=> Web Server <=> App Server <=> DB

サーバーレスな方

GCPのサービスをいろいろ使う。 Client <=> Cloud CDN <=> Cloud Storage, Cloud Function <=> Cloud SQL