I think the key thing missing from go slices is ownership information, especially around sub-slices.
Make it so you can create copy-on-write slices of a larger slice, and a huge number of bugs go away.
Or do what rust did, except at runtime, and keep track of ownership
s := []int{1, 2, 3}
s[0] = 0 // fine, s owns data
s1 := s[0:2] // ownership transferred to s1, s is now read-only
s1[0] = 1 // fine, s1 owns data
s[0] = 1 // panic or compiler error, s1 owns data, not s
With of course functions to allow multiple mutable ownership in cases where that's needed, but it shouldn't be the default