Go “panic: runtime error: index out of range” when the length of array is not null
Asked Answered
E

4

9

I am having a hard time learning how to loop through a string in Go to do some stuff (specifically, to separate words than contain vowels).

I wrote this code snippet: https://play.golang.org/p/zgDtOyq6qf.

Here is the error I’m getting when running it:

panic: runtime error: index out of range

goroutine 1 [running]:
panic(0x1045a0, 0x1040a010)
    /usr/local/go/src/runtime/panic.go:500 +0x720
main.myFunc(0x114130, 0x4, 0x0, 0x0, 0x0, 0x3ba3)
    /tmp/sandbox960520145/main.go:19 +0x1a0
main.main()
    /tmp/sandbox960520145/main.go:10 +0x40

I searched in this forum, and someone said that it’s due to the length of the array, but it’s not the case here. I cannot figure out how to solve this issue. Can someone please suggest something?

Exeunt answered 24/8, 2016 at 9:5 Comment(0)
C
3

The issue is that you are creating a slice with length 0, but with a maximum capacity of 4, but at the same time you are trying to allocate already a value to the zeroth index of the slice created, which is normally empty. This is why you are receiving the index out of range error.

result := make([]string, 0, 4)
fmt.Println(len(result)) //panic: runtime error: index out of range

You can change this code with:

result := make([]string, 4)

which means the capacity will be the same length as the slice length.

fmt.Println(cap(result)) // 4
fmt.Println(len(result)) // 4

You can read about arrays, slices and maps here: https://blog.golang.org/go-slices-usage-and-internals

Carey answered 24/8, 2016 at 9:42 Comment(1)
Thanks for the aswer! Didn't know about slicesExeunt
M
18

First let's explain:

result := make([]string, 0, 4)

The make built-in function allocates and initializes an object of type []string call it Slice of string

Slice internals:

A slice is a descriptor of an array segment. It consists of a pointer to the array, the length of the segment, and its capacity (the maximum length of the segment).

So result := make([]string, 0, 4) allocates and initializes an object of type []string with length = 0 and capacity = 4.
And result := make([]string, 4, 4) allocates and initializes an object of type []string with length = 4 and capacity = 4, which is equal to result := make([]string, 4).

Now what is the difference between result := make([]string, 0, 4) and result := make([]string, 4):

With result := make([]string, 0, 4) the underlying array of this Slice is empty meaning using result[0] will panic: runtime error: index out of range.

With result := make([]string, 4) the underlying array of this Slice has 4 string elements, meaning using result[0], result[1], result[2], result[3] is OK:

package main

import "fmt"

func main() {
    result := make([]string, 4)
    fmt.Printf("%q, %q, %q, %q \n", result[0], result[1], result[2], result[3])
}

output:

"", "", "", "" 

And result := make([]string, 4) is equal to result := []string{"", "", "", ""} meaning this code:

package main

import "fmt"

func main() {
    result := []string{"", "", "", ""}
    fmt.Printf("%q, %q, %q, %q \n", result[0], result[1], result[2], result[3])
}

output is the same as above code:

"", "", "", "" 

The append built-in function appends elements to the end of a slice. If it has sufficient capacity, the destination is resliced to accommodate the new elements. If it does not, a new underlying array will be allocated. Append returns the updated slice. It is therefore necessary to store the result of append, often in the variable holding the slice itself:

slice = append(slice, elem1, elem2)
slice = append(slice, anotherSlice...)

As a special case, it is legal to append a string to a byte slice, like this:

slice = append([]byte("hello "), "world"...)

Now in your code inside function myFunc after result := make([]string, 0, 4), you may use append, like this working code (The Go Playground):

package main

import (
    "fmt"
    "strings"
)

func main() {
    strs := strings.Fields("Political srt")
    fmt.Println(len(strs)) // It's not empty so why index out of range
    fmt.Println(strs, strs[0], strs[1])
    fmt.Println(strings.ContainsAny(strs[0], "eaiuo"))
    fmt.Println(myFunc("Political srt"))
}

func myFunc(input string) []string {
    strs := strings.Fields(input)
    result := make([]string, 0, 4)
    for i := 0; i < len(strs); i++ {
        if strings.ContainsAny(strs[i], "eaiu") {
            result = append(result, strs[i])
        } else {
            result = append(result, strs[i])
        }
    }
    return result
}

You may simplify that code, like this working code (The Go Playground):

package main

import (
    "fmt"
    "strings"
)

func main() {
    fmt.Println(myFunc("Political srt"))
}

func myFunc(input string) []string {
    strs := strings.Fields(input)
    result := make([]string, 0, 4)
    for _, s := range strs {
        if strings.ContainsAny(s, "eaiu") {
            result = append(result, s)
        }
    }
    return result
}
Matronage answered 24/8, 2016 at 10:55 Comment(2)
@Exeunt I hope this helps.Matronage
Thank you for your answer and the clarification about append. I think it's more useful in my case to do it without the append as I want to do some ordering using the same array rather than just adding at the end of the array.Exeunt
C
3

The issue is that you are creating a slice with length 0, but with a maximum capacity of 4, but at the same time you are trying to allocate already a value to the zeroth index of the slice created, which is normally empty. This is why you are receiving the index out of range error.

result := make([]string, 0, 4)
fmt.Println(len(result)) //panic: runtime error: index out of range

You can change this code with:

result := make([]string, 4)

which means the capacity will be the same length as the slice length.

fmt.Println(cap(result)) // 4
fmt.Println(len(result)) // 4

You can read about arrays, slices and maps here: https://blog.golang.org/go-slices-usage-and-internals

Carey answered 24/8, 2016 at 9:42 Comment(1)
Thanks for the aswer! Didn't know about slicesExeunt
P
1

Index out of range error is appearing because you are not initializing the result array with sufficient length.

In myFunc, you have:

result := make([]string, 0, 4)

This creates a slice of strings which has an underlying array of length 4, but since you have declared slice length to be 0, none of the elements from underlying array are accessible to the slice. So even result[0] is out of range of the available indices.

To fix this, simply supply a sufficiently large length parameter to make:

result := make([]string, 4, 4)

You can read more about how slices operate here.

Psychotherapy answered 24/8, 2016 at 9:10 Comment(1)
Thanks for the aswer!Exeunt
C
0

Solution First the source codes may be applied in wrote hardware device or configuration and solution is o manual configuration of environmental variables

nano ~/.bashrc

Enter the env variable for termux in huawei

export GOROOT=/data/data/com.termux/files/usr/local/go
export GOPATH=$HOME/go
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin
export GOROOT=$HOME/go
export GOPATH=$HOME/go_projects
export PATH=$PATH:$GOROOT/bin


source ~/.bashrc

Cyna answered 16/9 at 13:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.