This function's objective is very simple. It takes array and checks if val is a value inside of this array. It returns whether val exists and which is the index inside the array that contains val.

Could this be coded in a better way? How would I implement this to work with any kind of array (the code below works only with arrays of strings)?

package main

import "fmt"

func in_array(val string, array []string) (exists bool, index int) {
    exists = false
    index = -1;

    for i, v := range array {
        if val == v {
            index = i
            exists = true
            return
        }   
    }

    return
}

func main() {
    names := []string{ "Mary", "Anna", "Beth", "Johnny", "Beth" }

    fmt.Println( in_array("Jack", names) )
}

Go probably provides a similar function, but this is for study purposes only.

  • 1
    Some stylistic advice not related to the question: don't use snake_case, use camelCase. And switch the return parameters around, ok bool and err error are usually the second parameter. See e.g. val, exists := mymap[key]. – Arne Aug 21 '14 at 14:02
up vote 8 down vote accepted

Rather than tie yourself to only one type (string), you could use the reflect package as well as interfaces to make it somewhat type indifferent. The following is my reworking of your code:

package main

import "fmt"
import "reflect"

func in_array(val interface{}, array interface{}) (exists bool, index int) {
    exists = false
    index = -1

    switch reflect.TypeOf(array).Kind() {
    case reflect.Slice:
        s := reflect.ValueOf(array)

        for i := 0; i < s.Len(); i++ {
            if reflect.DeepEqual(val, s.Index(i).Interface()) == true {
                index = i
                exists = true
                return
            }
        }
    }

    return
}

Note that we now import the reflect package. We also changed the types of val and array to interface{} so that we may pass any type in. We then use the reflect.Typeof() to glean the reflection reflect.Type of the value in the array interface{}. We then glean the type with Kind(), and use a case to fall into our inner code if its a slice (can add more cases to extend this).

In our inner code, we get the value of the array argument, and store it in s. We then iterate over the length of s, and compare val to s at the index i declared as an interface with Interface() and check for truthiness. If its true, we exit with a true and the index.

Running the main function with both a slice of strings and a slice of integers, as follows, works:

func main() {
    names := []string{"Mary", "Anna", "Beth", "Johnny", "Beth"}
    fmt.Println(in_array("Anna", names))
    fmt.Println(in_array("Jon", names))

    ints := []int{1, 4, 3, 2, 6}
    fmt.Println(in_array(3, ints))
    fmt.Println(in_array(95, ints))
}

The above example gets us:

true 1
false -1
true 2
false -1
  • Few things to point out. 1. boolean's zero value is false, so you don't need to set exits. 2. you don't need the == true part in the check. 3. using reflect for that simple task is an extremely slow overkill way of doing it. – OneOfOne Aug 18 '14 at 0:17
  • 1
    Points 1 and 2 are good calls. Point three however ignores OP's question "How would I implement this to work with any kind of array?" - you need reflection for that. – jsanc623 Aug 18 '14 at 3:16

Using reflection for that simple task is a slow and an inefficient way of doing it, your first approach was fine, you could trim it a little, for example:

func in_array(val string, array []string) (ok bool, i int) {
    for i = range array {
        if ok = array[i] == val; ok {
            return
        }
    }
    return
}

Generic version using interfaces:

func in_array(v interface{}, in interface{}) (ok bool, i int) {
    val := reflect.Indirect(reflect.ValueOf(in))
    switch val.Kind() {
    case reflect.Slice, reflect.Array:
        for ; i < val.Len(); i++ {
            if ok = v == val.Index(i).Interface(); ok {
                return
            }
        }
    }
    return
}

playground

  • Advising not to use reflection ignores OP's question "How would I implement this to work with any kind of array?" - you need reflection for that. – jsanc623 Aug 18 '14 at 3:16
  • @jsanc623 I completely missed that. – OneOfOne Aug 18 '14 at 3:25
  • 1
    Your use of 'v' and 'in' is rather disconcerting as the next programmer to come along to your code cannot instantly discern what those values are. Code should be self documenting, and as such, variables should be descriptive. – jsanc623 Aug 18 '14 at 5:17

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.