Go中具有递归的len函数

I'm trying to build simple function to count elements in slice (like len) It must be simple (without additional libs) and with recursion. The problem is when i try to check is slice is empty (is nul).

package main
import "fmt"

func main() {
  x := []int{1, 2, 3}
  fmt.Println(len2(x))
}
func len2(s []int) int {
  if s == nil {
    return 0
  }
  return 1 + len2(s[1:])
}

the result it should be in this example '3'.

It's broken in if s == nil:

panic: runtime error: slice bounds out of range

The following is not a solution with better performance than len but an implementation that does not use any extra libraries and depends on recursion to find length

func len2(s []int) (count int) {
    defer func() {
        if r := recover(); r != nil {
            count = 0
        }
    }()

    return 1 + len2(s[1:])
}

Here is sample code

package main

import "fmt"

func main() {
    var x []int = nil
    var x1 = []int{1, 2, 3, 4}
    var x2 = []int{}
    var x3 = make([]int, 10, 20)
    fmt.Println(len2(x))
    fmt.Println(len2(x1))
    fmt.Println(len2(x2))
    fmt.Println(len2(x3))
}

func len2(s []int) (count int) {
    defer func() {
        if r := recover(); r != nil {
            count = 0
        }
    }()

    return 1 + len2(s[1:])
}

Checkout the same in playground

It panics because you have no valid termination condition.

When your len2() is called with a non-nil empty slice, it attempts to slice it like s[1:], which will be a runtime panic.

Instead of checking for nil slice, check if the slice is empty by comparing its length to 0:

func len2(s []int) int {
    if len(s) == 0 {
        return 0
    }
    return 1 + len2(s[1:])
}

Try it on the Go Playground.

If you can't use the builtin len() function (which you already did in your solution), you may use the for ... range:

func len2(s []int) int {
    size := 0
    for i := range s {
        size = i + 1
    }
    return size
}

Try this on the Go Playground.

And if it must be recursive, then for example:

func len2(s []int) int {
    size := 0
    for range s {
        size = 1 + len2(s[1:])
        break
    }
    return size
}

Try this on the Go Playground.

But know that these are awful solutions compared to using the builtin len().

If you do not want to use len() func, you can use cap()

func main() {
  x := []int{1, 2, 3}
  fmt.Println(len2(x))
}

func len2(s []int) int {

 if cap(s) == 0 {
    return 0
 }

  return 1 + len2(s[1:])
}

Try it again

Original Answer:

In order to check if an array (slice) is empty, you should use the function len()

  if len(s) == 0 {
    return 0
  }

Try it

If you can leave without recursion here is a function that does not use len() and should be faster then re-slicing recursively.

func len2(s []int) (count int) {
  for i := range s {
    count = i + 1
  }
}