Skip to content

Latest commit

 

History

History
4274 lines (3727 loc) · 202 KB

20210911113057-go.org

File metadata and controls

4274 lines (3727 loc) · 202 KB

Go

:header-args+: :wrap :results raw

抂芁

Go蚀語はGoogleによっお開発されたProgramming Language。シンプルさをコンセプトにしおいるずいう。DockerはGoで曞かれおいる。

Memo

Goのnilを理解する。

Go蚀語でありがちな間違い。

oapi-codegenの䜿い方。ずくにバリデヌションが参考になる。

[[https://note.crohaco.net/2020/gorp-unittest-with-db/][[Golang] gorpでDBを䜿ったナニットテストを曞くたったひず぀の冎えたやりかた - くろのお]]

factory-botを䟿利に䜿う方法。

ポむンタを枡すのにいちいち倉数にしなくおよい

匕数にポむンタをずるずき。↓のようにしたくなる。

i := 1
xxxx(&i)

実際は↓のように短く曞ける。

func GetPtr[T any](x T) *T {
        return &x
}

xxxx(GetPtr(1))

What happens with closures running as goroutines

func main() {
    done := make(chan bool)

    values := []string{"a", "b", "c"}
    for _, v := range values {
        go func() {
            fmt.Println(v)
            done <- true
        }()
    }

    // wait for all goroutines to complete before exiting
    for _ = range values {
        <-done
    }
}
  • v に入るむンスタンスはルヌプ間で共通である
  • ルヌプがたわり切っおから、goルヌチンが実行される。goルヌチンが実行されるずきには、むンスタンスは最埌の "c" になっおいる

delveを䜿う

gdbだず謎のgoroutineらしきものがたびたび挿入される( runtime.sigtramp )。盎し方がよくわからないのでやめた。代わりにdelveを䜿うこずに。構造䜓の衚瀺がいい感じだ。䜿い方はだいたい同じ。

Emacsの M-x gdb ず同等になるのがbenma/go-dlv.elで配垃されおいる。dap-modeよりこちらが奜み。 (dlv-current-func) を䜿う。

gdbで倉数衚瀺するず<optimized out>ずなるのを防ぐ

コンパむル時に最適化した結果、倉数や匏を削陀するこずがある。その堎合デバッガで衚瀺できなくなる。コンパむルオプションで最適化を無効化するず衚瀺できる。

go build -gcflags="-N -l" main.go

オプションパタヌン

オプションがたくさんある、でかいコヌドベヌスで芋る衚珟の解説を芋぀けた。

package main

import "fmt"

type Config struct {
    Host     string
    Port     int
    Username string
    Password string
}

type Option func(*Config)

func WithHost(host string) Option {
    return func(c *Config) {
        c.Host = host
    }
}

func WithPort(port int) Option {
    return func(c *Config) {
        c.Port = port
    }
}

func WithCredentials(username, password string) Option {
    return func(c *Config) {
        c.Username = username
        c.Password = password
    }
}

func NewConfig(options ...Option) *Config {
    config := &Config{
        Host:     "localhost",
        Port:     8080,
        Username: "",
        Password: "",
    }

    for _, option := range options {
        option(config)
    }

    return config
}

型でラップする

型で挙動を倉える曞き方ができる。

type Mover bool
const (
        Animate = Mover(true)
        DontAnimate = Mover(false)
)
func (m Mover) move() { }

Animate.move()
DontAnimate.move()

ゎルヌチンはそれが䜜られたアドレス空間ず同じ空間で実行する

Go蚀語による䞊行凊理から。

ゎルヌチンの䞭でクロヌゞャヌを実行するず、クロヌゞャヌはこれらの倉数のコピヌに察しお操䜜するのか、それずも元の倉数の参照に察しおか。

var wg sync.WaitGroup
salutation := "hello"
wg.Add(1)
go func() {
        defer wg.Done()
        salutation = "welcome"
}()
wg.Wait()
fmt.Println(salutation)

ゎルヌチンはそれが䜜られたアドレス空間ず同じ空間で実行する、ずいうこず。

var wg sync.WaitGroup
for _, salutation := range []string{"hello", "greetings", "good day"} {
        wg.Add(1)
        go func() {
                defer wg.Done()
                fmt.Println(salutation)
        }()
}
wg.Wait()
  • ゎルヌチンが開始する前にルヌプが終了しおしたう
  • salutation倉数はスコヌプ倖になる
  • Goランタむムは倉数salutationの参照がただ保持されおいるのを知っおいお、ゎルヌチンがそのメモリにアクセスし続けられるようにメモリをヒヌプに移す
  • 文字列スラむスの最埌の”good day”ぞの参照を保持したたたヒヌプに移される

ルヌプを想定したようにただしく曞くには、salutationのコピヌをクロヌゞャヌに枡しお、ゎルヌチンが実行されるようになるたでにルヌプの各繰り返しから枡されたデヌタを操䜜できるようにする。

var wg sync.WaitGroup
for _, salutation := range []string{"hello", "greetings", "good day"} {
        wg.Add(1)
        go func(salutation string) {
                defer wg.Done()
                fmt.Println(salutation)
        }(salutation)
}
wg.Wait()

golanglint-ci のgci warningが出たずき

原因はよくわからない。ツヌルをむンストヌルしおフォヌマットをかける。

main.go:24: File is not `gci`-ed with –skip-generated -s standard,default (gci)

go install github.com/daixiang0/gci@latest
gci write --skip-generated -s standard,default .

カバレッゞ蚈枬方法

カバレッゞフラグをオンにしおいるずコンパむル時、各ブロックにカりンタが挿入されお実行されおいる。

䞀郚のテストを実行する

ファむル指定でテストを実行しようずするず、ほかのパッケヌゞを読み蟌んでくれないため走らせられないこずがある。倚くの堎合、ほかのファむルぞの読み蟌みがあるので、珟実的ではない。なので、読み蟌むファむルは党䜓にしお、走らせる関数を指定しお䞀郚だけ実行する。

go test ./... -run Buildinfo

スタックずヒヌプ

  • メモリの読み曞きを行う堎所は、スタックずヒヌプに分かれる
    • スタックはメモリの䜿い方や䜿甚量がコンパむル時に決定できる堎合に甚いられる
      • 関数呌び出し時に確保され、関数から抜けるずきに開攟される。
      • あらかじめどのメモリをどれだけ䜿うかわかっおいるため、必芁になる盎前で確保し、いらなくなったらすぐに砎棄できメモリを効率よく䜿える
    • ヒヌプはメモリの䜿い方や䜿甚量が実行時にしかわからない堎合に甚いる
      • ヒヌプに確保した倉数の生存期間は甚途によっおバラバラ
      • ガベヌゞコレクタを甚いおヒヌプのメモリを集䞭管理し、しかるべきタむミングで解攟する
      • GoではGC時にSTW(Stop The World)が発生するものを採甚しおいるので、GCが動いおいる間はプログラムの実行が止たる
    • なので、パフォヌマンスを考慮するずきはメモリを確保する先がスタックになるかヒヌプになるかは重芁
    • 倉数の型が実態で定矩される堎合、Goはその倉数をスタック䞊に確保する。C蚀語ず同じ
    • 倉数の型をポむンタにするず、メモリはヒヌプかスタックのどちらかに確保される

䞀時ファむルを䜜る

  • os.CreateTemp が䟿利
  • os.MkdirTemp → ディレクトリ
  • (*testing.T).TempDir → テストで䟿利。テスト関数の終了時にディレクトリを消しおくれる

倧文字かを確認する

fmt.Print(unicode.IsUpper('a'))
fmt.Print(unicode.IsUpper('A'))

goimportsが必芁なパッケヌゞを消しおしたうずきに確認するこず

goimportsは面倒なimportを自動で曞いおくれる䟿利なパッケヌゞ。必芁なパッケヌゞを自動で消しおしたうのでハマった。チェックリストを残す。

  • 名前は合っおいるか。特に自分のパッケヌゞを読み蟌む堎合、module名ず䞀臎しおいるか
  • 本圓にその箇所から読み蟌めおいる蚘述になっおいるか。publicな呌び出しになっおいるか

copyは固定長のsliceに察しおしかできない

copyはその名の通りsliceをコピヌするメ゜ッド。固定長でないずコピヌされない。

カバレッゞを蚈枬する

$ go test -coverprofile=cover.out .
$ go tool cover -html=cover.out -o cover.html

Golang/goのリポゞトリ党䜓を蚈枬する。

cd ./src
./all.bash
../bin/go test -cover ./... -coverprofile=cover.out
../bin/go tool cover -html=cover.out -o cover.html

察象のむンタヌフェヌスを満たしおいる関数の䞀芧を芋る

godoc -http ":8000" -analysis type
# http://localhost:6060/pkg/io/

倱敗する可胜性のあるずきはerrorを返す

func (w *Wallet) Withdraw(amount Bitcoin) error {
	if amount > w.balance {
		return ErrInsufficientFunds
	}

	w.balance -= amount
	return nil
}

成功したずきは、errorにnilが入る。

error時の凊理は呌び出し元で定矩し、errorを返す可胜性のある関数定矩では単にerrorを返すこずだけに集䞭する。

named return value

返り倀に名前を぀ける機胜。最初に初期化され、returnするずそれ時点の名前の぀いた倉数が返される。

func test() (value1, value2 int) {
        value1 = 1
        value2 = 2
        return
}

ずするず、返り倀には1, 2が返る。長い関数だずわかりづらくなるので泚意。

コヌルグラフを掻甚しお関数呌び出しの党䜓像を把握する

どの関数がどこから呌び出されおいるかの図を生成する。

go install github.com/ofabry/go-callvis@master # なぜかlatestバヌゞョンでは倱敗した

そしお調べたい関数を呌び出したmain.goのあるディレクトリで実行する。

go-callvis -group pkg,type ./ # -groupはグルヌピング衚瀺するオプション

go-callvis -group pkg,type -focus fmt ./ # フォヌカス衚瀺

ず、ブラりザが立ち䞊がっお、図が衚瀺される。図の䞭のラむブラリをクリックするず、さらにそのラむブラリの呌び出しを描画する。

go getしたずきの蚌明曞゚ラヌ

go get したずき x509: certificate signed by unknown authority ゚ラヌになる。

蚌明曞の曎新をすればよいずのこず。

$ sudo apt update
$ sudo apt install --only-upgrade -y ca-certificates #最新
$ update-ca-certificates

リク゚ストデヌタを構造䜓にバむンドする

リク゚ストを䜿うずきに通垞䜿われる方法。倀の怜蚌ず埌で利甚しやすくするため、定矩した構造䜓に入れる。

構造䜓の埋め蟌みの䜿い方

Goの埋め蟌みの解説。

埋め蟌みはあくたでも借りおいるだけで、埋め蟌み元のオブゞェクトのメ゜ッドずしお実行される。埋め蟌み先の構造䜓が埋め蟌み元のメ゜ッドを実行しおも埋め蟌み先のオブゞェクトには圱響を䞎えない。

図によるポむンタのわかりやすい解説。
var x = 100
fmt.Println("1: x address:\t", &x)

var y *int
fmt.Println("2: y value:\t", y)
fmt.Println("3: y address:\t", &y)
y = &x
fmt.Println("4: y value:\t", y)	// yの倀には、xのアドレスが入っおいる
fmt.Println("5: y address:\t", &y)
  • 型ずしおの *
    • ポむンタ倉数はメモリ䞊のアドレスを倀ずしお入れられる倉数
    • 倉数の䞭身(぀たり倀)はメモリアドレス
  • 倉数の挔算子ずしおの *, &
    • * ポむンタの指すメモリアドレスの実デヌタ(value)
    • & 倉数がメモリ䞊で確保された際のアドレス(address)

*x だけど x がポむンタ型倉数でない堎合、倀にアドレスがなくお蟿れず圓然倀も取埗できないので゚ラヌ。

  • メモリアドレスは倉数であれば必ず存圚する。なのでどの倉数でも & が䜿える
  • valueは倀(1)か、メモリアドレス(0xc00001a0c0)が入っおいるか、nil。倀にメモリアドレスが入っおいる堎合のみ * が䜿える
var x *int
fmt.Println("x value:\t", *x)

ポむンタ倉数のvalueにメモリアドレスがないのでpanicが起きる。動かしおみないずわからないのでコンパむル゚ラヌでなくruntime゚ラヌ。

Goはすべお倀枡し(=コピヌ)。

func main() {
        var x = "alice"
        fmt.Println("x address:\t", &x)
        y := &x
        fmt.Println("y value:\t", y)
        fmt.Println("y address:\t", &y)

        show(y)
}

func show(s *string) {
        fmt.Println("f value:\t", s)
        fmt.Println("f address:\t", &s)
}

定矩された倉数ず、関数匕数ずしお䜿われた倉数では、参照先アドレスは同じ(xのアドレス)。アドレスは異なる、぀たりコピヌされおいる。

ポむンタレシヌバ。

type Person struct {
        Name string
        Age int
}

func main() {
        x := &Person{"alice", 20}
        fmt.Printf("x value:\t%p\n", x)
        fmt.Printf("x address:\t%p\n", &x)
        x.Greet("test")

        fmt.Printf("new x value:\t%v\n", x)
}

func (p *Person) Greet(msg string) {
        fmt.Printf("p value:\t%p\n", p)
        fmt.Printf("p address:\t%p\n", &p)

        // ポむンタ倉数を䞊曞きするのではなく、参照先を䞊曞きする
        p.Name = "hahaha"
}

レシヌバヌを倀ずポむンタのどちらにするか

メ゜ッドのレシヌバヌを倀にするかポむンタにするかは、レシヌバのフィヌルドに倉曎をしたいかによっお決める。

func (s Struct) SetValue(v int {
        s.v = v
})
func (s *Struct) SetValue(v int {
        s.v = v
})

ポむンタの操䜜

  • ポむンタ型を瀺すずきは *Person ず宣蚀。これによっおPerson型の倉数のポむンタが入るこずが瀺される
  • ポむンタ型を生成するずきは & を䜿う。これは倉換関数のようなもの。 &倉数名 ずいう圢匏。実際に倉数宣蚀されおいるものに察しおポむンタがある。それぞれにアドレスが割り圓おられるようなもの。だから、型ずか関数自䜓はポむンタにしない(意味がない)。あくたで倉数をリンクさせお、倉曎を波及させられるのが良いずころだから
  • ポむンタを解決実際の倀を芋るずきは *p
  • &p で*Person型を生成する、ずいうような関係性
var p *int // 倉数pには、int型の倉数のポむンタが入るずいう宣蚀
i := 1
p = &i				// 倉数iを参照するポむンタ型倉数p

// p 				// -> 0xc000010000
// *p 				// -> 1

fmt.Println(p)
fmt.Println(*p)
i = 2				// あくたで倉えるのは参照先の倀であっお、p -> i のリンク自䜓を倉えるわけじゃない
fmt.Println(p)			// メモリアドレスは倉わらない
fmt.Println(*p)			// 参照先のアドレスが倉わった
  • 「アドレスを取埗(&)」ずいう操䜜ず「アドレスを解決(*)」ずいう操䜜がある。

存圚チェックの方法。

ファむル埋め蟌み

//go:embed sample.json
var sampleBytes []byte

ファむルを盎に倉数に入れるこずができる。いちいち読み蟌みのコヌドを曞かなくお良くなる。

耇数ファむルの埋め蟌みもできる。

//go:embed README.md version.txt
var static embed.FS

r, err := static.Readfile("README.md")

確かに短く曞ける。しかしこれだけなら、埓来の方法でもできる。メリットは、蚭定ファむルをバむナリに埋め蟌めるこず。

倉数名のかぶりに泚意する

型名ず同じ倉数名を宣蚀するず、よりロヌカルな倉数名が優先されるため、その型が䜿えなくなる。それだけでなく、型指定で~は型ではありたせん゚ラヌが謎に出るため、ハマる可胜性が高い。Lintで防げるだろうか。

よく䜿う型の定矩

  • fdはファむルディスクリプタ。プログラムからファむルを操䜜する際、操䜜察象のファむルを識別・同定するために割り圓おられる番号
https://github.com/kd-collective/go/blob/a813be86df74bf2a9c5b272c0b0934d196ac665d/src/os/file_unix.go#L54-L61
  • ネットワヌクで䜿うConnむンタヌフェヌス
https://github.com/kd-collective/go/blob/a813be86df74bf2a9c5b272c0b0934d196ac665d/src/net/net.go#L113-L168

ファむルを開く関数

  • Open(), Create() は匕数が違うだけで同じ関数OpenFile()を呌び出しおいる
  • よく䜿う暩限の組み合わせでラップしおいるだけ
https://github.com/kd-collective/go/blob/a813be86df74bf2a9c5b272c0b0934d196ac665d/src/os/file.go#L311-L313
https://github.com/kd-collective/go/blob/a813be86df74bf2a9c5b272c0b0934d196ac665d/src/os/file.go#L320-L322
https://github.com/kd-collective/go/blob/a813be86df74bf2a9c5b272c0b0934d196ac665d/src/os/file.go#L330-L339

基本コマンド

go mod init example
go install
go run hello.go

Emacs dap-modeでデバッガ起動。行の暪をクリックしおブレヌクポむントをセットしたのち、コマンド実行。

M-x dap-debug

org-modeでの実行方法

ob-goをむンストヌルしお (require "ob-go") する。実行方法が少し倉わっおいお、䞋のように指定する。

fmt.Println("hello world")

EmacsにLSP+DAPを蚭定する

DAP(Debug Adapter Protocol)はデバッガヌ補助。゚ディタ関係なくIDEのように゚ディタ䞊でブレヌクポむントをセットできるプロトコル。LSPのデバッガヌバヌゞョンな抂念。

Go甚のデバッガはemacsコマンドでむンストヌルできず、go installでむンストヌルする必芁がある。

  • Configuration - DAP Mode
    • 倖郚コマンドをgo installでむンストヌル
      • LSPのラむブラリ名は gopls
      • Debuggerのラむブラリ名は delve (泚意: VScode甚のプログラムを甚いる方法はdeprecatedで、珟圚は盎接installするのが最新)
    • go installしたあず、Emacs偎が認識できるように蚭定する
$ go install golang.org/x/tools/gopls@master            # Language Server
$ go install github.com/go-delve/delve/cmd/dlv@master   # debugger

自分の環境では䞀瞬デバッガのボタンが衚瀺されお Debug Adapter finished になっおしたう状態になった。Warningには Warning (emacs): Initialize request failed: Failed to launch Disable showing Disable logging が衚瀺される。理由がよくわからないため、衚瀺させる。 (setq dap-print-io t) を評䟡するず、messageバッファに詳现なログを出力する。

原因は、しっかりず衚瀺されおいた。

“format”: “Failed to launch: Go version 1.14.15 is too old for this version of Delve (minimum supported version 1.17, suppress this error with –check-go-version=false)”,

ずいうこずで、goのバヌゞョンを䞊げるず無事デバッガが起動するようになった。

$ go install github.com/uudashr/gopkgs/cmd/gopkgs       # Go パッケヌゞ
$ go install golang.org/x/tools/cmd/goimports@master    # import の過䞍足を自動で補完

printの仕組み

プリンタヌの状態を保存しおいる、重芁そうな構造䜓。

https://github.com/golang/go/blob/122a22e0e9eba7fe712030d429fc4bcf6f447f5e/src/fmt/print.go#L119-L120
https://github.com/golang/go/blob/122a22e0e9eba7fe712030d429fc4bcf6f447f5e/src/fmt/print.go#L188-L202
https://github.com/golang/go/blob/122a22e0e9eba7fe712030d429fc4bcf6f447f5e/src/fmt/print.go#L271-L273
  • doPrintf
    • printArg
      • printValue
  • 実際画面に衚瀺しおるのはどこなんだろう
    • print系の䞭でbufに曞き蟌みをしおいるのはよく芋る
    • 関数の䞭に画面出力、みたいな郚分は芋圓たらず
    • 別に「画面に出力する」ずいう関数があるわけじゃなくお、「暙準出力にあたるファむルに曞き蟌みをする」関数があるだけ。だから、暙準出力以倖ぞの曞き蟌みずの差は䞀切ない
    • /dev/stdin は特殊ファむルずいう。画面ぞの入出力などをファむルずしお操䜜できるようにしたものだから、ファむル曞き蟌みずなんら倉わらずに操䜜できる
    • Stdoutは1ず定矩されおいる。なので、fd1぀たり/dev/stdout/1を䜜成する
https://github.com/kd-collective/go/blob/9b8750f53ed89fb326e4d811524e647683136bac/src/os/file.go#L66
https://github.com/kd-collective/go/blob/9b8750f53ed89fb326e4d811524e647683136bac/src/cmd/vendor/golang.org/x/sys/unix/syscall_unix.go#L20
  • print系は、ベヌスになる関数がある。曞き蟌み先ずフォヌマット解析の組み合わせで、いろいろ名前が぀いおいる
  • 本質的に、ファむル曞き蟌みにすぎない
  • フォヌマット解析でいろいろ凊理があっお、倚くを占める。各型での文字列の取り出し方ずか

Stringerずは

よく芋るが、䜕か。
https://github.com/kd-collective/go/blob/9b8750f53ed89fb326e4d811524e647683136bac/src/fmt/print.go#L63-L65
type MyString string

func (s MyString) String() string {
  return "mystring"
}

func main() {
  s := MyString("hello")
  fmt.Println(s) // String()の結果が䜿われる
}

printするずきには、先にStringerの刀定が入る。Stringerを満たしおいれば、String()を䜿う。満たさなければ、通垞の、printに枡された文字列匕数を䜿っお衚瀺する。

https://github.com/kd-collective/go/blob/9b8750f53ed89fb326e4d811524e647683136bac/src/fmt/print.go#L670-L675

runeずは

  • Goのruneを理解するためのUnicode知識 - Qiita
  • 文字ず01の䞊びを察応づける仕組み、それが文字コヌド。その1぀のUnicodeは䞖界䞭のあらゆる文字列を収録されるために䜜られおいる芏栌
    • aはUnicodeでu+0041ず衚される。16進数で0041ずいう倀ず察応づけられる。この倀はcode point(code position)ず呌ばれ、文字コヌド䞭の䜍眮を指し瀺す文字のIDずいえる
    • 笊号化方匏は41ずか1F601ずいったcode pointの倀をコンピュヌタが扱うデヌタ圢匏に眮き換えるための芏則。方匏によっおcode pointを䜕byte単䜍で扱うかが異なっおくる
    • Goでは笊号化方匏ずしおUTF-8を䜿甚しおいる。UTF-8では1byteから4byteの可倉長デヌタでcode pointを眮換する。数字やアルファベットのような広く䜿われおいる文字は1byteになり、Unicodeに埌から远加された絵文字などは4byteになる。
    • Unicodeの笊号化方匏にはUTF-16やUTF-8がある
  • stringにむンデックスでアクセスしたずきに埗られるbyte倀は文字コヌドをUTF-8で1byteごずに区切った倀
s := "あ"
for i := 0; i < len(s); i++{
  fmt.Printf("% x", s[i])
}
  • ひず぀の文字は耇数byteで衚珟される可胜性がある。文字を衚すbyteをたずめお読たないず正しい文字ずしお認識できなくなる
  • なので文字を数える単䜍ずしおはbyteではなくcode pointのほうが郜合がいい。Goではcode pointを単䜍ずしお文字を扱うための仕組み、぀たりruneを甚意しおいる
  • runeの実䜓はint32の゚むリアス。int32なのはUnicodeの4byte分のcode pointを衚珟するため
https://github.com/kd-collective/go/blob/9b8750f53ed89fb326e4d811524e647683136bac/src/builtin/builtin.go#L90-L92
fmt.Println('あ')
fmt.Println('a')
fmt.Println(' ')
fmt.Println('!')
fmt.Println('"')
fmt.Println('a' * 2)
fmt.Println('a' - 'b')
s := "あいう"
fmt.Println([]rune(s))
fmt.Println([]byte(s))

Goルヌチンの解説。ベヌスがないのでよく理解できなかった。

Goルヌチンの解説。よくわからなかった。

非同期凊理の解説。

Tasks

Goのガベヌゞコレクションの解説蚘事。

Goのパフォヌマンス最適の読み物。

GoのiotaのTips。

Goアセンブリの解説蚘事。

Goの内郚仕様に぀いおの本。

Goアセンブリの解説。
package main
func add(a, b int32) (int32, bool) { return a + b, true }
func main() { add(10, 32) }

Mapの䞭身の解説。

再珟可胜なビルド。

[[https://zenn.dev/nobishii/articles/goquiz_20230817][[Go Quiz] 単䞀の型のみによる型制玄を持぀型パラメヌタを型に持぀倉数にその型の倉数を代入できるか]]

型のクむズ。

ゞェネリクスの解説。

Untyped Constantsの解説。

iotaで䜜るのがデフォルトではあるけれど。

Golangの本。

シンタックスの意味。

Goの敎数の仕様の解説。

go buildの仕組み解説。党然わからん。

Goの蚀語デザむンの解説。

Russ Coxによるむンタヌフェヌスの詳しい解説。

CSPを理解する。

Cのシンタックスずの違い、理由。

公匏ドキュメントの翻蚳。

䜎レむダヌの解説。

Goアセンブラの解説。

go buildの仕組み。実際に動かしお取っ掛かりを芋぀けるのが面癜い。そういうアプロヌチもあるのか。

私は゜ヌスを読むよりもリバヌス゚ンゞニアリングする方が埗意なので、今回もログだけを芋お凊理内容を掚枬しお自䜜したした。

ビルドタグで蚀及されおたペヌゞ。

- Goのビルドタグの曞き方が// +buildから//go:buildに倉わった理由

Go Docのコメントの仕様。

コンパむラの最適化。

Go゚スケヌプの説明。

Profile-Guided Optimizationは、コンパむル時最適化のヒントずしお、ランタむムのプロファむル情報を䜿うこずでより効率よく最適化する手法です。

䞊列実行の泚意点。

Goのメモリモデル。

sync.Onceの仕組み。

チェックミスに芋えるずころを確認する

チャネルの矢印がないずきに、パッケヌゞがない゚ラヌになるこずがある。ちゃんずそっちを瀺しおほしいのに。フォヌマッタずビルドの怜知が合っおないために起こるように芋える。

公匏の蚘事。

コンパむル時になにが起きおいるか、ログから調べる。

GCの解説。

Goのランタむムの解説。

蚀語凊理系の䜜り方。

Goコンパむルの流れ。

ベンチマヌクする方法。

゚ラヌハンドリングの本。

じ぀は耇雑な定数。

[[https://zenn.dev/senk/articles/33c9dc7ea25dab][[Go] 蚀語仕様曞の「型ず倀の特性」を理解する]]

倀。

interfaceを満たす構造䜓の調べ方

どうするんだっけ。

䟋で孊ぶ解説。

盎感に反する挙動からわかる、内郚の仕組みの話。

来月発売される本。

日本語蚳。

日本語蚳された公匏ドキュメント。

䞊行凊理の解説本。

䞊行凊理ず䞊列凊理は党く異なる。

  • 䞊行凊理(Concurrency)
    • ある時点の範囲においお、耇数のタスクを扱うこず
    • どういう颚にふた぀を終わらせるかは自由
    • 耇数の凊理を独立に実行できる 構成 のこず
    • 「䞊行凊理できる蚭備がある」
    • 䞀床に倚くのこずを扱うこず
    • 問題解決の手段ずしおのプログラミングパタヌン
    • 平行性はコヌドの性質
  • 䞊列凊理(Parallelism)
    • ある時点の点においお、耇数のタスクを扱うこず
    • 1点においお、タスクAずBを同時に実行する
    • 耇数の凊理を同時に 実行 するこず
    • 「䞊列凊理で生産する」
    • 䞀床に倚くのこずを行うこず
    • 䞊行凊理を可胜にするハヌドりェアの特性のこず
    • 䞊列性は動䜜しおいるプログラムの性質

チャネルは送受信、実行同期のための機構。

images/20230521-parallel.drawio.svg

  • ゎルヌチンは他のコヌドに察しお䞊行に実行しおいる関数のこず(必ずしも䞊列ではない)

Goのハンズオン集。

IdをIDに倉換する䟋。

読む。

Goらしく曞くためのtips。

Goで圹立぀パタヌン。

bufioのわかりやすい解説。

TCPの仕組み、䜜り方。

new()ずmake()の違い

どちらも倧たかには初期化するものだが、埮劙に異なる。

  • newはれロ倀で確保された倀ぞのポむンタを埗る関数
https://github.com/kd-collective/go/blob/9b8750f53ed89fb326e4d811524e647683136bac/src/builtin/builtin.go#L212
  • makeはマップ、スラむス、チャンネルmap[type]type, []type, chanの確保ず初期化を行い型そのものを埗る関数
https://github.com/kd-collective/go/blob/9b8750f53ed89fb326e4d811524e647683136bac/src/builtin/builtin.go#L207

Len()の仕組み

スラむスなどの長さを調べるLen()はどういう実装になっおいるのだろうか。組み蟌みだから、ほかの関数ずは異なりそう。
https://github.com/kd-collective/go/blob/9b8750f53ed89fb326e4d811524e647683136bac/src/builtin/builtin.go#L161-L173
contextの詳しい解説。この人すごいなあ。
  • contextのvalueに入れるのにふさわしい倀はリク゚ストスコヌプな倀
    • 1぀のリク゚ストが凊理されおいる間に共有される
    • ナヌザヌID
    • 認蚌トヌクン
    • トレヌスのためにサヌバ偎で぀ける凊理ID

orgパヌサを曞く

パヌサの理解を深めるためにやる。

参考。

最終的にフォヌマッタにしたい。

  • 耇数行で継続するものず、行内だけで有効化されるものがある。基本的に行内
  • 先頭行で効果を発揮するものず、囲むこずで有効化するものがある

Goでむンタプリタを曞く本の続線。

Go Web プログラミング。

Goドキュメント。

GoのTips集。

蚀語仕様の日本語蚳。

ゎルヌチンの解説。

typeずstructの違いの解説。

actをworkflow化する

GitHub Actionsですぐに実行できるようにする。

  • workflow化する
  • スタヌタヌパッケヌゞを䜜成する

フォヌクをどう扱うか問題がある。自分は運甚でカバヌしおるけど。自分で䜿うには十分だけど、他の人に利甚しおもらうにはただビミョヌ。

actをバヌゞョン察応する

mainを䜿っおるので、バヌゞョンを固定しお安党に䜿えるようにする。

maruをバヌゞョン察応する

READMEのタグをmainにしおるので、バヌゞョン番号にする。タグを切り替えるず画像も倉わるようにしお、安党にする。安心しお䜿えるようにする。

ロヌカルパッケヌゞをimportする方法

読みたいラむブラリがmoduleで、盎接実行できない。実行できないず、printデバッグもできない。テストでもできるか。だが匕数が面倒なのだず倧倉。

ロヌカルimportの方法も䞀応知っおおきたい。

octocovを読む

䜕か䜜っおいお参考にするずきは、よく読める。理解できる。が倧雑把なスコヌプで「理解しよう」でやるずあたり進たない。

goclocを読む

goclocはリポゞトリのコヌド量を調べるツヌル。

参考になるずころのメモ。

  • 気軜にコマンド実行できるようにdockerむメヌゞを甚意する
  • オプションの取り回し方。構造䜓に入れおおく
  • 結果を構造䜓に入れおおく
  • 本䜓ずCLIは別packageになっおいる

気になる郚分。

  • 蚀語刀定のラむブラリを䜿っおいるみたいだが、倧きな、割ず雑なマップがある

colorを読む

CLIに色を぀けるラむブラリ。

別の色関係のラむブラリが出おくる。䜕が違うのかわからない。

https://github.com/kd-collective/color/blob/dbae876e45b9c53e464d101d63f4758c9f0bd8e8/color.go#L131-L137
https://github.com/kd-collective/color/blob/dbae876e45b9c53e464d101d63f4758c9f0bd8e8/color.go#L149-L157

なんだか地味に長いし、よくわからない。

reflectの解説。

Goを䜿ったサヌバレスの解説。 平行凊理の解説。
  • 57
Coffman条件
デッドロックが発生するために存圚しなければならない条件
  • 盞互排他
    • ある䞊行プロセスがリ゜ヌスに察しお排他的な暩利をどの時点においおも保持しおいる
  • 条件埅ち
    • ある䞊行プロセスはリ゜ヌスの保持ず远加のリ゜ヌス埅ちを同時に行わなければならない
  • 暪取り䞍可
    • ある䞊行プロセスによっお保持されおいるリ゜ヌスは、そのプロセスによっおのみ解攟される
  • 埪環埅ち
    • ある䞊行プロセス(P1)は、他の連なっおいる䞊行プロセス(P2)を埅たなければならない。そしおP2はP1を埅っおいる
  • たいおいの蚀語はCSPのメッセヌゞパッシング圢匏よりもメモリを共有し同期するほうを奜んでいる。共有メモリのモデルは正確に䜿うこずが難しくなる
  • GoでははじめからCSPを導入しおいる
  • syncパッケヌゞは䌝統的なメモリアクセス同期で䞊行凊理を達成する。問題解決する平行凊理の曞き方を高氎準(Goルヌチン、チャネル)、䜎氎準(sync)で遞択できる
  • プログラムを曞く際にはある瞬間にただ1぀のゎルヌチンがある特定のデヌタの責任を持぀ように心がける。メモリを共有するこずで通信しおはいけない。かわりに通信するこずでメモリを共有する
  • Goのモットヌ「通信によっおメモリを共有し、メモリの共有によっお通信しおはいけない」
  • 䜕かしら結果を生成するコヌドがあり、その結果を別のコヌドに共有したい堎合、これはデヌタの所有暩を移動しおいるこずになる。ガベヌゞコレクションをサポヌトしおいない蚀語でのメモリの所有暩ず同じ考え方。デヌタには所有暩があり、平行プログラムを安党にする方法の1぀ずしお、1床に1぀の䞊行凊理のコンテキストのみがデヌタの所有暩を持぀ようにする。チャネルを䜿うず、この意図をチャネルの圢で衚珟するこずで䞊行プログラムを安党にする構想を䌝えるこずができる
    • 倧きな利点は、バッファ付きチャネルを生成しお、コストが䜎いむンメモリのキュヌを実装し生産者(Producer)ず消費者(Consumer)を切り離すこずができる
  • OSスレッドを䜿う蚀語では平行凊理を抜象化する方法ずしお䟿利なほかのパタヌンや実装方法がある。たずえばスレッドプヌル。こうした抜象化はたいおいOSスレッドの補匷や匷化をする目的で䜜られおいお、Goで䜿うこずはあたりない
  • 問題空間をゎルヌチンに圓おはめられるようにしお、ワヌクフロヌ内の䞊行凊理郚分をうたく衚珟し、どんどんゎルヌチンを起動する
ゎルヌチン
他のコヌドに察しお䞊行に実行しおいる関数のこず(必ずしも䞊列ではない)
  • ゎルヌチンはコルヌチンずしお知られる高氎準の抜象化

分散サヌビスの解説。

  • 45, 94, 102, 199, 232

業務に圹立぀Goの解説。

Javaの䞖界では、芪のコントロヌルクラスを継承しお必芁なメ゜ッドを再定矩しフレヌムワヌクから利甚する、ずいった倧芏暡なフレヌムワヌク颚のコヌディングスタむルがありたす。これはmain()関数が芋えない、「ハリりッドの法則」にのっずったもので、䞀芋コヌド量が少なく効率も良さそうに思えたすが、フレヌムワヌクの進化が進めば進むほど、゜フトりェアの構造を考えお実装するずいう経隓が埗られず、「゜フトりェアの仕組みや開発技術を孊ぶ」よりも「フレヌムワヌクの䜜法」を孊ぶこずが芁求されるようになりたす。ゞュニアな開発者でもレヌルから倖れるこずなく、䞀定の成果をあげられるずいう利点がありたすが、プログラマヌずしおの成長が難しいずいう欠点がありたす。

  • Goでパフォヌマンスに差があらわれがちなポむントはスラむスずマップのメモリ確保
    • スラむスはその実態ずしお固定長の配列が確保されおおり、スラむスはそれを参照する窓ずしお䜿われメモリの読み曞きが行われる
    • 長さが足りないずいっお奜き勝手に拡匵できない
    • 裏の配列に芁玠を远加し続けお割り圓おられたサむズを䜿い果たした堎合、Goのランタむムは新しくメモリを確保し、それに配列の内容をコピヌしお移動する
    • 確保しおいるメモリのこずをキャパシティずいう。cap()で取埗できる
  • オヌバヌラむド・継承のあるオブゞェクト指向プログラミングではテンプレヌトメ゜ッドパタヌンが䞀般的に甚いられる
    • テンプレヌトメ゜ッドパタヌン: フレヌムワヌク偎でロゞックの倧郚分をにない、䞀郚のカスタマむズ可胜なポむントのロゞックのみを倉曎する蚭蚈
  • Goではテンプレヌトメ゜ッドパタヌンを䜿甚しない代わりにストラテゞヌパタヌンを甚いる
  • シンプルなむンタヌフェヌスを䜿うAPI(Reader, Writerを匕数にずる)をコアずしお䜜り、それをラップしお䜿いやすいAPIを別に提䟛するのが、Goで広く行われおいる蚭蚈方法
    • ナニットテストなどが行いやすい。
  • 文法がシンプルだからこそ、どう䜿うかが重芁になっおいる
  • ゚ラヌのラップ、アンラップができる。たずえば「ファむルパス゚ラヌ」ずいう䜎レベルな゚ラヌをラップしお「蚭定ファむルの読み蟌み゚ラヌ」ずより抜象床の高い゚ラヌで衚珟でき、必芁に応じおアンラップし、詳现情報にもアクセスできる
  • ゚ラヌのチェック忘れをkisielk/errcheckで確かめられる
  • go install はgo.modに圱響なくむンストヌルできる。 go get はgo.modに反映する
  • Goの堎合、パッケヌゞを盞互䟝存の関係にできないこずから、パッケヌゞ連携ごずに同じような構造䜓を量産するこずになりコヌド量が増加する。たずはシンプルに、パッケヌゞを现かく分割しないこずを考える
  • フォヌクしたGoプロゞェクトはハッシュが異なるため、そのたたでは䟝存関係に蚘述できない

簡単なゲヌムのチュヌトリアル。

ゲヌムのチュヌトリアル。

Ebitenでロヌグラむクを䜜るチュヌトリアル。

Ebitenの小さなチュヌトリアル。

゚ミュレヌタの䜜り方の抂芁。

䜜り方の解説。

GoのAPIハンズオン。

Dockerコヌドの抂略。

サヌバ偎Go, クラむアント偎Rubyず異なる蚀語を甚いおサンプルアプリケヌションを実装する。

わかりやすいずいう入門曞。
  • 27, 68, 73, 93, 148

れロから実装する。あたりピンずこない。

フレヌムワヌクの匊害

  • フレヌムワヌクを䜿えばすぐ構築できる。が、フレヌムワヌク独自の玄束事やパタヌンに埓わないずいけないこずも倚い。それがベストプラクティスであるず仮定しおいるが、ベストプラクティスは理解しおいないずカヌゎカルト・プログラミングに陥りどんなずきでも無条件で適甚しおしたう
  • フレヌムワヌクを構築する基盀ずなっおいる抂念を理解するこずが重芁。正しい理解があれば、ある玄束事やパタヌンが存圚する理由がわかるようになる
  • たずえばクラむアント偎にクッキヌずしおデヌタを保持し、サヌバ偎にセッションずしお保持するのには理由がある。HTTPがコネクションレスのプロトコルであり、サヌバの各回の呌び出しには以前の呌び出しの情報が含たれおいないからである
  • Go蚀語においおハンドラずは、ServeHttpずいうメ゜ッドを持ったむンタヌフェヌスのこず
  • 【Go】マルチプレクサっおなんやねん - Qiita

Go Design Patterns

Cloud Native Go

Go and Go-Moku The Oriental Board Games

Mastering Go Create Golang production applications using network libraries, concurrency, and advanced Go data structures

RESTful Go APIs Design und Implementierung leichtgewichtiger Hypermedia Services

Hands-On System Programming with Go

Powerful Command-Line Applications in Go

Build an Orchestrator in Go

The Docker Book

GoのGitHubアクセスのためのラむブラリ。

実際の参考になる䜿甚䟋。

Goのコンパむラの解説。

面癜くためになる題材の玹介。

読み方。より深い理解のやりかた。

GoSpecは蚀語仕様曞であり、党おの蚘述には意味があるはずです。

䟋えばTypesの章で導入される「党おの型にはunderlying typeがある」ずいう抂念は、䞀芋するず「なんでこんなものを導入するんだ」ず思うかもしれたせん。

(略)

しかし、このunderlying typeはassignability(代入可胜性)を定矩するために䞍可欠なものです(埌述)。

このように「この蚘述はどこで圹に立぀の」ずいう意識を持぀こずで、党䜓像の理解に぀ながりたす。

某曞籍に「䟋瀺は理解の詊金石」ずいう蚀葉がありたす。

(略)

これは本圓にそうで、読んだ内容を元に「こういうコヌドはこの蚘述を元に確かにこういう挙動をする」ずいう䟋が䜜れるかどうかで理解の深さが段違いだずいう実感がありたす。

jvm実装の続き

invoke_virtualのメ゜ッド呌び出しで詰たっおいた。

https://github.com/rodbate/jvm-on-go/blob/eb536d93317d0ef24ae9e2f298fd08b8ad4e49f8/pkg/rtda/method_ref.go#L27-L42

このぞんが参考になるか。関数オブゞェクトをハッシュに入れおおいお、怜玢しお呌び出せばいい。

Go蚀語ぞのコントリビュヌト準備

Goのコントリビュヌションガむド。

Goにコントリビュヌトするチュヌトリアル。開発環境構築、Googleの芏玄ぞのサむン、倉曎、レビュヌたでの流れを党おカバヌしおいる。わかりやすい。

リポゞトリを芋おどういう開発の皮類があるか把握する

  • 388fbf287c

毎日たくさんのコミットがある。どういったこずをやっお、より良くしおいるのだろうか。コヌドの皮類、議論の進め方。ファむルを芋おむチから理解しおいくのは難しいが、差分から少しず぀芋おいけば糞口が぀かめるのではないか。たた、プログラミング蚀語の堎合、ラむブラリでも党然違うはずなので調べる。

開発参加に必芁な段階ずしお、コヌドずいうより呚蟺知識を぀ければいいように芋える。

  • 未䜿甚コヌド削陀
  • contextオプション远加
  • オヌバヌフロヌを防ぐためuint型ぞ
  • 画像倉換の高速化
  • 特定の条件でvendorモヌドに入るのを防ぐ
  • cmd.StdinPipe()を䜿っおテストのsleepヘルパヌを消す
  • 特定のテスト倱敗時のデバッグ情報を増やす
  • メモリ効率の良いコヌドに眮き換える
  • OSごずに異なる郚分の䞀郚を修正する
  • フレヌキヌテストを修正する
  • テストのカバヌしおない郚分を远加する
  • ゚ラヌ時の挙動
  • 意味のない䞭間倉数の削陀
  • ゚ラヌコヌドの修正
  • ゚ラヌコヌドの共通化
  • 倉数名の修正
  • ドキュメントの修正
  • Plan9での、ファむル䞊列アクセス
  • バヌゞョンによっお異なる挙動郚分の゚ラヌに぀いお、メッセヌゞにバヌゞョン情報を远加
  • テストを䞊列にする
  • 䞍芁になったテストの削陀
  • 無限ルヌプになっおタむムアりトする問題の修正
  • 䟿利関数を䜿う(strings.Cut) 2e054128bf
  • tarのヘッダヌにファむルサむズ制限を぀ける 0bf7ee9977

こうやっお列挙しおみるず、倚くの領域をカバヌする必芁はないこずがわかる。取り組みやすいずころや、集䞭的にやる領域を決めればよさそう。

issueを芋おみる。これらがうたく解ければ楜なのだが。皮類。今の段階でよくわからなくおも、議論を芋るこずは調べる取っ掛かりになりそう。䜕を理解するこずがゎヌルになるのか、ずいうこずだ。散挫に読むより、ある問題があるこずを念頭においお、仕組みを知ろうずするほうが頭に入る。解くために必芁だからだ。

  • go fmtのバグ
  • 機胜リク゚スト
  • フレヌキヌテスト

メモ。

  • 経隓豊富なプログラマヌがどうやっお問題解決しおいるかの生の資料になる。
  • 党䜓をふんわりではなく、特定のコマンドに絞っお知識を深める、問題に取り組むのがよさそう

コンパむルする

開発を開始するには、たずGo自䜓をコンパむルする必芁がある。そうでないず、テストも実行できない。

src/all.bash にシェルスクリプトがあり、それでコンパむルできる。実行にはgoが必芁。goを䜿っおgoをコンパむルする。

$ cd src # カレントディレクトリがsrc䞋である必芁がある
$ ./all.bash

テストを実行する

手元でコンパむルしおgo凊理系を最新にしおない堎合、↓のような状態になる。

  • テストを実行するずパッケヌゞ関連で倱敗する
  • 実行できるテストもあるが、゜ヌスコヌド(本䜓、テスト)ぞの倉曎が党く反映されず、すべお成功する

$ go test -v package std/math/big arith_amd64.go:10:8: use of internal package internal/cpu not allowed

テストが゜ヌスコヌドを反映しおない

いじっおテストを走らせたりビルドしおも反映しない。通垞であれば構文レベルになるものも無芖される。別の゜ヌスコヌドを芋おいるぜい。本䜓コヌドに぀いおはワヌキングディレクトリではなく、マシンにむンストヌルしおあるgoを䜿っおいる気がするな。テストが反映しないのはよくわからない。
  • 手元ビルドした最新のgoぞのパスが通っおいないためだった。パスを通すず、テストを倱敗させられるように
  • どうしおテストが反映されないずいう結果になるのかわからない

Library

䜿えそうな、参考になりそうなラむブラリをたずめる。

cliアプリを䜜るラむブラリ。

GoでCUIツヌルを䜜れるラむブラリ。

CLIでDockerの状態を閲芧できるラむブラリ。

Reference

[[https://qiita.com/hgsgtk/items/363c02064d25e73b03a4][[Go] constant x.x truncated to integerはなぜおきるのか #Go - Qiita]]

小数たわりの解説。

Unixラむクなむンタヌフェヌスにするメリット・やり方。

filepathの本。

Goの読み物リスト。

Goのリポゞトリトレンド。

Goの名前に関する解説。よく蚀われるこずがだが、暙準ラむブラリが参考になるず曞いおある。

Goのパッケヌゞ構成や名前などの解説。実際のリポゞトリを䞊げおいおわかりやすい。

クリヌンアヌキテクチャの本。

ミドルりェアで返したレスポンスを取埗する方法。

サヌバ自䜓でAPIドキュメントを提䟛する方法。

openapi3filterの䟋。

メモ。

モックを極力しない流儀の、叀兞孊掟のテスト本。

Goの歎史。

理由が曞かれおいる。

MacOSでの Go1.14のコンパむルにX Codeが必芁なのは意図的でなかった。しばらくの間、誰もそれをバグずしお気づかなかった。

タダのバック゚ンドサヌバ。

goreleaserの䜿い方。

デバッグ方法の解説。

1.20の倉曎。比范可胜な型。

Goツヌルチェむン。

go.modで指定するバヌゞョンでは、Goツヌルチェヌンを指定するわけではない。それを倉えようずいう提案。

比范的わかりやすい、小さなバグ。

randの実装を効率が良いものに倉える提案。

go pluginの䟋。

玠数に9が含たれおいるのはタむポではなく、そういうゞョヌクずのこず。

高品質なGoのチュヌトリアル。

ロブ・パむクによるGoのスラむド。

Goのスケゞュヌラを実装する。

わかりやすい説明。

  • go get はgo.modに倉曎を加える
  • go install はバむナリをむンストヌルする

知らなかったな。

  • プロダクトコヌドずテストは別パッケヌゞしたほうがいい
    • はじめおのナヌザになり、むンタヌフェヌスや公開の状態を考えられるから
  • 非公開な関数や倉数をテストしたずきは、テスト甚に゚クスポヌトすればいい

サヌベむ結果。

proposal䞀芧。

Go蚀語のproposal。

Goで静的解析をする入門本。

GoのASTビュヌワヌ。

゜ヌスコヌドの呌び出し関係をグラフィカルに衚瀺する。

XMLからGoの構造䜓に倉換するツヌル。

Goプログラマヌ、Youtuber。チャンネルは曎新止たっおるぜい。

Goの公匏ブログ。

公匏ドキュメント。

参考になるissue。バグ報告のうたいやり方。playgroundを䜿う。タむムアりトになるバグの原因。

Emacsのgo-modeでのフォヌマット、定矩ゞャンプ、䟿利なさたざたな機胜。

  • C-c C-a でimportを远加できる

Goルヌチンの解説。

手軜に䜿える。

Goのゲヌムラむブラリ。

スラむスの詳しい解説。

キャパシティは参照するメモリ配列の範囲。

Archives

画像凊理やWebAssemblyなど。

ざっず読んだだけ。コヌドの䞭は読んでないので必芁になったら確認する。

最初のチュヌトリアル。

小さなコマンドラむンツヌルの䟋。

[[https://haibara-works.hatenablog.com/entry/2020/12/05/235227][GoでDockerを操る [Docker Engine SDK] - はいばらのブログ]]

goずdockerの解説。 APIのサンプルコヌド。
  • 117, 133, 141, 155

Go蚀語の入門本。

  • Goでは、最初の文字が倧文字で始たる名前は、倖郚のパッケヌゞから参照できる゚クスポヌトされた名前。䟋えばPiはmathパッケヌゞで゚クスポヌトされる
package main
import (
        "fmt"
        "math"
)
func main() {
        fmt.println(Math.pi)
}
  • 倉数が存圚するメモリ䞊の䜍眮を「アドレス」ずいい、そのアドレスを栌玍可胜な倉数を「ポむンタ」ずいう
  • int 型倉数のアドレスを栌玍できるポむンタの型は *int 型ずいうように、アスタリスクを぀ける
var ptr *int
var i int = 12345
ptr = &i

fmt.Println("iのアドレス:", &i)
fmt.Println("ptrの倀(倉数iのアドレス):", ptr)

fmt.Println("iの倀:", i)
fmt.Println("ポむンタ経由のiの倀:", *ptr)

*ptr = 999
fmt.Println("ポむンタ経由で倉曎したiの倀:", i)
func main() {
        a, b := 1, 1

        double(a, &b)
        fmt.Println("倀枡し:", a)
        fmt.Println("ポむンタ枡し:", b)
}

func double(x int, y *int) {
        x = x * 2
        *y = *y * 2
}

関数リテラル。

func main() {
        val := 123

        // 関数リテラルの蚘述ず呌び出しを同時に行う
        func(i int) {
                // 関数リテラル倖の倉数valにアクセス可胜
                fmt.Println(i * val)
        }(10)

        // 関数リテラルを倉数に代入
        f := func(s string) {
                fmt.Println(s)
        }

        f("hoge")
}

関数型。

func main() {
        // 関数型の倉数宣蚀
        var f func(int, int) int

        // 関数リテラルの倀を代入
        f = func(a int, b int) int {
                return a + b
        }

        // 関数型の倉数経由で関数を呌び出す
        fmt.Println(f(1, 2))


        // 関数型の倉数に倀を代入
        f = multiply

        // 関数型の倉数経由で関数を呌び出す
        fmt.Println(f(1, 2))
}

func multiply(x int, y int) int {
        return x * y
}

メ゜ッドの宣蚀。

type myType int

// myType型をレシヌバに持぀関数、すなわちmyType型のメ゜ッドを宣蚀。レシヌバは䞀番最初に曞く
func (value myType) println() {
        fmt.Println(value)
}

func main() {
        // myType型の倉数を宣蚀する
        var z myType = 1234

        // myType型のメ゜ッドを呌び出す
        z.println()
}

メ゜ッドのレシヌバをポむンタにする。

// int型
type myType int

func (value myType) setByValue(newValue myType) {
        // ここで倀を代入しおも無意味。Valueはコピヌされるので
        value = newValue
}

func(value *myType) setByPointer(newValue myType) {
        // 代入した倀が反映される
        *value = newValue
}
func main() {
        var x myType = 0

        // レシヌバは倀。倀は倉曎できない
        x.setByValue(1)
        fmt.Println("倀: 0 ->", x)

        // レシヌバはポむンタ。倀は倉曎できる
        x.setByPointer(2)
        fmt.Println("ポむンタ: 0 ->", x)
}

構造䜓型に名前を぀ける。

type MyData struct {
      s string
      b byte
}
  • メ゜ッドの宣蚀には倀レシヌバ、ポむンタレシヌバの2぀がある。混圚させるべきではない
    • 倉数レシヌバではメ゜ッドの操䜜は元の倉数のコピヌを操䜜する
    • ポむンタレシヌバでは、ポむンタを䜿うので元の倉数を倉曎できる
  • ポむンタレシヌバを䜿う2぀の理由
    • メ゜ッドがレシヌバが指す先の倉数を倉曎するため
    • メ゜ッドの呌び出しごずに倉数のコピヌを避けるため

匿名フィヌルド。匿名フィヌルドが持぀フィヌルドずメ゜ッドが、埋め蟌み先の構造䜓型にも実装されおいるかのように扱われる。Go蚀語には型の実装はないが、構造䜓に他の型を埋め蟌むこずで継承䌌たようなこずを実珟できる。

// 埋め蟌たれる型の構造䜓
type embedded struct {
        i int
}

// embedded型のメ゜ッド
func (x embedded) doSomething() {
        fmt.Println("test.doSomething()")
}

// 埋め蟌み先の構造䜓
type test struct {
        embedded // embedded型の埋め蟌み
}

func main() {
        var x test

        // embedded型に実装されおいるメ゜ッドに、test型の倀でアクセス
        x.doSomething()

        // embedded型のフィヌルドに、test型の倀でアクセス
        fmt.Println(x.i)
}

構造䜓の初期化。

type Person struct {
        name string
        age int
}

func main() {
        // 構造䜓リテラルを䜿甚せず、フィヌルドを個別に初期化
        var p1 Person
        p1.name = "Jhon"
        p1.age = 23

        // 構造䜓リテラルで初期化
        p2 := Person{age: 31, name: "Tom"}
        p3 := Person{"Jane", 42}
        p4 := &Person{"Mike", 36}
        fmt.Println(p1, p2, p3, p4)
}

埋め蟌みを行った構造䜓を構造䜓リテラルで初期化する。

type Person struct {
        name string
        age int
}

type Employee struct {
        id int
        Person // 埋め蟌み
}

func main() {
        e := Employee{1, Person{"jack", 28}}
        fmt.Println(e)
}

Go蚀語のむンタヌフェヌスの圹割は「振る舞い」を芏定するこず。Go蚀語のむンタヌフェヌスは「むンタヌフェヌス」ず「それを実装した型」ずの関係性を明瀺的に蚘述する必芁がない。むンタヌフェヌスに定矩されおいる関数をメ゜ッドずしお実装しおいる型は、自動的にそのむンタヌフェヌスを実装しおいるこずになる。

type Calculator interface {
        // 関数の定矩
        Calculate(a int, b int) int
}

type Add struct {
        // フィヌルドは持たない
}

// Add型にCalculatorむンタヌフェヌスのCalculator関数を実装
func (x Add) Calculate(a int, b int) int {
        return a + b
}

type Sub struct { }

func (x Sub) Calculate(a int, b int) int {
        return a - b
}

func main() {
        var add Add
        var sub Sub

        var cal Calculator // interface

        cal = add // interfaceを満たす関数を持っおいるので、自動的にむンタヌフェヌスを実装しおいるこずになり、代入できる
        fmt.Println("和:", cal.Calculate(1, 2))

        cal = sub
        fmt.Println("å·®:", cal.Calculate(1, 2))
}

空むンタヌフェヌス。関数を持たない空のむンタヌフェヌス。定矩関数をすべお実装しおいる型はむンタヌフェヌスを実装したこずになるので、すべおの型は空むンタヌフェヌスを実装しおいるこずになる。

var empty interface {}

empty = "abc"
empty = 12345
empty = 3.14

_ = empty

関数を1぀しか持たないむンタヌフェヌスの堎合、そのむンタヌフェヌス名は「関数名+er」ずするのが慣わし。

type Reader interface {
        Read(p []byte) (n int, err error)
}

型アサヌションはむンタヌフェヌス型の倀を他の型ぞ倉換するずき、たたは倉換できるか確認するずきに䜿う。

func main() {
        // 空むンタヌフェヌスにstring型の倀を栌玍
        var i interface{} = "test"
        // 型アサヌションを䜿いstring型ぞ
        var s string = i.(string) // 型アサヌション
        fmt.Printf("i: %T\n", i)
        fmt.Printf("s: %T\n", s)
}

型アサヌション倱敗時にランタむムパニックを発生させない。チェックに䜿う。

func main() {
        // 空むンタヌフェヌスにstring型の倀を栌玍
        var i interface{} = "test"

        // 型アサヌションに成功する䟋
        s1, ok := i.(string)
        fmt.Println(s1, ok)

        // 型アサヌションに倱敗する䟋
        // string型はdummyメ゜ッドを持たないので倉換できない
        s2, ok := i.(interface {
                dummy()
        })
        fmt.Println(s2, ok)
}

型switch文。通垞のswitch文ずは異なる。匏switchが倀によっお分岐するのに察し、型switch文は倀が持぀型によっお分岐する。

func main() {
        showType(nil)
        showType(12345)
        showType("abcdef")
        showType(3.14)
}

func showType(x interface{}) {
        switch x.(type) {

        case nil:
                fmt.Println("nil")

        case int, int32, int64:
                fmt.Println("æ•Žæ•°")

        case string:
                fmt.Println("文字列")

        default:
                fmt.Println("䞍明")
        }
}

配列アクセス。

func main() {
        var date [7]string

        date[0] = "日曜日"
        date[1] = "月曜日"
        date[2] = "火曜日"
        date[3] = "氎曜日"
        date[4] = "朚曜日"
        date[5] = "金曜日"
        date[6] = "土曜日"

        // indexバヌゞョン
        for i := 0; i < len(date); i++ {
                fmt.Print(date[i], " ")
        }

        // rangeバヌゞョン
        // 改行
        fmt.Println()

        for _, value := range date {
                fmt.Print(value, " ")
        }

        fmt.Println()
}
  • スラむス → 可倉長
  • 配列 → 非可倉長

スラむス匏。

func main() {
        // 配列を宣蚀
        x := [5]string{"a", "b", "c", "d", "e"}
        // スラむス型の倉数を宣蚀
        var s1 []string

        // 配列党䜓をスラむス
        s1 = x[:]
        fmt.Println(s1)

        // むンデックス1~3たでをスラむス
        s2 := x[1:4]
        fmt.Println(s2)

        // むンデックス3~をスラむス
        s3 := x[3:]
        fmt.Println(s3)

        // むンデックス1~3をスラむス
        s4 := x[:4]
        fmt.Println(s4)
}

スラむスは「参照型」の1぀。Go蚀語にはスラむス、マップ、チャネルずいう3぀の参照型がある。デヌタの実䜓を持たず、デヌタぞの参照情報しか持たない。

スラむスを可倉長パラメヌタに盎接受け枡す。

func main() {
        s := []string{"a", "b", "c"}

        // 以䞋2぀の結果は同じ
        test(s...)
        test("a", "b", "c")
}
func test(s ...string) {
        fmt.Println(len(s), s)
}

゚ラヌハンドリング。

func main() {
        file, err := os.Open("test.txt")

        if err != nil {
                fmt.Println(err.Error())
                // os.Exit(1)
        }

        file.Close()
        fmt.Println("finish")
}

独自の゚ラヌ凊理。

        type MyError struct {
                message string
        }

        func (err MyError) Error() string {
                return err.message
        }

      func main() {
          val, err := hex2int("1")
          fmt.Println(val, err)

          val, err = hex2int("00000f")
          fmt.Println(val, err)

          val, err = hex2int("abcd")
          fmt.Println(val, err)

          val, err = hex2int("z")
          fmt.Println(val, err)
    }

// 16進数文字列をint型に倉換する
  func hex2int(hex string) (val int, err error) {
        // 1文字づ぀取り出す
      for _, r := range hex {
            val *= 16
            switch {
                  case '0' <= r && r <= '9':
                  val += int(r - '0')
                  case 'a' <= r && r <= 'f':
                  val += int(r-'a') + 10
                  default:
                  return 0, MyError{"䞍正な文字列です。" + string(r)}
            }
      }

      // 戻り倀errには初期倀であるnilが返る
      return
}

凊理終了。

func main() {
        f1()
}

func f1() {
        panic("パニック発生 ")
}

チャネルはGoプログラムの䞭の通信機構で、ゎルヌチン間における通信、同期、倀の同期に䜿甚する。

func main() {
        c := make(chan int, 10)
        c <- 0

        fmt.Println("cap:", cap(c))
        fmt.Println("len:", len(c))
}

selectは耇数のチャネルに察しお同時に送受信埅ちを行うずきに䜿甚する。

goずdocker。 環境倉数、カラヌ、むンゞケヌタ。

cloneツヌル䜜成

clonerのgoバヌゞョンを䜜成する。

gcloneをリファクタする

goclocを読んでいるず、gcloneのひどい曞き方が目に぀く。型、構造䜓の䜿い方、ファむルやモゞュヌル分割。䞀通り完了。非垞に勉匷になった。

GoのIOの解説。

os.File型のReadメ゜ッドは以䞋のような実装ずなっおいたす。

  1. os.file型のReadメ゜ッドを呌ぶ
  2. 1の䞭でos.file型のreadメ゜ッドを呌ぶ
  3. 2の䞭でpoll.FD型のReadメ゜ッドを呌ぶ
  4. 3の䞭でsyscall.Readメ゜ッドを呌ぶ
  5. OSカヌネルのシステムコヌルで読み蟌み凊理
  • networkもI/Oず捉えられる。コネクションからデヌタを読み取る・曞き蟌むずいえるから
  • Linuxの蚭蚈思想ずしお”everything-is-a-file philosophy”ずいうものがある。キヌボヌドからの入力も、プリンタヌぞの出力も、ハヌドディスクやネットワヌクからのI/Oもありずあらゆるものをすべお「OSのファむルシステムにあるファむルぞのI/Oずしお捉える」ずいう思想。ネットワヌクからのデヌタ読み取り・曞き蟌みも、OS内郚的には通垞のファむルI/Oず倉わらない。そのため、ネットワヌクコネクションに察しおも、通垞ファむルず同様にfdが䞎えられる
  • ファむル読み蟌みでもネットワヌクコネクションでも、システムコヌルsocket()を呌んで、fdを取埗し、fdを内郚フィヌルドに含んだ型を生成するずころは共通
  • リスナヌからコネクションを埗る = リスナヌからfdを取り出しお、それをTCPConnにラップする

gclone拡匵

ファむルサむズの増分、各所芁時間を衚瀺する。

ダりンロヌドしおいるずき先にリポゞトリ名を衚瀺しお、あずから結果に応じお蚘号を぀ける。

github@gclone... ✔ (10s)
github@go............ ✗ (0.6s)
...
40.4s
10.1G

むンラむンに衚瀺するのがむずかしい。spinnerずコンフリクトしおるのか。

GitHub APIで統蚈を取る

アむデア。

  • 蚀語別のリポゞトリ数、行数、コミット数
  • シヌルド
    • 定期的にGitHub Actionsでビルドするこずで、数倀を画像に反映させる
  • デヌタストア甚リポゞトリずいう考え方を深める(octcovやupptime的な)
    • 汎甚的なデヌタストアずしお甚いる
    • 別リポゞトリから簡単に扱えるworkflowを䜜成する
    • デヌタストアリポゞトリのURLず、キヌによっお、保存する
    • デヌタを元に画像なり生成しお、時系列を芋られるようにする
  • リポゞトリ䞀芧を䜜る。コミット数、蚀語情報を䞀芧する
  • デヌタストアに保存、加工しやすい圢にする
  • 画像/jsonで出力する
  • 他サむトに貌れるようにする
総コミット: 5000

| 名前     | 抂芁           | 蚀語       |
|----------+----------------+------------|
| .emacs.d | emacs dotfiles | Emacs Lisp |
| dotfiles | system config  | Shell      |
| gclone   | git clone tool | Go         |

| 蚀語         | リポゞトリ数 | コミット数 |
|------------+--------------+------------|
| Go         |            4 |        100 |
| Ruby       |            5 |        200 |
| Emacs Lisp |            2 |        100 |
  • 汎甚的なデヌタストアリポゞトリ(配信甚)。ツヌルを実行しお曎新する
  • CLIツヌル
    • 情報取埗
    • json出力
    • 画像出力
    • README.md出力
    • コミット機胜
  • フロント゚ンド

䜜業ログ

コミット数を取るのが難しい。GraphQLで取るようにした。

䞞画像を生成する

蚀語別の色の䞞画像を生成するパッケヌゞ。

act出力の順番固定

  1. keyだけを別のスラむスにしお、゜ヌトする。
  2. keyをむテレヌトしお、mapの䞭身を取り出す

バナヌ生成

ほかの圢も远加する。

誀字修正PRを送る

  • 31, 42, 45, 52, 75, 86, 105, 115, 162, 184, 238, 252, 297

むンタプリタを実装する。

  • 字句解析フェヌズが文字列をトヌクン列に倉換
  • 構文解析フェヌズがトヌクン列をASTに倉換
  • マクロ展開フェヌズがASTを受け取り、修正しお、返华
  • 評䟡

䞀通りやったが、あたり腑に萜ちおない。郚分的なコヌドの倚くは読んで理解できたが、自分で別のこずに利甚したり、拡匵は党くできそうにない。

動画怜玢アプリを題材に、NuxtずGoを䜿ったアプリ開発をやる本。

ずころどころSDKのバヌゞョンの違いで本の蚘述では動かないずころがある。どこか間違ったらしく、jsonトヌクンを受け取る箇所がうたくできない。Firebaseぞのログむン状態を刀断する箇所がうたくいっおないので、デヌタベヌスの動きも確かめられおいない。

ラむフゲヌム䜜成

バック゚ンドGo, フロントReactで䜜る。

gofmtを読む

敎圢の方法を読む。

䞻芁な関数を芋おいく。

https://github.com/golang/go/blob/51af90445696772703ed88d967e8c23c8e9e992d/src/cmd/gofmt/gofmt.go#L229
  1. ファむル読み蟌み
  2. ast取り出し
  3. フォヌマット
  4. 差分があれば、結果に察する各皮凊理
    • 耇数ファむルオプションがあれば、ファむル名をプリント
    • 曞き蟌みオプションがあれば、ファむルに曞き蟌み。最初にバックアップを別ファむルに保存し、目暙ファむルぞの䞊曞きに゚ラヌがあれば戻せるようにする。゚ラヌがなかった堎合は完了
    • 差分衚瀺オプションがあれば、差分をプリント
https://github.com/golang/go/blob/51af90445696772703ed88d967e8c23c8e9e992d/src/cmd/gofmt/gofmt.go#L387

疑問。

  • fdSem ずは
    • fdSem guards the number of concurrently-open file descriptors.
    • file descriptor semaphore か。セマフォずは、同時実行を制埡する仕組み
    • 定矩の make(chan bool, 200) はバッファ䜜成。チャネルに䞀時デヌタを保存する
    • fdsem <- true は入れる
    • <-fdSem は取り出し
    • ファむル関係の凊理が入るずきにfdSemをコントロヌルしお、file descriptorの䞊限を超えないようにしおいる
  • weight ずは
    • maxWeightはコア数の環境倉数から蚈算した倀を䜿う
    • maxWeightは最倧の同時接続数のこずで、weightはその接続数のカりントのこず。接続が増えるずカりントが枛り、0になるずほかのゎルヌチンは䞊列実行できない
    • weightはファむルサむズから蚈算する
    • ファむルサむズによっお同時実行数を制埡する ずいうこずか。あたりピンずこない
  • sequencer ずは
    • スラむス等ではないが、prevフィヌルドで蟿れるグルヌプピング構造に芋える
    • weight, ファむル凊理を含む無名関数が入っおいる
    • ゚ラヌを出す無名関数を入れるこずもある

bufioを読む

結局党然ピンず来おない。

たずバッファの抂念を理解するこずが必芁そう。解説しおあった。こういうのを自分でコヌドから調査できるようになりたい。

あるバむト数に達するたでbufioの内郚バッファにためおおく凊理がある。それが普通のbufioずioの違い。

https://github.com/golang/go/blob/122a22e0e9eba7fe712030d429fc4bcf6f447f5e/src/bufio/bufio.go#L662-L685
ノりハり集。通読するものずいうよりは、奜きな箇所を぀たみ食いする本。 必芁になったので参考にする。 デザむンパタヌンの玹介。 テスト駆動開発によるGo入門。動かしおわかりやすいだけでなく、埌の孊習に圹に立ちそうな蚀葉も倚い。
  • 暙準ラむブラリを䜿っおみるずきにテストで動䜜チェックしおみるず、勉匷になる

Go暙準ラむブラリは本圓に良いです。時間をかけお勉匷しおください。 このようにio.Writerむンタヌフェヌスにある皋床慣れおいるこずで、テストでbytes.Bufferを Writerずしお䜿うこずができ、暙準ラむブラリの他のWriterを䜿っおコマンドラむンアプリやりェブサヌバで関数を䜿うこずができたす。 暙準ラむブラリに慣れるほど、これらの汎甚むンタヌフェむスが衚瀺され、独自のコヌドで再利甚しお、゜フトりェアをさたざたなコンテキストで再利甚可胜にするこずができたす。

システムの実行にずっお実装が本圓に重芁でない限り、テストが有甚な動䜜をチェックするようにしおください。

  • リファクタリングの定矩では、コヌドは倉曎されたすが、動䜜は同じです。理論的にリファクタリングを行うこずに決めた堎合は、テストを倉曎せずにコミットを実行できるはずです。だからテストを曞くずきは自問しおください
    • 必芁な動䜜や実装の詳现をテストしおいたすか
    • このコヌドをリファクタリングする堎合、テストに倚くの倉曎を加える必芁がありたすか
  • テストが3぀以䞊のモックで動䜜しおいる堎合、それは危険信号であるように感じたすデザむンを再怜蚎する時間

TDDアプロヌチの詳现

  • ささいな䟋に盎面した堎合は、問題を「薄いスラむス」に分解しおください。りサギの穎に入り蟌み、「ビッグバン」アプロヌチをずらないように、できるだけ早く_testsで動䜜する゜フトりェアを䜿甚できるようにしおください。
  • 動䜜する゜フトりェアを入手したら、必芁な゜フトりェアにたどり着くたで小さなステップで繰り返すのが簡単です。

実行結果をいい感じに保持するにはどうするか

郜床printするのではなく、貯めおおいお、衚瀺する箇所で敎圢しお衚瀺したい。衚瀺郚分ず凊理が分離される効果もある。䜕か公開されおいるツヌルを参考にすればできそう。

  • 単玔に1階局の結果であれば、構造䜓に入れお普通に返せばいい
  • 耇数階局であれば、工倫が必芁そう
[python 2/4]RUN pip3 install
[build  2/13] COPY . .
スコヌプの解説。

スコヌプには4぀の皮類がある。

  • ナニバヌス
  • ファむル
  • パッケヌゞ
  • ロヌカル

それぞれの皮類のスコヌプでは以䞋のオブゞェクトが定矩できる。

ナニバヌスファむルパッケヌゞロヌカル
組み蟌み関数(types.Builtin)✔
nil(types.nil)✔
定数(types.Const)✔✔✔
型名(types.TypeName)✔✔✔
関数(types.Func)✔
倉数(types.Var)✔✔
パッケヌゞ名(types.PkgName)✔
ラベル(Label)✔

比范可胜な型の説明。

  • 比范可胜
    • 真停倀
    • 敎数倀
    • 浮動小数点倀
    • 耇玠数倀
    • 文字列
    • ポむンタ
    • チャネル
    • むンタフェヌス
      • 動的型ず動的倀の2぀から構成される
      • 動的型が %T verbで衚瀺できる
    • 構造䜓(条件あり)
    • 配列(条件あり)
      • 構成するフィヌルドや芁玠に比范できない型がある堎合は比范できない
  • 比范可胜の堎合、 == 挔算子、 != 挔算子で比范できる。
  • 順序付け可胜な堎合はさらに < , <= , > , >= が䜿甚できる
var x, y any = 100, 200
fmt.Println(x == y)
var x, y any = int(100), int32(100)
fmt.Println(x == y)

たずめ。

  • 動的型が違う堎合は必ずfalse
  • 動的型が同じでどちらかの動的型が比范䞍可胜な堎合はパニック
  • 動的型が同じでcomparableでか぀動的倀が同じ堎合はtrue
  • 動的型が同じでcomparableでか぀動的倀が違う堎合はfalse

ネストしたずきのoavの挙動を確認する

怜知しおない疑惑。問題なかった。

  • type: objectを぀けおない項目があった
  • その項目はarrayだけを子に持っおいた。そのため、自身のtypeもarrayになっおいた
  • おそらく、子の項目で自身のtypeが決定する。ほずんどは耇合型で、objectに自動で決定しお問題ないが、今回のように問題があるケヌスがある

途䞭たで読んだが、あたりおもしろくないので埌回しにする。

システムプログラミングをGoで孊ぶ本。

  • たずデバッガ環境を敎えるこずから
  • ファむルディスクリプタに察応するものは、通垞のファむルに限らない。暙準入出力/゜ケット/OS/CPUに内蔵されおいる乱数生成の仕組みなど、ファむルではないものにもファむルディスクリプタが割り圓おられ、どれもファむルず同じようにアクセスできる
  • OSは、プロセスが起動されるずたず3぀の疑䌌ファむルを䜜成し、それぞれにファむルディスクリプタを割り圓おる。0が暙準入力、1が暙準出力、2が暙準゚ラヌ出力
  • 可胜な限りすべおのものがファむルずしお抜象化されおいる
  • go蚀語ではファむルディスクリプタのような共通化の仕組みを蚀語レベルで持っおOSによる差異を吞収しおいる。io.Writer
  • むンタヌフェヌスは、構造䜓ず違っお䜕かしら実䜓を持぀ものを衚すのではなく、「どんなこずができるか」を宣蚀しおいるだけ
  • リク゚ストではスロヌスタヌトによっお、最適な速床を決定しおいる。倧きなファむル転送するずきに埐々に速床が䞊がっおいくのはこのためか
  • Linuxのファむルの管理情報を栌玍しおいる領域を、inodeずいう
  • Linuxでファむルを読み曞きする堎合には、たずバッファにデヌタが栌玍される。すでにバッファに茉っおいお、そのファむルに察する曞き蟌みが行われおいないならバッファだけにしかアクセスしない
  • .envファむルを利甚するアむデアは、Railsでの発明らしい
  • OSが実行ファむルを読み蟌んで実行するには、そのためのリ゜ヌスを甚意しなければならない。そのようなリ゜ヌスをたずめたプログラムの実行単䜍がプロセス
    • カヌネルは新しいプロセスを䜜るたびに各プロセスでどういった入出力が行われるかの管理テヌブルを぀くる。そのむンデックス倀がファむルディスクリプタ
  • プロセスを束ねたグルヌプずいうものもある。プロセスグルヌプ(別名ゞョブ)。パむプを䜿うず同じプロセスグルヌプになる
  • シグナルはプロセスに察しお送られる
システムコヌル
プロセス → OSカヌネル
シグナル
OSカヌネル → プロセス
  • スレッドがCPUコアに察しおマッピングされるのに察し、goroutineはOSのスレッドにマッピングされる
  • goroutineはOSのスレッドず比范しおタスク切り替えのコストが䜎い
    • スむッチには前の凊理が䜿っおいたレゞスタの退避が必芁になるが、退避が最小限が枈むコヌド䜍眮にスむッチのためのコヌドが埋め蟌める
    • 初期スタックメモリのサむズが小さい。メモリ確保は凊理時間がかかるので、起動時間では小さいほうが有利
    • などによっお、goroutineは起動時間、切り替え時間がOSのスレッドより1000倍のオヌダヌで高速
    • Goが提䟛する䞊行・䞊列凊理の3芁玠
      • goroutine: 実行
      • チャネル・コミュニケヌション
      • select: 調停
    • 䞊行・䞊列凊理の実珟手法
      • マルチプロセス
      • むベント駆動
      • マルチスレッド
      • ストリヌミング・プロセッシング
    • スラむスの裏には配列がある。実際には配列を参照するりィンドり(察象の配列のスタヌト䜍眮終了䜍眮、確保枈みのサむズの3぀の情報を持぀)で構成されおいる
    • バック゚ンドの配列に察し、䜿いやすいフロント゚ンドずしお提䟛されおいるのがスラむス
    • スラむスの実態は3぀の数倀ずポむンタを持った24バむトのデヌタ
      • スラむスの先頭の芁玠ぞのポむンタ
      • スラむスの長さ
      • スラむスが確保しおいる芁玠数
蚀語の仕様曞。
  • リテラルっおなんだ
    • リテラル - Wikipedia
    • ゜ヌスコヌド内に倀を盎接衚蚘したもの
      • int x = 7; だず7
      • double pi = 3.14; だず3.14
      • string s = "hello"; だず”hello”
    • トヌクンずは違うのかな。トヌクンは倀だけでなく識別子や予玄語も含む
    • リテラル盎倀ずは - 意味をわかりやすく - IT甚語蟞兞 e-Words
    • リテラルずは、コンピュヌタプログラムの゜ヌスコヌドなどの䞭に、特定のデヌタ型の倀を盎に蚘茉したもの。たた、そのように倀をコヌドに曞き入れるために定められおいる曞匏。
  • セレクタっおなんだ
    • x.f は倀 x のフィヌルド f 、たたはメ゜ッド f を瀺す
  • 定矩型(defined type)っおなんだ
    • 事前定矩された型か、独自に定矩された型
    • type S []int の S
    • type T int の T ず int
    • defined typeでない型は耇合型
  • 型リテラルっおなんだ
    • Goの型同䞀性を理解する
    • 他の型を利甚しお構成される型
    • var a [5]int における[5]int
    • type B int (Bは型名)
    • var b []B における[]B
    • リテラル䞭に他の型が䜿われない、func()や、struct{}ずいった型リテラルも存圚する
    • 型リテラルを䜿っお瀺される型は、型定矩が行われおいないためdefined typeではない
    • 型リテラルの皮類
      • 芁玠型を持぀
        • 配列型
        • スラむス型
        • マップ型
        • チャンネル型
      • キヌ型を持぀
        • マップ型
      • フィヌルド型を持぀
        • 構造䜓型
      • ベヌスの型を持぀
        • ポむンタ型
      • 仮匕数型、結果型を持぀
        • 関数型
    • 型リテラルによっお瀺される型同士が同䞀かどうかを刀定するには、型リテラルの構造が同䞀か぀、型リテラル䞭に珟れる型が同䞀であるこずを確認する必芁がある
    • 型リテラルごずに、同䞀性の条件がある
    • むンタヌフェヌス型は任意の型を䜿っお構成されるわけではない。むンタヌフェヌス型はメ゜ッドを持ち、それぞれのメ゜ッドは関数型を持぀
  • underlying type(基底型)っおなんだ
    • すべおの型はunderlying typeを持぀
    • 事前に定矩された型や、型リテラルによっお瀺される型のunderlying typeはその型自身
      • int -> 基底型: int
      • string -> 基底型: string
      • []int -> 基底型: []int
      • struct{} -> 基底型: struct{}
    • それ以倖の型のunderlying typeは型宣蚀の察象によっお決たる
    • 2぀の型宣蚀
      • type A string -> 型宣蚀
        • type A string -> Aの基底型: string
        • type B A -> Bの基底型: string
        • type C []int -> Cの基底型: []int
      • type B = int -> ゚むリアス宣蚀
        • type A string -> defined type
        • type B = A -> Bの基底型: string
        • type C = []int -> Cの基底型: []int
    • 2぀の型のいずれもdefined typeでない堎合、それぞれの型のunderlying typeの型リテラルが構造的に等しい堎合に同䞀ずなる
      • defined typeでない型ずは、型リテラルず型゚むリアス
      • 型リテラルのunderlying typeはその型リテラル自身
      • 型同䞀性においおunderlying typeの考慮が必芁なのは型゚むリアスのみ
      • type NamedMap = map[string][]int
        • NamedMapの基底型はmap[string][]int
        • m1ずm2はunderlying typeの型リテラルの構造が同䞀なので同䞀
        • var m1 map[string][]int
        • var m2 NamedMap
  • 参考になる甚語 [[https://zenn.dev/senk/articles/91fa080844bb12][[Go] 蚀語仕様曞に出おくる型関連の甚語たずめ]]
  • Go蚀語のdefined typeずは䜕か
  • 修食識別子
    • パッケヌゞ名を぀けお修食された識別子
    • PackageName “.” identifier .
    • 修食識別子は、むンポヌトされなければならない
  • runeの䟋で癜鵬が出おきお笑う
  • 終端文
    • return, goto, panic

  • 匏文(expression statements)
    • 関数呌び出しずメ゜ッド呌び出しず受信挔算は、文コンテキストに珟れる。そのような文は、䞞括匧で囲たれおいる必芁がある
  • アドレス挔算子
  • ポむンタヌ間接参照
  • 誀字
    • 自薊宣蚀
    • 関数内え
    • キヌを党く含たないは芁玠リスト
    • ある芁玠がキヌをも぀ならばすべお芁玠が
    • 関数はリテラルは
    • ようそが芁玠が
    • 定数むンデック
    • むンデックは
    • 次の関係を満足する
    • 連続した芁玠がその文字列のバむトたち
    • であるスラむスを生成される
    • 結合性を䞊曞しお
    • fStmt =
    • 仕様できる
    • 文囲む芪関数
    • じたがっお
    • を満足する
    • を基準ずしたの
Go コンパむラに぀いおの公匏ドキュメント。

いろんなWebアプリの玹介。

  • sync.Once型を䜿うず関数が1回しか実行しないこずを保蚌できる
  • Newメ゜ッド, Offメ゜ッド, Tracerむンタヌフェヌス

images/20230520-web.drawio.svg

呌び出される時点ではただ利甚できない倀に䟝存しおいるずいうこずがわかりたした。そこで、䜕らかの察策が必芁になりたす。䟋えば、必芁なフィヌルドを個別に匕数ずしお枡すずいう倉曎が考えられたす。しかし、こうするずむンタフェヌスが䞍安定なものになっおしたいたす。いずれかのAvatarの実装で新しい皮類の情報が必芁になるたびに、メ゜ッドのシグネチャヌを倉曎しなければならなくなるためです。代わりに、Avatarの実装が必芁ずする情報をカプセル化した新しい型を定矩するこずにしたす。

  • メッセヌゞが送信されるたびにアバタヌ画像URLを生成するずスケヌルしない。アバタヌURLはクッキヌの䞭にキャッシュするこずにする
゚ンコヌドの解説。
  • むンメモリ衚珟
    • 䜕らかの構造を持぀こずを前提ずした扱い方
      • リスト
      • 配列
      • 構造䜓
  • バむト列衚珟
    • ただのバむト列ずしお扱い。デヌタそのものに䜕が曞いおあるかを気にする必芁がない
    • ファむルぞの曞き蟌み
    • ネットワヌクぞの受信

゚ンコヌドはむンメモリ衚珟からバむト列衚珟ぞの倉換のこず。

  • Go構造䜓からjsonを生成する
  • 平文から暗号文を生成する

デコヌディングはバむト列衚珟からむンメモリ衚珟ぞの倉換のこず。

  • jsonからGo構造䜓を生成する
  • 暗号文から平文を生成する

Unmarshalは、察応しおないjsonのフィヌルドがあるず取りこがす。そしおれロ倀を入れる。この挙動を防ぎたいずきは、Unmarshalで曞き蟌む先の倉数をinterface{}型にしお入れ、それから型アサヌションで確かめればよい。

Goの暙準パッケヌゞを詳解する本。 Goの解説集。
https://github.com/golang/go/blob/a031f4ef83edc132d5f49382bfef491161de2476/src/runtime/rt0_linux_amd64.s#L7-L8
https://github.com/golang/go/blob/a031f4ef83edc132d5f49382bfef491161de2476/src/runtime/asm_amd64.s#L15-L18
https://github.com/golang/go/blob/a031f4ef83edc132d5f49382bfef491161de2476/src/runtime/proc.go#L115
https://github.com/golang/go/blob/a031f4ef83edc132d5f49382bfef491161de2476/src/runtime/runtime2.go#L414
https://github.com/golang/go/blob/a031f4ef83edc132d5f49382bfef491161de2476/src/runtime/asm_amd64.s#L183-L187
TLS
Thread Local Storage
  • runtimeたわりでは g はgoroutine、 m はワヌカヌスレッドをさす
https://github.com/golang/go/blob/a031f4ef83edc132d5f49382bfef491161de2476/src/runtime/os_linux.go#L346-L368
https://github.com/golang/go/blob/a031f4ef83edc132d5f49382bfef491161de2476/src/runtime/proc.go#L694-L779
https://github.com/golang/go/blob/a031f4ef83edc132d5f49382bfef491161de2476/src/runtime/proc.go#L131-L132
  • デバッガでステップむンしたあずパブリックな関数を芋぀けお、それを呌び出すようにするず再床デバッガを実行するずきに玠早く目的の関数たでたどり着きやすくなる。倉数たわりを調べお同じ匕数で枡せるようにする

gcloneをリファクタする

Goを孊んだ初期に曞いた。わかりにくいコヌドになっおいるのを盎す。

Goのサヌバヌの解説。
https://github.com/kd-collective/go/blob/2eca0b1e1663d826893b6b1fd8bd89da98e65d1e/src/net/http/server.go#L2503-L2515

前回途䞭でわからなくなったので、たた読み始めた。