Соответствующие вопросы здесь https://stackoverflow.com/a/12965872/6421681.
На ходу вы можете сделать:
func numsInFactorial(n int) (nums []int) {
// `nums := make([]int)` is not needed
for i := 1; i <= n; i++ {
nums = append(nums, i)
}
return
}
Однако следующее не работает:
func mapWithOneKeyAndValue(k int, v int) (m map[int]int) {
m[k] = v
return
}
Выдается ошибка:
panic: assignment to entry in nil map
Вместо этого вы должны:
func mapWithOneKeyAndValue(k int, v int) map[int]int {
m := make(map[int]int)
m[k] = v
return
}
Я не могу найти документацию для этого поведения.Я прочитал все эффективные ходы, и там тоже нет упоминаний об этом.
Я знаю, что именованные возвращаемые значения определены (т. Е. Выделена память; близко к тому, что делает new
), но не инициализированы (поэтому поведение make
не реплицируется).
После некоторых экспериментов, я считаю, что это поведение может быть сведено к пониманию поведения следующего кода:
func main() {
var s []int // len and cap are both 0
var m map[int]int
fmt.Println(s) // works... prints an empty slice
fmt.Println(m) // works... prints an empty map
s = append(s, 10) // returns a new slice, so underlying array gets allocated
fmt.Println(s) // works... prints [10]
m[10] = 10 // program crashes, with "assignment to entry in nil map"
fmt.Println(m)
}
Кажется, что проблема append
вызывает make
и выделяет обнаружение нового срезачто емкость s
составляет 0
.Однако map
никогда не получает явную инициализацию.
Причина этого СО вопроса состоит из двух частей.Во-первых, я хотел бы документировать поведение на SO.Во-вторых, почему язык допускает неинициализирующие определения slice
и map
?С моим опытом работы с этим языком кажется прагматичным (т. Е. Неиспользуемые переменные приводят к сбою компиляции, gofmt вызывает правильное форматирование), поэтому имеет смысл предотвратить компиляцию кода.