web-dev-qa-db-ja.com

Goで文字列をnilにできないのはなぜですか?

プログラム Go Playgroundで利用可能 読み取り

package main

import "fmt"

func main() {
    var name string = nil
    fmt.Println(name)
}

エラーが発生します

prog.go:6: cannot use nil as type string in assignment

わかります - ""は文字列の「ゼロ値」 です。 nilstringに割り当てることができない理由がわかりません。

22
user319286

単純な答えは、 言語仕様nilstring型の有効な値として定義されていないことです。

...しかし、あなたはもっと長い答えが欲しいですか?

nilは、ポインター、インターフェース、チャネル、スライス、マップ、および関数タイプのゼロ値であり、未初期化状態を表します。

次の変数宣言を検討してください。

var a *SomeType
var b interface{}
var c func()

これらの変数はすべて、初期化されていない状態を表す値を持つことは当然のことです。 aはポインターとして宣言されていますが、まだ何も指し示していない場合、何を指し示しますか? nilは、これらのタイプの明らかなゼロ値です。

チャネル、スライス、マップについては、実装を使用してから明示的に初期化する必要があるという単純な理由により、ゼロ値はnilです。これは主にパフォーマンス上の理由によるものであり、これらの型はすべて内部的に多少複雑なデータ構造として表されており、初期化は無料ではありません。

ただし、stringは初期化を必要とせず、新しい文字列変数のデフォルトのゼロ値は空の文字列""。したがって、nilが有効な文字列値である理由はまったくありません。仕様に追加すると、言語がより複雑になり、扱いにくくなります。

さらに、タイプnilstringrepresentとは何でしょうか?空の文字列?すでにそれがあります。初期化されていない文字列?そのようなことはありません。

35
Aedolon

Go stringはデータ型であり、C/C++のような配列へのポインタではありません。そのため、nilに割り当てることはできません。

4
GarMan

Aedolonはいくつかの良い点を示しましたが、さらに先へ進むと、他の言語では文字列はバイトの配列を文字として表現する便利な方法です。これを何度も行う必要があるため、配列のこの特定のユースケースは、使いやすくするために多くの言語サポートを取得します。ただし、問題の核心であるのは、配列を操作することです。配列は、参照型であるため、多くの場合、言語でnullになる可能性があります。つまり、文字列は実際にはヌルではなく、配列へのポインターはヌルです。多くの言語はこれら2つのことを融合しているため、プログラマーは使用する前に文字列がnullかどうかをチェックする必要があります。

Goはこれを行いません。 goのデータ構造では許可されていないため、文字列をnilにすることはできません。文字表現を保持するバイト配列へのポインタをgo nullにできますが、それは文字列ではありません。

0
Roger Hill