第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) }