For example, is there a reason I shouldn't be allowed to do the
following?
Yes, there is. [4]int is just a flat sequence of four integers. When you pass it to the function, they are copied, so modifications inside a function won't affect original value. The following code prints 1 2 3 4 both times.
func change(arr [4]int) {
arr[1] = 100
}
func prn(arr [4]int) {
for _, v := range arr {
print(v, " ")
}
println()
}
func main() {
x := [4]int{1, 2, 3, 4}
prn(x)
change(x)
prn(x)
}
However, a slice is a pointer to an array of some size (called capacity of the slice) and a length - two pointer-sized numbers. When you pass a slice to a function, you essentially pass a reference to the underlying array, so you can change it inside the function. The following program prints 1 2 3 4 and then 1 100 3 4:
func change(arr []int) {
arr[1] = 100
}
func prn(arr []int) {
for _, v := range arr {
print(v, " ")
}
println()
}
func main() {
x := []int{1, 2, 3, 4}
prn(x)
change(x)
prn(x)
}
So, in fact, internal representation of slices and arrays are different, and one cannot be used instead of another and vice versa. You have to copy slice contents to another array.
Of course, there are no technical difficulties which prevent Go from doing such conversion automatically (create an array implicitly and copy slice contents to it and pass it to the function). However, Go language designers made deliberate decision to abstain from implicit conversions as much as possible. If you really need this operation, you can do it yourself, it is not that hard.