Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 14753] ファイルの概要

このコミットは、Go言語の標準ライブラリnetパッケージにおけるファイルディスクリプタ(FD)のポーリングに関するコードの整理を目的としています。具体的には、FreeBSD、NetBSD、OpenBSDという3つのBSD系OS向けにそれぞれ存在していたfd_freebsd.gofd_netbsd.go、``fd_openbsd.goというほぼ同一の内容を持つファイルを、fd_bsd.go`という単一のファイルに統合しています。これにより、コードの重複を排除し、保守性を向上させています。

コミット

commit 7c4183ac2439a48d42ae7491ef47a26dc469b5fd
Author: Dave Cheney <dave@cheney.net>
Date:   Fri Dec 28 21:01:52 2012 +1100

    net: consolidate fd_{free,net,open}bsd.go into fd_bsd.go
    
    These files are identical, so probably pre date // +build.
    
    With a little work, fd_darwin could be merged as well.
    
    R=mikioh.mikioh, jsing, devon.odell, lucio.dere, minux.ma
    CC=golang-dev
    https://golang.org/cl/7004053

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/7c4183ac2439a48d42ae7491ef47a26dc469b5fd

元コミット内容

net: consolidate fd_{free,net,open}bsd.go into fd_bsd.go

These files are identical, so probably pre date // +build.

With a little work, fd_darwin could be merged as well.

R=mikioh.mikioh, jsing, devon.odell, lucio.dere, minux.ma
CC=golang-dev
https://golang.org/cl/7004053

変更の背景

この変更の主な背景は、Go言語のnetパッケージ内に存在するBSD系OS(FreeBSD, NetBSD, OpenBSD)向けのファイルディスクリプタ(FD)ポーリング処理の実装が、それぞれfd_freebsd.gofd_netbsd.gofd_openbsd.goという個別のファイルに分かれていたにもかかわらず、その内容がほぼ同一であったことです。

コミットメッセージにある「probably pre date // +build」という記述は、これらのファイルがGoのビルドタグ(// +buildディレクティブ)が導入される以前、またはその利用が一般的になる以前に作成された可能性を示唆しています。ビルドタグは、特定のOSやアーキテクチャ向けにコードを条件付きでコンパイルするためのGoの機能であり、これを使用することで、複数のOSで共通のロジックを持つファイルを一つにまとめることが可能になります。

この重複は、コードの冗長性を生み出し、バグ修正や機能追加の際に複数のファイルを変更する必要があるため、保守性の低下を招いていました。したがって、これらの同一のファイルをfd_bsd.goという単一のファイルに統合し、ビルドタグを用いて各OSに対応させることで、コードベースを簡潔にし、将来的なメンテナンスを容易にすることが変更の動機となっています。コミットメッセージには、将来的にはfd_darwin.go(macOS向け)も同様に統合できる可能性が示唆されており、さらなるコードベースの整理への意欲が見て取れます。

前提知識の解説

1. ファイルディスクリプタ (File Descriptor, FD)

ファイルディスクリプタは、Unix系オペレーティングシステムにおいて、ファイルやソケット、パイプなどのI/Oリソースを識別するためにカーネルがプロセスに割り当てる非負の整数です。プログラムはFDを通じてこれらのリソースにアクセスし、読み書きなどの操作を行います。ネットワークプログラミングにおいては、ソケットがFDとして扱われ、データの送受信や接続の確立・切断が行われます。

2. kqueue/kevent

kqueuekeventは、BSD系OS(FreeBSD, NetBSD, OpenBSD, macOSなど)で利用される、高性能なイベント通知インターフェースです。これは、ファイルディスクリプタの状態変化(読み込み可能、書き込み可能、エラー発生など)を効率的に監視するための仕組みです。

  • kqueue: イベントキューを作成するためのシステムコールです。これにより、アプリケーションは監視したいイベントのリストをカーネルに登録し、イベントが発生するまで待機することができます。
  • kevent: kqueueにイベントを登録したり、発生したイベントを取得したりするためのシステムコールです。アプリケーションはkeventを使って、監視対象のFDとイベントの種類(例: EVFILT_READで読み込みイベント、EVFILT_WRITEで書き込みイベント)を指定します。イベントが発生すると、keventは発生したイベントの詳細を返します。

kqueue/keventは、多数のFDを同時に効率的に監視できるため、高並行なネットワークサーバーなどのアプリケーションで広く利用されています。LinuxにおけるepollやWindowsにおけるI/O Completion Ports (IOCP) と同種の機能を提供します。

3. Goのビルドタグ (// +build)

Go言語には、ソースコードの特定のセクションを特定の環境でのみコンパイルするための「ビルドタグ」という機能があります。これは、Goソースファイルの先頭に// +build tag_nameのような形式でコメントとして記述されます。

例:

  • // +build linux:Linux環境でのみコンパイルされる。
  • // +build freebsd netbsd openbsd:FreeBSD、NetBSD、OpenBSDのいずれかの環境でコンパイルされる。
  • // +build !windows:Windows以外の環境でコンパイルされる。

この機能により、OS固有のシステムコールやライブラリを使用するコードを、プラットフォームごとに異なるファイルに分離することなく、単一のファイル内で管理することが可能になります。コンパイラはビルド時にこれらのタグを読み取り、現在のターゲット環境に合致するコードのみをコンパイル対象とします。

4. Goの net パッケージ

Go言語の標準ライブラリであるnetパッケージは、ネットワークI/Oプリミティブを提供します。TCP/IP、UDP、Unixドメインソケットなどのネットワークプロトコルを扱うための機能が含まれています。このパッケージは、OSに依存する低レベルのネットワーク操作(ソケットの作成、接続、データの送受信、FDのポーリングなど)を抽象化し、Goプログラムからクロスプラットフォームで利用できるようにしています。内部的には、各OSのシステムコール(Linuxのepoll、BSD系のkqueue、WindowsのIOCPなど)を適切に利用して、効率的なネットワークI/Oを実現しています。

技術的詳細

このコミットの技術的な核心は、Goのビルドタグを活用して、複数のBSD系OS向けのFDポーリングロジックを単一のファイルに統合した点にあります。

  1. ファイルのリネームと削除:

    • src/pkg/net/fd_freebsd.gosrc/pkg/net/fd_bsd.go にリネームされました。これは、FreeBSD固有のファイルから、より汎用的なBSD系OS向けのファイルへと役割が変更されたことを意味します。
    • src/pkg/net/fd_netbsd.gosrc/pkg/net/fd_openbsd.go は完全に削除されました。これは、これらのファイルの内容がリネームされたfd_bsd.goに吸収されたためです。
  2. ビルドタグの追加:

    • 新しくリネームされたsrc/pkg/net/fd_bsd.goファイルの先頭に、以下のビルドタグが追加されました。
      // +build freebsd netbsd openbsd
      
      このタグにより、fd_bsd.goファイルは、GoコンパイラがFreeBSD、NetBSD、OpenBSDのいずれかのターゲットOS向けにビルドを行う場合にのみコンパイル対象となります。これにより、以前は個別のファイルで提供されていた各OS向けのFDポーリングロジックが、この単一のファイルで共通して扱われるようになります。
  3. コードの同一性:

    • コミットメッセージが示唆するように、削除されたfd_netbsd.gofd_openbsd.goの内容は、リネーム前のfd_freebsd.goとほぼ同一でした。この同一性があったからこそ、ビルドタグを導入するだけでコードの統合が可能となりました。これにより、同じロジックが3つのファイルに分散していた状態が解消され、コードの重複が大幅に削減されました。

この変更により、Goのnetパッケージは、BSD系OSにおけるFDポーリングの実装をより効率的かつ保守性の高い形で管理できるようになりました。特定のOSに依存する部分をビルドタグで切り替えることで、コードベース全体の複雑さを軽減し、将来的な機能拡張やバグ修正が容易になります。

コアとなるコードの変更箇所

このコミットにおけるコアとなるコードの変更は、主に以下のファイル操作と、fd_bsd.goへのビルドタグの追加です。

--- a/src/pkg/net/fd_freebsd.go
+++ b/src/pkg/net/fd_bsd.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build freebsd netbsd openbsd
+
 // Waiting for FDs via kqueue/kevent.
 
 package net
diff --git a/src/pkg/net/fd_netbsd.go b/src/pkg/net/fd_netbsd.go
deleted file mode 100644
index 35d84c30ef..0000000000
--- a/src/pkg/net/fd_netbsd.go
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Waiting for FDs via kqueue/kevent.
-
-package net
-
-import (
-	"os"
-	"syscall"
-)
-
-type pollster struct {
-	kq       int
-	eventbuf [10]syscall.Kevent_t
-	events   []syscall.Kevent_t
-
-	// An event buffer for AddFD/DelFD.
-	// Must hold pollServer lock.
-	kbuf [1]syscall.Kevent_t
-}
-
-func newpollster() (p *pollster, err error) {
-	p = new(pollster)
-	if p.kq, err = syscall.Kqueue(); err != nil {
-		return nil, os.NewSyscallError("kqueue", err)
-	}
-	syscall.CloseOnExec(p.kq)
-	p.events = p.eventbuf[0:0]
-	return p, nil
-}
-
-func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
-	// pollServer is locked.
-
-	var kmode int
-	if mode == 'r' {
-		kmode = syscall.EVFILT_READ
-	} else {
-		kmode = syscall.EVFILT_WRITE
-	}
-	ev := &p.kbuf[0]
-	// EV_ADD - add event to kqueue list
-	// EV_ONESHOT - delete the event the first time it triggers
-	flags := syscall.EV_ADD
-	if !repeat {
-		flags |= syscall.EV_ONESHOT
-	}
-	syscall.SetKevent(ev, fd, kmode, flags)
-
-	n, err := syscall.Kevent(p.kq, p.kbuf[:], nil, nil)
-	if err != nil {
-		return false, os.NewSyscallError("kevent", err)
-	}
-	if n != 1 || (ev.Flags&syscall.EV_ERROR) == 0 || int(ev.Ident) != fd || int(ev.Filter) != kmode {
-		return false, os.NewSyscallError("kqueue phase error", err)
-	}
-	if ev.Data != 0 {
-		return false, syscall.Errno(int(ev.Data))
-	}
-	return false, nil
-}
-
-func (p *pollster) DelFD(fd int, mode int) {
-	// pollServer is locked.
-
-	var kmode int
-	if mode == 'r' {
-		kmode = syscall.EVFILT_READ
-	} else {
-		kmode = syscall.EVFILT_WRITE
-	}
-	ev := &p.kbuf[0]
-	// EV_DELETE - delete event from kqueue list
-	syscall.SetKevent(ev, fd, kmode, syscall.EV_DELETE)
-	syscall.Kevent(p.kq, p.kbuf[:], nil, nil)
-}
-
-func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
-	var t *syscall.Timespec
-	for len(p.events) == 0 {
-		if nsec > 0 {
-			if t == nil {
-				t = new(syscall.Timespec)
-			}
-			*t = syscall.NsecToTimespec(nsec)
-		}
-
-		s.Unlock()
-		n, err := syscall.Kevent(p.kq, nil, p.eventbuf[:], t)
-		s.Lock()
-
-		if err != nil {
-			if err == syscall.EINTR {
-				continue
-			}
-			return -1, 0, os.NewSyscallError("kevent", err)
-		}
-		if n == 0 {
-			return -1, 0, nil
-		}
-		p.events = p.eventbuf[:n]
-	}
-	ev := &p.events[0]
-	p.events = p.events[1:]
-	fd = int(ev.Ident)
-	if ev.Filter == syscall.EVFILT_READ {
-		mode = 'r'
-	} else {
-		mode = 'w'
-	}
-	return fd, mode, nil
-}
-
-func (p *pollster) Close() error { return os.NewSyscallError("close", syscall.Close(p.kq)) }
diff --git a/src/pkg/net/fd_openbsd.go b/src/pkg/net/fd_openbsd.go
deleted file mode 100644
index 35d84c30ef..0000000000
--- a/src/pkg/net/fd_openbsd.go
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.\n
-// Waiting for FDs via kqueue/kevent.\n
-\n
-package net\n
-\n
-import (\n
-	"os"\n
-	"syscall"\n
-)\n
-\n
-type pollster struct {\n
-	kq       int\n
-	eventbuf [10]syscall.Kevent_t\n
-	events   []syscall.Kevent_t\n
-\n
-	// An event buffer for AddFD/DelFD.\n
-	// Must hold pollServer lock.\n
-	kbuf [1]syscall.Kevent_t\n
-}\n
-\n
-func newpollster() (p *pollster, err error) {\n
-	p = new(pollster)\n
-	if p.kq, err = syscall.Kqueue(); err != nil {\n
-		return nil, os.NewSyscallError("kqueue", err)\n
-	}\n
-	syscall.CloseOnExec(p.kq)\n
-	p.events = p.eventbuf[0:0]\n
-	return p, nil\n
-}\n
-\n
-func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {\n
-	// pollServer is locked.\n
-\n
-	var kmode int\n
-	if mode == 'r' {\n
-		kmode = syscall.EVFILT_READ\n
-	} else {\n
-		kmode = syscall.EVFILT_WRITE\n
-	}\n
-	ev := &p.kbuf[0]\n
-	// EV_ADD - add event to kqueue list\n
-	// EV_ONESHOT - delete the event the first time it triggers\n
-	flags := syscall.EV_ADD\n
-	if !repeat {\n
-		flags |= syscall.EV_ONESHOT\n
-	}\n
-	syscall.SetKevent(ev, fd, kmode, flags)\n
-\n
-	n, err := syscall.Kevent(p.kq, p.kbuf[:], nil, nil)\n
-	if err != nil {\n
-		return false, os.NewSyscallError("kevent", err)\n
-	}\n
-	if n != 1 || (ev.Flags&syscall.EV_ERROR) == 0 || int(ev.Ident) != fd || int(ev.Filter) != kmode {\n
-		return false, os.NewSyscallError("kqueue phase error", err)\n
-	}\n
-	if ev.Data != 0 {\n
-		return false, syscall.Errno(int(ev.Data))\n
-	}\n
-	return false, nil\n
-}\n
-\n
-func (p *pollster) DelFD(fd int, mode int) {\n
-	// pollServer is locked.\n
-\n
-	var kmode int\n
-	if mode == 'r' {\n
-		kmode = syscall.EVFILT_READ\n
-	} else {\n
-		kmode = syscall.EVFILT_WRITE\n
-	}\n
-	ev := &p.kbuf[0]\n
-	// EV_DELETE - delete event from kqueue list\n
-	syscall.SetKevent(ev, fd, kmode, syscall.EV_DELETE)\n
-	syscall.Kevent(p.kq, p.kbuf[:], nil, nil)\n
-}\n
-\n
-func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {\n
-	var t *syscall.Timespec\n
-	for len(p.events) == 0 {\n
-		if nsec > 0 {\n
-			if t == nil {\n
-				t = new(syscall.Timespec)\n
-			}\n
-			*t = syscall.NsecToTimespec(nsec)\n
-		}\n
-\n
-		s.Unlock()\n
-		n, err := syscall.Kevent(p.kq, nil, p.eventbuf[:], t)\n
-		s.Lock()\n
-\n
-		if err != nil {\n
-			if err == syscall.EINTR {\n
-				continue\n
-			}\n
-			return -1, 0, os.NewSyscallError("kevent", err)\n
-		}\n
-		if n == 0 {\n
-			return -1, 0, nil\n
-		}\n
-		p.events = p.eventbuf[:n]\n
-	}\n
-	ev := &p.events[0]\n
-	p.events = p.events[1:]\n
-	fd = int(ev.Ident)\n
-	if ev.Filter == syscall.EVFILT_READ {\n
-		mode = 'r'\n
-	} else {\n
-		mode = 'w'\n
-	}\n
-	return fd, mode, nil\n
-}\n
-\n
-func (p *pollster) Close() error { return os.NewSyscallError("close", syscall.Close(p.kq)) }\n

この差分は以下の変更を示しています。

  1. src/pkg/net/fd_freebsd.go のリネームと +build タグの追加:

    • src/pkg/net/fd_freebsd.gosrc/pkg/net/fd_bsd.go に名前が変更されました。
    • 新しい fd_bsd.go の2行目と3行目の間に、// +build freebsd netbsd openbsd という行が追加されています。これは、このファイルがFreeBSD、NetBSD、OpenBSDのいずれかのOS向けにビルドされる際にのみコンパイルされることを示します。
  2. src/pkg/net/fd_netbsd.go の削除:

    • このファイルは完全に削除されました。その内容は fd_bsd.go に統合されました。
  3. src/pkg/net/fd_openbsd.go の削除:

    • このファイルも完全に削除されました。その内容は fd_bsd.go に統合されました。

これらの変更により、Goのビルドシステムは、BSD系OS向けにビルドする際に、fd_bsd.goという単一のファイルを使用するようになります。

コアとなるコードの解説

統合されたfd_bsd.go(旧fd_freebsd.gofd_netbsd.gofd_openbsd.go)に含まれるコアとなるコードは、netパッケージがBSD系OS上で非同期I/Oイベントを処理するために使用するpollster構造体とその関連メソッドです。この実装は、kqueue/keventシステムコールを基盤としています。

pollster 構造体

type pollster struct {
	kq       int
	eventbuf [10]syscall.Kevent_t
	events   []syscall.Kevent_t

	// An event buffer for AddFD/DelFD.
	// Must hold pollServer lock.
	kbuf [1]syscall.Kevent_t
}
  • kq: kqueue()システムコールによって作成されたkqueueインスタンスのファイルディスクリプタを保持します。これがイベント監視の中心となります。
  • eventbuf: keventからイベントを受け取るための一時的なバッファです。syscall.Kevent_t型の配列で、最大10個のイベントを一度に受け取ることができます。
  • events: eventbufから読み取られた、処理待ちのイベントを保持するスライスです。
  • kbuf: AddFDDelFDメソッドで単一のイベントをkeventに渡すための一時的なバッファです。pollServerのロックを保持している間に使用されます。

newpollster() 関数

func newpollster() (p *pollster, err error) {
	p = new(pollster)
	if p.kq, err = syscall.Kqueue(); err != nil {
		return nil, os.NewSyscallError("kqueue", err)
	}
	syscall.CloseOnExec(p.kq)
	p.events = p.eventbuf[0:0]
	return p, nil
}

pollsterの新しいインスタンスを初期化します。

  1. syscall.Kqueue()を呼び出して新しいkqueueを作成し、そのFDをp.kqに格納します。
  2. エラーが発生した場合は、os.NewSyscallErrorでラップして返します。
  3. syscall.CloseOnExec(p.kq)を呼び出し、p.kqexecシステムコールで子プロセスに継承されないように設定します。これは、ファイルディスクリプタのリークを防ぐための一般的なプラクティスです。
  4. p.eventsスライスを初期化し、eventbufの先頭を指すようにします。

(p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) メソッド

func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
	// pollServer is locked.

	var kmode int
	if mode == 'r' {
		kmode = syscall.EVFILT_READ
	} else {
		kmode = syscall.EVFILT_WRITE
	}
	ev := &p.kbuf[0]
	// EV_ADD - add event to kqueue list
	// EV_ONESHOT - delete the event the first time it triggers
	flags := syscall.EV_ADD
	if !repeat {
		flags |= syscall.EV_ONESHOT
	}
	syscall.SetKevent(ev, fd, kmode, flags)

	n, err := syscall.Kevent(p.kq, p.kbuf[:], nil, nil)
	if err != nil {
		return false, os.NewSyscallError("kevent", err)
	}
	if n != 1 || (ev.Flags&syscall.EV_ERROR) == 0 || int(ev.Ident) != fd || int(ev.Filter) != kmode {
		return false, os.NewSyscallError("kqueue phase error", err)
	}
	if ev.Data != 0 {
		return false, syscall.Errno(int(ev.Data))
	}
	return false, nil
}

指定されたファイルディスクリプタfdをkqueueに登録し、監視を開始します。

  1. mode('r'または'w')に基づいて、監視するイベントフィルター(syscall.EVFILT_READまたはsyscall.EVFILT_WRITE)を設定します。
  2. syscall.SetKeventを使用して、kbuf内のKevent_t構造体にイベント情報を設定します。
    • EV_ADD: イベントをkqueueに追加します。
    • EV_ONESHOT: repeatfalseの場合、イベントが一度トリガーされたら自動的に削除されるように設定します。
  3. syscall.Keventを呼び出して、設定したイベントをkqueueに登録します。
  4. keventの戻り値とev.Flagsをチェックし、エラーがないか、期待通りのイベントが登録されたかを確認します。

(p *pollster) DelFD(fd int, mode int) メソッド

func (p *pollster) DelFD(fd int, mode int) {
	// pollServer is locked.

	var kmode int
	if mode == 'r' {
		kmode = syscall.EVFILT_READ
	} else {
		kmode = syscall.EVFILT_WRITE
	}
	ev := &p.kbuf[0]
	// EV_DELETE - delete event from kqueue list
	syscall.SetKevent(ev, fd, kmode, syscall.EV_DELETE)
	syscall.Kevent(p.kq, p.kbuf[:], nil, nil)
}

指定されたファイルディスクリプタfdの監視をkqueueから削除します。

  1. AddFDと同様に、modeに基づいてイベントフィルターを設定します。
  2. syscall.SetKeventEV_DELETEフラグを設定し、イベントを削除するように指示します。
  3. syscall.Keventを呼び出して、イベントの削除を実行します。

(p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) メソッド

func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
	var t *syscall.Timespec
	for len(p.events) == 0 {
		if nsec > 0 {
			if t == nil {
				t = new(syscall.Timespec)
			}
			*t = syscall.NsecToTimespec(nsec)
		}

		s.Unlock()
		n, err := syscall.Kevent(p.kq, nil, p.eventbuf[:], t)
		s.Lock()

		if err != nil {
			if err == syscall.EINTR {
				continue
			}
			return -1, 0, os.NewSyscallError("kevent", err)
		}
		if n == 0 {
			return -1, 0, nil
		}
		p.events = p.eventbuf[:n]
	}
	ev := &p.events[0]
	p.events = p.events[1:]
	fd = int(ev.Ident)
	if ev.Filter == syscall.EVFILT_READ {
		mode = 'r'
	} else {
		mode = 'w'
	}
	return fd, mode, nil
}

kqueueからイベントが発生するのを待ち、発生したイベントのFDとモードを返します。

  1. p.eventsに処理待ちのイベントがない場合、ループに入ります。
  2. nsec(タイムアウト時間)が設定されている場合、syscall.Timespec構造体に変換します。
  3. s.Unlock()s.Lock()は、pollServerのロックを一時的に解放し、syscall.Keventの呼び出し中に他のゴルーチンがpollServerにアクセスできるようにします。これは、keventがブロッキングコールであるため、デッドロックを避けるために重要です。
  4. syscall.Keventを呼び出して、kqueueからイベントを取得します。
    • 第2引数にnilを渡すことで、新しいイベントの登録は行わず、既存のイベントの取得のみを行います。
    • 第3引数にp.eventbuf[:]を渡すことで、イベントをこのバッファに書き込ませます。
    • 第4引数にtを渡すことで、タイムアウトを設定します。
  5. keventからの戻り値をチェックし、エラー処理(EINTRの場合は再試行)を行います。
  6. イベントが取得された場合、p.eventsスライスを更新し、取得されたイベントを格納します。
  7. p.eventsから最初のイベントを取り出し、そのFDとモード(読み込みまたは書き込み)を返します。

(p *pollster) Close() error メソッド

func (p *pollster) Close() error { return os.NewSyscallError("close", syscall.Close(p.kq)) }

kqueueのファイルディスクリプタを閉じます。これにより、kqueueに関連付けられたリソースが解放されます。

これらのメソッドは、GoのnetパッケージがBSD系OS上で効率的な非同期ネットワークI/Oを実現するための基盤を提供しています。kqueue/keventの仕組みをGoのインターフェースにマッピングし、ファイルディスクリプタの監視とイベント通知を抽象化しています。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント
  • BSD系OSのmanページ (kqueue(2), kevent(2))
  • Go言語のソースコード (src/pkg/net/)
  • Go言語のビルドタグに関する一般的な情報源 (例: Go言語のブログ記事やチュートリアル)
  • ファイルディスクリプタ、kqueue/keventに関する一般的なOSプログラミングの知識