Goならわかるシステムプログラミング:第2章

第2章。

  • ファイルディスクリプタ・・・OSがカーネルのレイヤーで用意している抽象化の仕組み limits.confでいじるやつ。 0が標準入力 1が標準出力 2が標準エラー出力

  • 構造体が持つべきメソッドを表現するのがインタフェース

package main

import "fmt"

type Talker interface {
    Talk()
}

type Greeter struct {
    name string
}

func (g Greeter) Talk() {
    fmt.Printf("Hello, my name is %s\n", g.name)
}

func main() {
    var talker Talker

    talker = &Greeter{"wozozo"}
    talker.Talk()
}
  • ファイル出力の例
package main

import (
    "os"
)

func main() {
    file, err := os.Create("test.txt")
    if err != nil {
        panic(err)
    }
    file.Write([]byte("os.File example\n"))
    file.Close()
}
  • 画面出力
package main

import "os"

func main() {
    os.Stdout.Write([]byte("os.Stdout example\n"))
}
  • バッファ
package main

import (
    "bytes"
    "fmt"
)

func main() {
    var buffer bytes.Buffer
    buffer.Write([]byte("bytes.Buffer example\n"))
        //buffer.WriteString("bytes.Buffer example\n") これでもOK
    fmt.Println(buffer.String())
}
  • インターネットアクセス
package main

import (
    "net"
    "io"
    "os"
)

func main() {
    conn, err := net.Dial("tcp", "ascii.jp:80")
    if err != nil {
        panic(err)
    }
    io.WriteString(conn, "GET / HTTP1.0\r\nHost: ascii.jp\r\n\r\n")
    io.Copy(os.Stdout, conn)
}
  • httpパッケージを使う方法
package main

import (
    "net"
    "io"
    "os"
    "net/http"
)

func main() {
    conn, err := net.Dial("tcp", "ascii.jp:80")
    if err != nil {
        panic(err)
    }
    req, err := http.NewRequest("GET", "http://ascii.jp", nil)
    if err != nil {
        panic(err)
    }
    req.Write(conn)
    io.Copy(os.Stdout, conn)
}
  • ウェブサーバーからブラウザに対して書き込む
package main

import (
    "net/http"
    "io"
)

func handler(w http.ResponseWriter, r *http.Request) {
    io.WriteString(w, "http.ResponseWriter sample")
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}
  • デコレータ・・・io.Writerを受け取り、書き込まれtデータを加工して別のio.Writerに書き出す 下記の例は1つのWriteでファイルと標準出力両方に書き込んでいる
package main

import (
    "os"
    "io"
)

func main() {
    file, err := os.Create("multiwriter.txt")
    if err != nil {
        panic(err)
    }
    writer := io.MultiWriter(file, os.Stdout)
    io.WriteString(writer, "io.MultiWriter example\n")
}

*gzip圧縮してos.Fileに中継する

package main

import (
    "os"
    "compress/gzip"
    "io"
)

func main() {
    file, err := os.Create("test.txt.gz")
    if err != nil {
        panic(err)
    }
    writer := gzip.NewWriter(file)
    writer.Header.Name = "test.txt"
    io.WriteString(writer, "gzip.Writer example")
    writer.Close()
}
  • バッファをためておいてFlush()で書き込む
package main

import (
    "bufio"
    "os"
)

func main() {
    buffer := bufio.NewWriter(os.Stdout)
    buffer.WriteString("bufio.Writer ")
    buffer.Flush()
    buffer.WriteString("example\n")
    buffer.Flush()
}
  • Fprintf()
package main

import (
    "fmt"
    "os"
    "time"
)

func main() {
    fmt.Fprintf(os.Stdout, "Write with os.Stdout at %v", time.Now())
}
Write with os.Stdout at 2018-07-05 23:07:33.224526589 +0900 JST m=+0.000422627
  • JSONを整形して標準出力に出す
package main

import (
    "encoding/json"
    "os"
)

func main() {
    encoder := json.NewEncoder(os.Stdout)
    encoder.SetIndent("", "   ")
    encoder.Encode(map[string]string {
        "example": "encoding/json",
        "hello": "world",
    })
}

問題

Q2.1: ファイルに対するフォーマット出力

package main

import (
    "os"
    "fmt"
)

func main() {
    file, err := os.Create("test.txt")
    if err != nil {
        panic(err)
    }
    d := 1
    s := "s"
    f := 0.2
    fmt.Fprintf(file, "%d, %s, %f", d, s, f)
    file.Close()
}

Q2.2: CSV出力

package main

import (
    "os"
    "encoding/csv"
)

func main() {
    file, err := os.Create("test.csv")
    if err != nil {
        panic(err)
    }
    writer := csv.NewWriter(file)
    writer.Write([]string{"apple", "orange", "lemon"})
    writer.Write([]string{"red", "orange", "yellow"})
    writer.Flush()
    file.Close()
}

Q2.3 gzipされたJSON出力をしながら、標準出力にログを出力

package main

import (
    "net/http"
    "encoding/json"
    "io"
    "compress/gzip"
    "os"
)

