Go公式WikiのRationalesの日本語意訳になります。
(元記事の最終更新日: 2017/01/26 rev.2)
一部の言語仕様の決定の根拠について載っています。
根拠
はじめに
この記事はGo FAQやEffective Goにあるものの他に、いくつかの重要な言語仕様の決定について、その背景にある論理的根拠ついて記載しています。
言語機能
なぜメソッドのレシーバの基本型は、ポインタやインターフェースにできないのか
Goは曖昧性の排除のために、レシーバの基本型としてポインタ型を使えません。
以下のようなコードがあった場合、
type T blah
type P *T
func (t *T) String() string { ... }
func (p P) String() string { ... }
var p P
// 訳注: このコードは `invalid receiver type P (P is a pointer type)` となり、コンパイルエラーになります.
訳注: Go PlayGroundで確認
(*p).String()
という式の意味があいまいになります。
(*T).String
と P.String
の両方を参照する可能性があるからです。
レシーバの基本型としてインターフェースを使えません。
インターフェースには既にメソッドがあるからです。(TODO)
閉じられたチャネルへのselect
(以下、やりとりの抜粋)
質問
以下のプログラムはパニックになります。
package main
import (
"fmt"
)
func main() {
c := make(chan int, 10)
close(c)
d := make(chan int, 10)
for i := 0; i < 10; i++ {
fmt.Println(i)
select {
case c <- 0:
case d <- 0:
}
}
fmt.Println("OK")
}
訳注: Go PlayGroundで確認
c
は閉じられているのにselectが可能だからです。これは仕様と一致していますが、個人的にはこの仕様は変えるべきだと思います。
回答
チャネルを閉じることは、送信者から受信者へのもう送信しないという送信のような通信です。もしその後に送信者がこのチャネルへと送信しようとした場合、チャネルを閉じたゴルーチンは明らかに混乱します。select処理だろうと通常の操作の一部だろうとパニックに値します。
チャネルのクローズが(通常の送信と同じく)送信者から受信者への通信という事実は、その動作の基本事項です。人々はよくクローズを受信者から送信者へ「もう自分に送信しないでくれ」と言う逆信号として使いたがります。しかしそれはクローズが本来意味するものとは違います。それはチャネルの単方向性を壊してしまうでしょう。これをしたがる人々の少なくとも10回のうち9回は、このようなキャンセルの仕組みの暗黙的な意味を完全には考えていません。ほとんどの場合において、キャンセルには2つのステップが必要です。キャンセルのリクエストと、そして動作が実際に停止したことの確認です。クローズは後者として役に立ちます。両方の役割を行うことはできませんし、私たちは人々が間違ってやってしまうのを可能な限り難しくしています。
クローズが送信者から受信者への通信であって逆側の通信ではないというこの主張は、受信専用チャネルを閉じることができないという理由にもなっています。
このイシュー報告はクローズしたチャネルのパニックについて、通常の送信ではなくselect時のみの例外を作ることを提案しているようです。
Go1では、私たちは積極的にXに対する全ての通信操作に対して、 select { case X: } を通常のXに近づけるように努めました。私はそれを簡単に壊すことはしないでしょう。(唯一の例外は Y = <-Z の場合の評価の順番です。 selectではZが最初に評価されます。http://play.golang.org/p/HppmwsO0QO を参照してください。)
とにかく、これらが今日のGoがこうなっている理由です。変更する理由はなんですか?
それらは最初のイシュー報告から著しく欠落しています。
閉じられたチャネルへの送信
(以下、やりとりの抜粋)
質問
閉じられたチャネルへの値送信はパニックになり、チャネルへの値送信は非ブロック操作とみなされます。この2つの事実はselect機構の利用の可能性の制限を結びつけます。だからチャネルに値を送信するための特別な構文を提案します。
aChannel <-| value
この構文を使って閉じられたチャネルに値を送信すると、パニックは発生せずに現在のゴルーチンがブロックされます。言い換えると、この構文での閉じられたチャネルへの値送信はブロック操作とみなされます。これにより、select機構の利用のさらなる可能性が作られます。
おそらくもう一つ追加するのも良いよ思います。
aChannel <-? value
この構文を使用して閉じられたチャネルへとあたいを送信すると、現在のゴルーチンをパニックもブロックもしません。つまり、この構文での閉じられたチャネルへの値送信は何もしません。
回答
いえ、これはチャネルの単方向性を破壊します。 私の#11344の回答を引用します。
(以下、上の回答と同じ)
メモリモデル
(記述なし)
標準ライブラリ
(記述なし)
comments powered by Disqus