Open5

【Go】低レイヤープログラミングメモ

ピン留めされたアイテム
shoetshoet

直近の目的

  • Goのインターフェースのありがたみを確認する
shoetshoet

その構造体があるインターフェースの条件を満たしているかを確認するには、
そのインターフェース型の変数に構造体のポインタを代入する。

main.go
package main

import (
	"io"
	"log"
)

func main() {
	var someFile io.Writer

	df := DummyFile{} // io.Writerを満たした構造体
	someFile = &df    // 代入してチェックする

	someFile.Write([]byte(""))
        // 2023/09/10 14:36:07 DummyFile.Write()
}

type DummyFile struct{}

func (df *DummyFile) Write(p []byte) (n int, err error) {
	log.Println("DummyFile.Write()")
	return 0, nil
}

// このようにポインタを代入してチェックもできる
var _ io.Writer = (*DummyFile)(nil)
shoetshoet

Unixではデータの入出力をファイルディスクリプタで抽象化して、すべてをファイルに入出力するノリでデータを扱っている。
Goではio.Writer/io.Readerインターフェースでこれに似たような概念を実現している。

shoetshoet

いろんな構造体のWriteを実行してみる

main.go
package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"net"
	"os"
	"path"
	"strings"
)

func main() {
	strByte := []byte("hoge\n")

	// ファイル ==============
	out_f, fCloser, err := exampleFileOuter()
	if err != nil {
		log.Fatalf("failed load file outer: %v\n", err)
	}
	defer fCloser()
	someWriter(out_f, strByte) // write

	// 標準出力 =============
	out_std := os.Stdout
	someWriter(out_std, strByte)

	// バッファ =============
	out_buf := &bytes.Buffer{}
	someWriter(out_buf, strByte)

	// strings.Builder ======
	out_s_builder := &strings.Builder{}
	someWriter(out_s_builder, strByte)

	// ネットワーク =========
	out_net_conn, err := net.Dial("tcp", "example.com:80")
	someWriter(out_net_conn, strByte)
}

func someWriter(out io.Writer, some []byte) {
	n, err := out.Write(some)
	if err != nil {
		log.Fatalf("failed write: %v\n", err)
	}
	log.Printf("written : %d", n)
}

func exampleFileOuter() (*os.File, func(), error) {
	filepath := "ex12writer/example_files/example1.txt"
	curdir, err := os.Getwd()
	if err != nil {
		return nil, nil, fmt.Errorf("failed get pwd %v: ", err)
	}

	fp := path.Join(curdir, filepath)
	f, err := os.Create(fp)
	if err != nil {
		return nil, nil, fmt.Errorf("failed create file %v: ", err)
	}
	closer := func() { f.Close() }
	return f, closer, nil
}
shoetshoet

チャンク形式のレスポンスを作成するには

  • Transfer-Encodingヘッダーにchunkdを指定する
  • bodyがサイズ¥r¥nデータ¥r¥nサイズ¥r¥nデータ....¥r¥n0 の形にする
HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked

5
hello
5
world
0