Почему строка не может быть нулевой в Go?

Программа доступная на Game 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

Я понимаю "" - это "нулевое значение" для строк. Я не понимаю, почему я не могу назначить nil моему string.

Ответ 1

Простой ответ заключается в том, что nil не определено как допустимое значение для типа string в спецификации языка .

... но, возможно, вам нужен более длинный ответ?

nil - это нулевое значение для указателей, интерфейсов, каналов, срезов, карт и типов функций, и оно представляет собой неинициализированное состояние.

Рассмотрим следующие объявления переменных:

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

Кажется естественным, что все эти переменные имели бы значение, которое представляет собой неинициализированное состояние. a был объявлен как указатель, но на что он указывает, когда мы еще ничего не указали? nil является очевидным нулевым значением для этих типов.

Что касается каналов, срезов и карт, их нулевое значение nil по той простой причине, что их реализация такова, что они должны быть явно инициализированы до их использования. Это в основном по причинам производительности, все эти типы представлены внутри как более или менее сложные структуры данных, а их инициализация не является бесплатной.

Однако a string не требует инициализации, и кажется естественным, что значение по умолчанию для нулевой строковой переменной будет пустой строкой, "". Поэтому просто нет причин для nil быть допустимым строковым значением, и добавление его в спецификацию только сделает язык более сложным и гораздо более громоздким для работы.

Кроме того, что означает nil типа string? Пустая строка? У нас это уже есть. Неинициализированная строка? Нет такой вещи.

Ответ 2

В go string - тип данных, он не является указателем на такой массив, как C/С++. Таким образом, вы не можете присвоить его нулю.

Ответ 3

Aedolon сделал несколько хороших замечаний, но, если пойти дальше, строки в других языках представляют собой удобный способ представления массивов байтов в виде символов. Мы должны сделать это много, поэтому этот конкретный вариант использования массива получает большую языковую поддержку, чтобы упростить его использование. Однако, в основе дела, вы работаете с массивом, который часто может быть нулевым в языке, потому что это ссылочный тип. То есть строка на самом деле не равна нулю, указатель на массив равен нулю. Поскольку многие языки объединяют эти две вещи, программисты привыкли проверять, является ли строка нулевой, прежде чем использовать ее.

Иди не делает этого. Строка не может быть nil, потому что структура данных в go не позволяет этого. У вас может быть указатель на байтовый массив, содержащий символьные представления в go, равном нулю, но это не строка.