func handler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Encoding", "gzip")
    w.Header().Set("Content-Type", "application/json")
    source := map[string]string {
        "Hello": "World",
    }

    gzipWriter := gzip.NewWriter(w)
    encoder := json.NewEncoder(io.MultiWriter(gzipWriter, os.Stdout))
    encoder.SetIndent("", "   ")
    encoder.Encode(source)
    gzipWriter.Close()
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}

Goならわかるシステムプログラミング:第1章

Goならわかるシステムプログラミング

Goならわかるシステムプログラミング

ライブラリで借りた。 ちょうどGoと、インフラレイヤーの知識をあらためてつけたいという希望がいっぺんに満たせそうなので取り組んでいく。

第1章

GoとVisual Studio Codeの設定、delveを使ったデバッガーを使用してみるところまで。 Visual StudioのKeybindに慣れなかったが、プラグインIntelliJのKeybindというのがあってそれをいれたらいっきに楽になった。

package main

import (
    "fmt"
)

func main() {
    fmt.Println("Hello, World!") // ここにブレークポイント
}

図解・ベイズ統計「超」入門 あいまいなデータから未来を予測する技術

読んだ。 基礎がわかってないのでこういう本を他にも読んでいきたい

アドホックなScalaコードを実行したいときにAmmonite REPL

よく使うし便利なのでメモ

Ammonite

インストールしたら、ammで起動できる。

ᐅ amm 
Loading...
Compiling (synthetic)/ammonite/predef/interpBridge.sc
Compiling (synthetic)/ammonite/predef/replBridge.sc
Compiling (synthetic)/ammonite/predef/DefaultPredef.sc
Welcome to the Ammonite Repl 1.1.0
(Scala 2.12.4 Java 1.8.0_152)
If you like Ammonite, please support our development at www.patreon.com/lihaoyi

例えば、cats-coreをその場で読み込む

@ import $ivy.`org.typelevel::cats-core:1.0.0`
https://repo1.maven.org/maven2/org/typelevel/cats-core_2.12/1.0.0/cats-core_2.1…
  100.0% [##########] 4.6 KiB (7.4 KiB / s)
https://repo1.maven.org/maven2/org/typelevel/cats-macros_2.12/1.0.0/cats-macros…
  100.0% [##########] 4.1 KiB (9.7 KiB / s)
https://repo1.maven.org/maven2/org/typelevel/cats-kernel_2.12/1.0.0/cats-kernel…
  100.0% [##########] 3.9 KiB (9.0 KiB / s)
https://repo1.maven.org/maven2/org/typelevel/machinist_2.12/0.6.2/machinist_2.1…
  100.0% [##########] 1.7 KiB (3.9 KiB / s)
https://repo1.maven.org/maven2/org/scala-lang/scala-reflect/2.12.0/scala-reflec…
  100.0% [##########] 1.8 KiB (15.0 KiB / s)
https://repo1.maven.org/maven2/org/typelevel/cats-macros_2.12/1.0.0/cats-macros…
  100.0% [##########] 6.0 KiB (46.9 KiB / s)
https://repo1.maven.org/maven2/org/typelevel/machinist_2.12/0.6.2/machinist_2.1…
  100.0% [##########] 32.9 KiB (124.9 KiB / s)
https://repo1.maven.org/maven2/org/scala-lang/scala-reflect/2.12.0/scala-reflec…
  100.0% [##########] 3.4 MiB (2.2 MiB / s)
https://repo1.maven.org/maven2/org/typelevel/cats-core_2.12/1.0.0/cats-core_2.1…
  100.0% [##########] 3.7 MiB (2.1 MiB / s)
https://repo1.maven.org/maven2/org/typelevel/cats-kernel_2.12/1.0.0/cats-kernel…
  100.0% [##########] 3.0 MiB (1.6 MiB / s)
https://repo1.maven.org/maven2/org/typelevel/cats-macros_2.12/1.0.0/cats-macros…
  100.0% [##########] 1.1 KiB (9.4 KiB / s)
https://repo1.maven.org/maven2/org/typelevel/machinist_2.12/0.6.2/machinist_2.1…
  100.0% [##########] 3.5 KiB (29.6 KiB / s)
https://repo1.maven.org/maven2/org/typelevel/cats-kernel_2.12/1.0.0/cats-kernel…
  100.0% [##########] 42.8 KiB (133.9 KiB / s)
https://repo1.maven.org/maven2/org/scala-lang/scala-reflect/2.12.0/scala-reflec…
  100.0% [##########] 557.8 KiB (718.8 KiB / s)
https://repo1.maven.org/maven2/org/typelevel/cats-core_2.12/1.0.0/cats-core_2.1…
  100.0% [##########] 190.4 KiB (210.6 KiB / s)
import $ivy.$
@ import cats.Eval
import cats.Eval

@ def factorial(n: BigInt): Eval[BigInt] =
    if(n == 1) {
      Eval.now(n)
    } else {
      factorial(n - 1).map(_ * n)
    }
defined function factorial

単にscalaコマンドでREPLすると外部ライブラリ読み込めないしsbt console使うのもtoo muchなときに使っている。