[インデックス 19594] ファイルの概要
このコミットは、Go言語の syscall
パッケージにおけるソケットオプション関連の関数を、Unix系システム全体で統合し、簡素化することを目的としています。具体的には、プラットフォーム固有のファイル(syscall_bsd.go
、syscall_linux.go
)に分散していた Getsockopt*
関数群を syscall_unix.go
に集約し、APIの統一とコードの重複排除を図っています。また、Getsockopt*
および Setsockopt*
関数の戻り値の型をGoの慣習に沿って簡素化し、Solarisを含むUnix系システムでの共通ソケットオプション関数の利用を促進しています。
コミット
syscall: consolidate, simplify socket options for Unix-like systems
Also exposes common socket option functions on Solaris.
Update #7174
Update #7175
LGTM=aram
R=golang-codereviews, aram
CC=golang-codereviews
https://golang.org/cl/107280044
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/e3e48cd075091d8f0e1265ae6a18e69ac83d2af4
元コミット内容
commit e3e48cd075091d8f0e1265ae6a18e69ac83d2af4
Author: Mikio Hara <mikioh.mikioh@gmail.com>
Date: Mon Jun 23 18:46:01 2014 +0900
syscall: consolidate, simplify socket options for Unix-like systems
Also exposes common socket option functions on Solaris.
Update #7174
Update #7175
LGTM=aram
R=golang-codereviews, aram
CC=golang-codereviews
https://golang.org/cl/107280044
---
src/pkg/syscall/syscall_bsd.go | 42 -----------------------
src/pkg/syscall/syscall_linux.go | 34 ------------------
src/pkg/syscall/syscall_unix.go | 74 +++++++++++++++++++++++++++++++---------
3 files changed, 58 insertions(+), 92 deletions(-)
diff --git a/src/pkg/syscall/syscall_bsd.go b/src/pkg/syscall/syscall_bsd.go
index af563910b1..c569b1900b 100644
--- a/src/pkg/syscall/syscall_bsd.go
+++ b/src/pkg/syscall/syscall_bsd.go
@@ -309,48 +309,6 @@ func Getsockname(fd int) (sa Sockaddr, err error) {
}\n \n //sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error)\n-\n-func GetsockoptByte(fd, level, opt int) (value byte, err error) {\n-\tvar n byte\n-\tvallen := _Socklen(1)\n-\terr = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)\n-\treturn n, err\n-}\n-\n-func GetsockoptInet4Addr(fd, level, opt int) (value [4]byte, err error) {\n-\tvallen := _Socklen(4)\n-\terr = getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen)\n-\treturn value, err\n-}\n-\n-func GetsockoptIPMreq(fd, level, opt int) (*IPMreq, error) {\n-\tvar value IPMreq\n-\tvallen := _Socklen(SizeofIPMreq)\n-\terr := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)\n-\treturn &value, err\n-}\n-\n-func GetsockoptIPv6Mreq(fd, level, opt int) (*IPv6Mreq, error) {\n-\tvar value IPv6Mreq\n-\tvallen := _Socklen(SizeofIPv6Mreq)\n-\terr = getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)\n-\treturn &value, err\n-}\n-\n-func GetsockoptIPv6MTUInfo(fd, level, opt int) (*IPv6MTUInfo, error) {\n-\tvar value IPv6MTUInfo\n-\tvallen := _Socklen(SizeofIPv6MTUInfo)\n-\terr = getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)\n-\treturn &value, err\n-}\n-\n-func GetsockoptICMPv6Filter(fd, level, opt int) (*ICMPv6Filter, error) {\n-\tvar value ICMPv6Filter\n-\tvallen := _Socklen(SizeofICMPv6Filter)\n-\terr = getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)\n-\treturn &value, err\n-}\n-\n //sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error)\n //sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error)\n //sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error)\ndiff --git a/src/pkg/syscall/syscall_linux.go b/src/pkg/syscall/syscall_linux.go
index fa0d7ea3c7..cdba97d2e7 100644
--- a/src/pkg/syscall/syscall_linux.go
+++ b/src/pkg/syscall/syscall_linux.go
@@ -440,19 +440,6 @@ func Getsockname(fd int) (sa Sockaddr, err error) {
return anyToSockaddr(&rsa)\n }\n \n-func GetsockoptInet4Addr(fd, level, opt int) (value [4]byte, err error) {\n-\tvallen := _Socklen(4)\n-\terr = getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen)\n-\treturn value, err\n-}\n-\n-func GetsockoptIPMreq(fd, level, opt int) (*IPMreq, error) {\n-\tvar value IPMreq\n-\tvallen := _Socklen(SizeofIPMreq)\n-\terr = getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)\n-\treturn &value, err\n-}\n-\n func GetsockoptIPMreqn(fd, level, opt int) (*IPMreqn, error) {\n \tvar value IPMreqn\n \tvallen := _Socklen(SizeofIPMreqn)\n@@ -460,27 +447,6 @@ func GetsockoptIPMreqn(fd, level, opt int) (*IPMreqn, error) {\n \treturn &value, err\n }\n \n-func GetsockoptIPv6Mreq(fd, level, opt int) (*IPv6Mreq, error) {\n-\tvar value IPv6Mreq\n-\tvallen := _Socklen(SizeofIPv6Mreq)\n-\terr = getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)\n-\treturn &value, err\n-}\n-\n-func GetsockoptIPv6MTUInfo(fd, level, opt int) (*IPv6MTUInfo, error) {\n-\tvar value IPv6MTUInfo\n-\tvallen := _Socklen(SizeofIPv6MTUInfo)\n-\terr = getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)\n-\treturn &value, err\n-}\n-\n-func GetsockoptICMPv6Filter(fd, level, opt int) (*ICMPv6Filter, error) {\n-\tvar value ICMPv6Filter\n-\tvallen := _Socklen(SizeofICMPv6Filter)\n-\terr = getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)\n-\treturn &value, err\n-}\n-\n func GetsockoptUcred(fd, level, opt int) (*Ucred, error) {\n \tvar value Ucred\n \tvallen := _Socklen(SizeofUcred)\ndiff --git a/src/pkg/syscall/syscall_unix.go b/src/pkg/syscall/syscall_unix.go
index b28891568d..699a8fd120 100644
--- a/src/pkg/syscall/syscall_unix.go
+++ b/src/pkg/syscall/syscall_unix.go
@@ -207,13 +207,6 @@ func Getpeername(fd int) (sa Sockaddr, err error) {\n \treturn anyToSockaddr(&rsa)\n }\n \n-func GetsockoptInt(fd, level, opt int) (value int, err error) {\n-\tvar n int32\n-\tvallen := _Socklen(4)\n-\terr = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)\n-\treturn int(n), err\n-}\n-\n func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {\n \tvar rsa RawSockaddrAny\n \tvar len _Socklen = SizeofSockaddrAny\n@@ -234,24 +227,73 @@ func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) {\n \treturn sendto(fd, p, flags, ptr, n)\n }\n \n-func SetsockoptByte(fd, level, opt int, value byte) (err error) {\n+func GetsockoptByte(fd, level, opt int) (byte, error) {\n+\tvar v byte\n+\tl := _Socklen(1)\n+\terr := getsockopt(fd, level, opt, unsafe.Pointer(&v), &l)\n+\treturn v, err\n+}\n+\n+func GetsockoptInt(fd, level, opt int) (int, error) {\n+\tvar v int32\n+\tl := _Socklen(4)\n+\terr := getsockopt(fd, level, opt, unsafe.Pointer(&v), &l)\n+\treturn int(v), err\n+}\n+\n+func GetsockoptInet4Addr(fd, level, opt int) ([4]byte, error) {\n+\tvar v [4]byte\n+\tl := _Socklen(4)\n+\terr := getsockopt(fd, level, opt, unsafe.Pointer(&v[0]), &l)\n+\treturn v, err\n+}\n+\n+func GetsockoptIPMreq(fd, level, opt int) (*IPMreq, error) {\n+\tvar v IPMreq\n+\tl := _Socklen(SizeofIPMreq)\n+\terr := getsockopt(fd, level, opt, unsafe.Pointer(&v), &l)\n+\treturn &v, err\n+}\n+\n+func GetsockoptIPv6Mreq(fd, level, opt int) (*IPv6Mreq, error) {\n+\tvar v IPv6Mreq\n+\tl := _Socklen(SizeofIPv6Mreq)\n+\terr := getsockopt(fd, level, opt, unsafe.Pointer(&v), &l)\n+\treturn &v, err\n+}\n+\n+func GetsockoptIPv6MTUInfo(fd, level, opt int) (*IPv6MTUInfo, error) {\n+\tvar v IPv6MTUInfo\n+\tl := _Socklen(SizeofIPv6MTUInfo)\n+\terr := getsockopt(fd, level, opt, unsafe.Pointer(&v), &l)\n+\treturn &v, err\n+}\n+\n+func GetsockoptICMPv6Filter(fd, level, opt int) (*ICMPv6Filter, error) {\n+\tvar v ICMPv6Filter\n+\tl := _Socklen(SizeofICMPv6Filter)\n+\terr := getsockopt(fd, level, opt, unsafe.Pointer(&v), &l)\n+\treturn &v, err\n+}\n+\n+func SetsockoptByte(fd, level, opt int, value byte) error {\n \treturn setsockopt(fd, level, opt, unsafe.Pointer(&value), 1)\n }\n \n-func SetsockoptInt(fd, level, opt int, value int) (err error) {\n-\tvar n = int32(value)\n+func SetsockoptInt(fd, level, opt int, value int) error {\n+\tn := int32(value)\n \treturn setsockopt(fd, level, opt, unsafe.Pointer(&n), 4)\n }\n \n-func SetsockoptInet4Addr(fd, level, opt int, value [4]byte) (err error) {\n+func SetsockoptInet4Addr(fd, level, opt int, value [4]byte) error {\n \treturn setsockopt(fd, level, opt, unsafe.Pointer(&value[0]), 4)\n }\n \n-func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (err error) {\n+func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) error {\n \treturn setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPMreq)\n }\n \n-func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (err error) {\n+func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) error {\n \treturn setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPv6Mreq)\n }\n \n@@ -259,15 +301,15 @@ func SetsockoptICMPv6Filter(fd, level, opt int, filter *ICMPv6Filter) error {\n \treturn setsockopt(fd, level, opt, unsafe.Pointer(filter), SizeofICMPv6Filter)\n }\n \n-func SetsockoptLinger(fd, level, opt int, l *Linger) (err error) {\n+func SetsockoptLinger(fd, level, opt int, l *Linger) error {\n \treturn setsockopt(fd, level, opt, unsafe.Pointer(l), SizeofLinger)\n }\n \n-func SetsockoptString(fd, level, opt int, s string) (err error) {\n+func SetsockoptString(fd, level, opt int, s string) error {\n \treturn setsockopt(fd, level, opt, unsafe.Pointer(&[]byte(s)[0]), uintptr(len(s)))\n }\n \n-func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (err error) {\n+func SetsockoptTimeval(fd, level, opt int, tv *Timeval) error {\n \treturn setsockopt(fd, level, opt, unsafe.Pointer(tv), unsafe.Sizeof(*tv))\n }\n \n```
## 変更の背景
このコミットの主な背景は、Go言語の `syscall` パッケージにおけるソケットオプション関連のコードの重複を解消し、APIの一貫性と保守性を向上させることにあります。
Goの `syscall` パッケージは、OSのシステムコールをGoプログラムから直接呼び出すための低レベルなインターフェースを提供します。ソケットオプションの取得(`getsockopt`)と設定(`setsockopt`)は、ネットワークプログラミングにおいて非常に頻繁に利用される機能ですが、Goの初期の実装では、これらの関数が各Unix系OS(BSD、Linuxなど)のプラットフォーム固有のファイルに個別に定義されていました。
これにより、以下のような問題が生じていました。
1. **コードの重複**: 多くの `Getsockopt*` 関数が、異なるプラットフォーム間でほぼ同じロジックを持ちながら、それぞれのファイルにコピーされていました。これはコードの肥大化と保守の複雑化を招きます。
2. **APIの不統一**: 各プラットフォームで同じ機能を提供する関数であっても、定義されているファイルが異なるため、開発者が一貫した方法でソケットオプションを扱うことが困難になる可能性がありました。
3. **Solarisサポートの不足**: コミットメッセージに「Also exposes common socket option functions on Solaris」とあるように、Solaris環境ではこれらの共通ソケットオプション関数が十分に利用できていなかった可能性があります。
このコミットは、これらの問題を解決するために、共通のソケットオプション関数を `syscall_unix.go` という共通のファイルに集約し、プラットフォーム固有のファイルからはそれらを削除することで、コードベースを整理し、より簡潔で一貫性のあるAPIを提供することを目指しました。また、`Getsockopt*` および `Setsockopt*` 関数の戻り値の型をGoの慣習に合わせた形に簡素化することで、APIの使いやすさも向上させています。
コミットメッセージに記載されている `#7174` と `#7175` というIssueは、この変更に関連する具体的な課題や改善要求を示唆していますが、GoのIssueトラッカーのシステム変更などにより、直接的な参照は困難でした。しかし、コードレビューのタイトルから、ソケットオプションの統合と簡素化が主要な目的であったことが確認できます。
## 前提知識の解説
このコミットの変更内容を理解するためには、以下の前提知識が役立ちます。
### 1. Go言語の `syscall` パッケージ
`syscall` パッケージは、Goプログラムからオペレーティングシステム(OS)のシステムコールを直接呼び出すための低レベルなインターフェースを提供します。これにより、ファイル操作、ネットワーク通信、プロセス管理など、OSが提供する基本的な機能にアクセスできます。通常、Goの標準ライブラリはより高レベルな抽象化を提供しますが、`syscall` パッケージは、OS固有の機能やパフォーマンスが重要な場面で利用されます。
### 2. ソケットオプション (`getsockopt`, `setsockopt`)
ネットワークプログラミングにおいて、ソケットはネットワーク通信のエンドポイントです。ソケットの挙動は、様々な「ソケットオプション」によって制御されます。
* **`getsockopt`**: ソケットの現在のオプション設定を取得するためのシステムコールです。例えば、ソケットの送受信バッファサイズ、タイムアウト設定、再利用設定などを取得できます。
* **`setsockopt`**: ソケットのオプション設定を変更するためのシステムコールです。例えば、ソケットをブロードキャストモードにする、キープアライブを有効にする、TCP_NODELAYを設定するなど、ソケットの動作を細かく調整するために使用されます。
これらのシステムコールは、通常、ファイルディスクリプタ(ソケットを識別する整数値)、オプションのレベル(例: `SOL_SOCKET` はソケットレベルのオプション、`IPPROTO_TCP` はTCPプロトコルレベルのオプション)、オプション名(例: `SO_REUSEADDR` はアドレス再利用を許可するオプション)、そしてオプションの値へのポインタとそのサイズを引数に取ります。
### 3. Unix系システム
Unix系システムとは、Unixオペレーティングシステムの設計思想や機能セットを共有するOSの総称です。これには、Linux、BSD(FreeBSD、OpenBSD、NetBSDなど)、Solaris、macOSなどが含まれます。これらのシステムは、多くの場合、共通のシステムコールインターフェース(POSIX標準など)を共有しており、`getsockopt` や `setsockopt` のような基本的なネットワークシステムコールも同様の振る舞いをします。しかし、細部の実装や利用可能なオプション、構造体の定義などが異なる場合があります。
### 4. `unsafe.Pointer`
Go言語は通常、厳格な型安全性を提供しますが、`unsafe` パッケージは、その型安全性をバイパスする機能を提供します。`unsafe.Pointer` は、任意の型のポインタを保持できる特殊なポインタ型です。これは、Goのメモリモデルを直接操作したり、C言語のライブラリやシステムコールと連携したりする際に必要となることがあります。`getsockopt` や `setsockopt` のようなシステムコールは、C言語のインターフェースを模倣しているため、Goの構造体や変数のアドレスを `unsafe.Pointer` を介して渡すことで、OSのAPIが期待する形式に合わせます。
### 5. `_Socklen`
`_Socklen` は、ソケットオプションのサイズやアドレス構造体の長さを表すために使用される型です。これは、`getsockopt` や `setsockopt` システムコールに渡される引数の一つで、オプションの値が格納されるバッファのサイズを示します。
### 6. ネットワーク関連の構造体
コミットで変更されている関数名や削除されているコードから、以下のようなネットワーク関連の構造体がソケットオプションとして扱われていることがわかります。
* **`IPMreq` (IP Multicast Request)**: IPマルチキャストグループに参加または脱退するための構造体。
* **`IPv6Mreq` (IPv6 Multicast Request)**: IPv6マルチキャストグループに参加または脱退するための構造体。
* **`IPv6MTUInfo` (IPv6 Maximum Transmission Unit Information)**: IPv6のパスMTU(最大転送単位)に関する情報を含む構造体。
* **`ICMPv6Filter` (ICMPv6 Filter)**: ICMPv6メッセージのフィルタリングルールを設定するための構造体。
* **`Linger`**: ソケットのクローズ時の挙動(未送信データの扱いなど)を制御するための構造体。
* **`Timeval`**: 時間値を表す構造体で、ソケットのタイムアウト設定などに使用されます。
これらの構造体は、特定のソケットオプションの値を表現するために使用され、`getsockopt` や `setsockopt` を通じてOSとやり取りされます。
## 技術的詳細
このコミットにおける技術的な変更は、主に以下の3つの側面に集約されます。
### 1. ソケットオプション関数の統合とコードの重複排除
最も顕著な変更は、`Getsockopt*` 関数群の定義場所の変更です。変更前は、`GetsockoptByte`, `GetsockoptInet4Addr`, `GetsockoptIPMreq` など、様々な型のソケットオプションを取得する関数が、`src/pkg/syscall/syscall_bsd.go` と `src/pkg/syscall/syscall_linux.go` の両方に個別に存在していました。これらの関数は、内部的にはほとんど同じ `getsockopt` システムコールを呼び出し、戻り値の型と `unsafe.Pointer` を介して渡すデータのサイズが異なるだけでした。
このコミットでは、これらの重複する定義を削除し、`src/pkg/syscall/syscall_unix.go` に一元化しました。`syscall_unix.go` は、Unix系OS全般に共通するシステムコールやユーティリティ関数を定義するファイルであり、ここに集約することで、コードの重複を大幅に削減し、保守性を向上させています。これにより、将来的に新しいUnix系OSをサポートする際や、既存のソケットオプション関数に修正を加える際に、複数のファイルを変更する必要がなくなります。
### 2. APIの簡素化とGoの慣習への適合
`Getsockopt*` および `Setsockopt*` 関数の戻り値の型が簡素化されました。
**変更前(例: `GetsockoptByte`):**
```go
func GetsockoptByte(fd, level, opt int) (value byte, err error) {
var n byte
vallen := _Socklen(1)
err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)
return n, err
}
この形式では、戻り値として value byte
と err error
を明示的に名前付きで宣言し、関数内で n
に値を代入してから return n, err
としています。
変更後(例: GetsockoptByte
):
func GetsockoptByte(fd, level, opt int) (byte, error) {
var v byte
l := _Socklen(1)
err := getsockopt(fd, level, opt, unsafe.Pointer(&v), &l)
return v, err
}
変更後では、戻り値の型を (byte, error)
のように直接指定し、関数内で v
に値を代入した後、return v, err
としています。これはGo言語における一般的な関数の戻り値の書き方であり、コードの可読性を向上させ、よりGoらしい(idiomatic Go)コードになっています。
同様に、Setsockopt*
関数も (err error)
から error
へと戻り値の型が簡素化されています。
変更前(例: SetsockoptByte
):
func SetsockoptByte(fd, level, opt int, value byte) (err error) {
return setsockopt(fd, level, opt, unsafe.Pointer(&value), 1)
}
変更後(例: SetsockoptByte
):
func SetsockoptByte(fd, level, opt int, value byte) error {
return setsockopt(fd, level, opt, unsafe.Pointer(&value), 1)
}
これもまた、Goの慣習に沿った簡潔な記述です。
3. Solaris環境での共通ソケットオプション関数の公開
コミットメッセージに「Also exposes common socket option functions on Solaris.」とあるように、この変更はSolaris環境においても、統合された共通のソケットオプション関数が利用可能になることを意味します。syscall_unix.go
に関数が集約されたことで、Solarisを含むすべてのUnix系システムが、これらの共通APIを利用できるようになり、プラットフォーム間の互換性が向上します。これは、Goがより多くのプラットフォームで一貫した動作を提供するための重要なステップです。
unsafe.Pointer
の継続的な利用
これらの変更後も、getsockopt
および setsockopt
システムコールを呼び出す際には、引き続き unsafe.Pointer
が使用されています。これは、Goの型システムとC言語ベースのシステムコールインターフェースとの間の橋渡しをするために不可欠です。unsafe.Pointer
を使用することで、Goの変数や構造体のアドレスを、システムコールが期待する汎用ポインタとして渡すことが可能になります。このコミットは unsafe.Pointer
の利用方法を変更するものではなく、その利用を前提としたAPIの整理と簡素化を行っています。
コアとなるコードの変更箇所
このコミットでは、主に以下の3つのファイルが変更されています。
-
src/pkg/syscall/syscall_bsd.go
:GetsockoptByte
GetsockoptInet4Addr
GetsockoptIPMreq
GetsockoptIPv6Mreq
GetsockoptIPv6MTUInfo
GetsockoptICMPv6Filter
上記のGetsockopt*
関数がすべて削除されています。
-
src/pkg/syscall/syscall_linux.go
:GetsockoptInet4Addr
GetsockoptIPMreq
GetsockoptIPv6Mreq
GetsockoptIPv6MTUInfo
GetsockoptICMPv6Filter
上記のGetsockopt*
関数がすべて削除されています。
-
src/pkg/syscall/syscall_unix.go
:- 既存の
GetsockoptInt
関数が削除され、新しい形式で再追加されています。 syscall_bsd.go
とsyscall_linux.go
から削除されたすべてのGetsockopt*
関数(GetsockoptByte
,GetsockoptInet4Addr
,GetsockoptIPMreq
,GetsockoptIPv6Mreq
,GetsockoptIPv6MTUInfo
,GetsockoptICMPv6Filter
)が、新しい簡素化された戻り値の型で追加されています。- 既存の
Setsockopt*
関数群(SetsockoptByte
,SetsockoptInt
,SetsockoptInet4Addr
,SetsockoptIPMreq
,SetsockoptIPv6Mreq
,SetsockoptICMPv6Filter
,SetsockoptLinger
,SetsockoptString
,SetsockoptTimeval
)の戻り値の型が(err error)
からerror
へと変更されています。
- 既存の
コアとなるコードの解説
ここでは、変更されたコードの具体的な例を挙げて、その意味を解説します。
Getsockopt*
関数の統合と戻り値の簡素化
syscall_bsd.go
および syscall_linux.go
から削除され、syscall_unix.go
に統合された GetsockoptByte
関数を例に取ります。
変更前(syscall_bsd.go
または syscall_linux.go
に存在):
func GetsockoptByte(fd, level, opt int) (value byte, err error) {
var n byte
vallen := _Socklen(1)
err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)
return n, err
}
このコードでは、value byte, err error
という名前付き戻り値が宣言されており、関数内で n
という変数に結果を格納し、最後に return n, err
で返しています。
変更後(syscall_unix.go
に存在):
func GetsockoptByte(fd, level, opt int) (byte, error) {
var v byte
l := _Socklen(1)
err := getsockopt(fd, level, opt, unsafe.Pointer(&v), &l)
return v, err
}
変更後では、戻り値の型が (byte, error)
と直接指定されています。関数内で v
という変数を宣言し、そこに結果を格納した後、return v, err
で返します。この形式は、Go言語の関数で複数の戻り値を返す際の一般的な慣習であり、コードがより簡潔で読みやすくなります。value
や n
といった一時的な変数名を明示的に戻り値として宣言する必要がなくなります。
同様に、GetsockoptInt
も変更されています。
変更前(syscall_unix.go
に存在):
func GetsockoptInt(fd, level, opt int) (value int, err error) {
var n int32
vallen := _Socklen(4)
err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)
return int(n), err
}
変更後(syscall_unix.go
に存在):
func GetsockoptInt(fd, level, opt int) (int, error) {
var v int32
l := _Socklen(4)
err := getsockopt(fd, level, opt, unsafe.Pointer(&v), &l)
return int(v), err
}
ここでも、value int, err error
から (int, error)
への変更と、内部変数名の変更が行われています。
Setsockopt*
関数の戻り値の簡素化
Setsockopt*
関数も同様に、戻り値の型が簡素化されています。
変更前(例: SetsockoptByte
):
func SetsockoptByte(fd, level, opt int, value byte) (err error) {
return setsockopt(fd, level, opt, unsafe.Pointer(&value), 1)
}
この関数は、err error
という名前付き戻り値を宣言していますが、関数本体では直接 setsockopt
の結果を返しています。
変更後(例: SetsockoptByte
):
func SetsockoptByte(fd, level, opt int, value byte) error {
return setsockopt(fd, level, opt, unsafe.Pointer(&value), 1)
}
変更後では、戻り値の型が error
と直接指定されています。これにより、関数シグネチャがより簡潔になり、Goの慣習に沿った記述となります。
これらの変更は、機能的な振る舞いを変更するものではなく、主にコードの構造とAPIの表現を改善することを目的としています。これにより、syscall
パッケージのソケットオプション関連コードがより整理され、Go言語のスタイルガイドラインに沿ったものになっています。
関連リンク
-
Go Code Review (Gerrit) リンク: このコミットの元のコードレビューページです。変更の議論や承認プロセスに関する詳細が含まれています。 https://golang.org/cl/107280044
-
Go Issue #7174: このコミットで更新されたとされるIssueの一つですが、現在のGoのIssueトラッカーでは直接参照できませんでした。
-
Go Issue #7175: このコミットで更新されたとされるIssueの一つですが、現在のGoのIssueトラッカーでは直接参照できませんでした。
参考にした情報源リンク
-
Go言語公式ドキュメント: Go言語の基本的な構文や標準ライブラリに関する公式情報源です。 https://go.dev/
-
Go
syscall
パッケージ ドキュメント:syscall
パッケージのAPIリファレンスです。 https://pkg.go.dev/syscall -
getsockopt
およびsetsockopt
man ページ: Unix系システムにおけるgetsockopt
およびsetsockopt
システムコールの詳細な説明です。 例:man 2 getsockopt
(Linuxの場合) -
Goの
unsafe
パッケージ ドキュメント:unsafe
パッケージの利用に関する公式ドキュメントです。 https://pkg.go.dev/unsafe